From: Christof Schmitt <christof.schmitt@xxxxxxxxxx> fc_bsg_goose_queue is only called from fc_remote_port_add which already requires to be run from thread context. For this case simply replace fc_bsg_goose_queue with a call to blk_run_queue. The code in scsi_run_queue needs a mechanism to avoid recursing through scsi_run_queue->blk_run_queue->scsi_request_fn->scsi_dispatch_cmd ->scsi_queue_insert->scsi_run_queue for each entry in the starved_list. Instead of using QUEUE_FLAG_PLUGGED, always defer running the queue for starved devices to the block layer workqueue. Signed-off-by: Christof Schmitt <christof.schmitt@xxxxxxxxxx> --- drivers/scsi/scsi_lib.c | 17 +++-------------- drivers/scsi/scsi_transport_fc.c | 34 ++-------------------------------- 2 files changed, 5 insertions(+), 46 deletions(-) --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -411,8 +411,6 @@ static void scsi_run_queue(struct reques list_splice_init(&shost->starved_list, &starved_list); while (!list_empty(&starved_list)) { - int flagset; - /* * As long as shost is accepting commands and we have * starved queues, call blk_run_queue. scsi_request_fn @@ -435,20 +433,11 @@ static void scsi_run_queue(struct reques continue; } - spin_unlock(shost->host_lock); - spin_lock(sdev->request_queue->queue_lock); - flagset = test_bit(QUEUE_FLAG_REENTER, &q->queue_flags) && - !test_bit(QUEUE_FLAG_REENTER, - &sdev->request_queue->queue_flags); - if (flagset) - queue_flag_set(QUEUE_FLAG_REENTER, sdev->request_queue); - __blk_run_queue(sdev->request_queue); - if (flagset) - queue_flag_clear(QUEUE_FLAG_REENTER, sdev->request_queue); + queue_flag_set(QUEUE_FLAG_PLUGGED, sdev->request_queue); + kblockd_schedule_work(sdev->request_queue, + &sdev->request_queue->unplug_work); spin_unlock(sdev->request_queue->queue_lock); - - spin_lock(shost->host_lock); } /* put any unprocessed entries back */ list_splice(&starved_list, &shost->starved_list); --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -50,7 +50,6 @@ static int fc_vport_setup(struct Scsi_Ho static int fc_bsg_hostadd(struct Scsi_Host *, struct fc_host_attrs *); static int fc_bsg_rportadd(struct Scsi_Host *, struct fc_rport *); static void fc_bsg_remove(struct request_queue *); -static void fc_bsg_goose_queue(struct fc_rport *); /* * Redefine so that we can have same named attributes in the @@ -2737,7 +2736,8 @@ fc_remote_port_add(struct Scsi_Host *sho spin_unlock_irqrestore(shost->host_lock, flags); - fc_bsg_goose_queue(rport); + if (rport->rqst_q) + blk_run_queue(rport->rqst_q); return rport; } @@ -3752,36 +3752,6 @@ fail_host_msg: return FC_DISPATCH_UNLOCKED; } - -/* - * fc_bsg_goose_queue - restart rport queue in case it was stopped - * @rport: rport to be restarted - */ -static void -fc_bsg_goose_queue(struct fc_rport *rport) -{ - int flagset; - unsigned long flags; - - if (!rport->rqst_q) - return; - - get_device(&rport->dev); - - spin_lock_irqsave(rport->rqst_q->queue_lock, flags); - flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) && - !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags); - if (flagset) - queue_flag_set(QUEUE_FLAG_REENTER, rport->rqst_q); - __blk_run_queue(rport->rqst_q); - if (flagset) - queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q); - spin_unlock_irqrestore(rport->rqst_q->queue_lock, flags); - - put_device(&rport->dev); -} - - /** * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD * @q: rport request queue -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html