···6969#include "scsi_logging.h"70707171static void scsi_done(struct scsi_cmnd *cmd);7272-static int scsi_retry_command(struct scsi_cmnd *cmd);73727473/*7574 * Definitions and constants.···751752 * isn't running --- used by scsi_times_out */752753void __scsi_done(struct scsi_cmnd *cmd)753754{754754- unsigned long flags;755755+ struct request *rq = cmd->request;755756756757 /*757758 * Set the serial numbers back to zero···762763 if (cmd->result)763764 atomic_inc(&cmd->device->ioerr_cnt);764765766766+ BUG_ON(!rq);767767+765768 /*766766- * Next, enqueue the command into the done queue.767767- * It is a per-CPU queue, so we just disable local interrupts768768- * and need no spinlock.769769+ * The uptodate/nbytes values don't matter, as we allow partial770770+ * completes and thus will check this in the softirq callback769771 */770770- local_irq_save(flags);771771- list_add_tail(&cmd->eh_entry, &__get_cpu_var(scsi_done_q));772772- raise_softirq_irqoff(SCSI_SOFTIRQ);773773- local_irq_restore(flags);774774-}775775-776776-/**777777- * scsi_softirq - Perform post-interrupt processing of finished SCSI commands.778778- *779779- * This is the consumer of the done queue.780780- *781781- * This is called with all interrupts enabled. This should reduce782782- * interrupt latency, stack depth, and reentrancy of the low-level783783- * drivers.784784- */785785-static void scsi_softirq(struct softirq_action *h)786786-{787787- int disposition;788788- LIST_HEAD(local_q);789789-790790- local_irq_disable();791791- list_splice_init(&__get_cpu_var(scsi_done_q), &local_q);792792- local_irq_enable();793793-794794- while (!list_empty(&local_q)) {795795- struct scsi_cmnd *cmd = list_entry(local_q.next,796796- struct scsi_cmnd, eh_entry);797797- /* The longest time any command should be outstanding is the798798- * per command timeout multiplied by the number of retries.799799- *800800- * For a typical command, this is 2.5 minutes */801801- unsigned long wait_for 802802- = cmd->allowed * cmd->timeout_per_command;803803- list_del_init(&cmd->eh_entry);804804-805805- disposition = scsi_decide_disposition(cmd);806806- if (disposition != SUCCESS &&807807- time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {808808- sdev_printk(KERN_ERR, cmd->device,809809- "timing out command, waited %lus\n",810810- wait_for/HZ);811811- disposition = SUCCESS;812812- }813813-814814- scsi_log_completion(cmd, disposition);815815- switch (disposition) {816816- case SUCCESS:817817- scsi_finish_command(cmd);818818- break;819819- case NEEDS_RETRY:820820- scsi_retry_command(cmd);821821- break;822822- case ADD_TO_MLQUEUE:823823- scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);824824- break;825825- default:826826- if (!scsi_eh_scmd_add(cmd, 0))827827- scsi_finish_command(cmd);828828- }829829- }772772+ rq->completion_data = cmd;773773+ blk_complete_request(rq);830774}831775832776/*···782840 * level drivers should not become re-entrant as a result of783841 * this.784842 */785785-static int scsi_retry_command(struct scsi_cmnd *cmd)843843+int scsi_retry_command(struct scsi_cmnd *cmd)786844{787845 /*788846 * Restore the SCSI command state.···12151273}12161274EXPORT_SYMBOL(scsi_device_cancel);1217127512181218-#ifdef CONFIG_HOTPLUG_CPU12191219-static int scsi_cpu_notify(struct notifier_block *self,12201220- unsigned long action, void *hcpu)12211221-{12221222- int cpu = (unsigned long)hcpu;12231223-12241224- switch(action) {12251225- case CPU_DEAD:12261226- /* Drain scsi_done_q. */12271227- local_irq_disable();12281228- list_splice_init(&per_cpu(scsi_done_q, cpu),12291229- &__get_cpu_var(scsi_done_q));12301230- raise_softirq_irqoff(SCSI_SOFTIRQ);12311231- local_irq_enable();12321232- break;12331233- default:12341234- break;12351235- }12361236- return NOTIFY_OK;12371237-}12381238-12391239-static struct notifier_block __devinitdata scsi_cpu_nb = {12401240- .notifier_call = scsi_cpu_notify,12411241-};12421242-12431243-#define register_scsi_cpu() register_cpu_notifier(&scsi_cpu_nb)12441244-#define unregister_scsi_cpu() unregister_cpu_notifier(&scsi_cpu_nb)12451245-#else12461246-#define register_scsi_cpu()12471247-#define unregister_scsi_cpu()12481248-#endif /* CONFIG_HOTPLUG_CPU */12491249-12501276MODULE_DESCRIPTION("SCSI core");12511277MODULE_LICENSE("GPL");12521278···12481338 INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));1249133912501340 devfs_mk_dir("scsi");12511251- open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL);12521252- register_scsi_cpu();12531341 printk(KERN_NOTICE "SCSI subsystem initialized\n");12541342 return 0;12551343···12751367 devfs_remove("scsi");12761368 scsi_exit_procfs();12771369 scsi_exit_queue();12781278- unregister_scsi_cpu();12791370}1280137112811372subsys_initcall(init_scsi);
+36
drivers/scsi/scsi_lib.c
···14931493 __scsi_done(cmd);14941494}1495149514961496+static void scsi_softirq_done(struct request *rq)14971497+{14981498+ struct scsi_cmnd *cmd = rq->completion_data;14991499+ unsigned long wait_for = cmd->allowed * cmd->timeout_per_command;15001500+ int disposition;15011501+15021502+ INIT_LIST_HEAD(&cmd->eh_entry);15031503+15041504+ disposition = scsi_decide_disposition(cmd);15051505+ if (disposition != SUCCESS &&15061506+ time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {15071507+ sdev_printk(KERN_ERR, cmd->device,15081508+ "timing out command, waited %lus\n",15091509+ wait_for/HZ);15101510+ disposition = SUCCESS;15111511+ }15121512+15131513+ scsi_log_completion(cmd, disposition);15141514+15151515+ switch (disposition) {15161516+ case SUCCESS:15171517+ scsi_finish_command(cmd);15181518+ break;15191519+ case NEEDS_RETRY:15201520+ scsi_retry_command(cmd);15211521+ break;15221522+ case ADD_TO_MLQUEUE:15231523+ scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);15241524+ break;15251525+ default:15261526+ if (!scsi_eh_scmd_add(cmd, 0))15271527+ scsi_finish_command(cmd);15281528+ }15291529+}15301530+14961531/*14971532 * Function: scsi_request_fn()14981533 *···17021667 blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));17031668 blk_queue_segment_boundary(q, shost->dma_boundary);17041669 blk_queue_issue_flush_fn(q, scsi_issue_flush_fn);16701670+ blk_queue_softirq_done(q, scsi_softirq_done);1705167117061672 if (!shost->use_clustering)17071673 clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);