diff options
author | Finn Thain <fthain@telegraphics.com.au> | 2016-01-03 00:05:58 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2016-01-06 21:43:07 -0500 |
commit | 32b26a104237c1ba3575a6c8d47e46060cc416fb (patch) | |
tree | 436ad259aa17efdd392ee60a6a687efaa20ead13 | |
parent | 5299b3caf525c5a6cdebbe162733c8ff1692c4d0 (diff) |
ncr5380: Use standard list data structure
The NCR5380 drivers have a home-spun linked list implementation for
scsi_cmnd structs that uses cmd->host_scribble as a 'next' pointer. Adopt
the standard list_head data structure and list operations instead. Remove
the eh_abort_handler rather than convert it. Doing the conversion would
only be churn because the existing EH handlers don't work and get replaced
in a subsequent patch.
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Tested-by: Ondrej Zary <linux@rainbow-software.org>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/scsi/NCR5380.c | 214 | ||||
-rw-r--r-- | drivers/scsi/NCR5380.h | 16 | ||||
-rw-r--r-- | drivers/scsi/arm/cumana_1.c | 1 | ||||
-rw-r--r-- | drivers/scsi/arm/oak.c | 1 | ||||
-rw-r--r-- | drivers/scsi/atari_NCR5380.c | 287 | ||||
-rw-r--r-- | drivers/scsi/atari_scsi.c | 1 | ||||
-rw-r--r-- | drivers/scsi/dmx3191d.c | 1 | ||||
-rw-r--r-- | drivers/scsi/dtc.c | 1 | ||||
-rw-r--r-- | drivers/scsi/g_NCR5380.c | 1 | ||||
-rw-r--r-- | drivers/scsi/mac_scsi.c | 1 | ||||
-rw-r--r-- | drivers/scsi/pas16.c | 1 | ||||
-rw-r--r-- | drivers/scsi/sun3_scsi.c | 1 | ||||
-rw-r--r-- | drivers/scsi/t128.c | 1 |
13 files changed, 106 insertions, 421 deletions
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 9e8636300c8a..6b861fd3fbb1 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c | |||
@@ -622,8 +622,9 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) | |||
622 | #endif | 622 | #endif |
623 | spin_lock_init(&hostdata->lock); | 623 | spin_lock_init(&hostdata->lock); |
624 | hostdata->connected = NULL; | 624 | hostdata->connected = NULL; |
625 | hostdata->issue_queue = NULL; | 625 | INIT_LIST_HEAD(&hostdata->unissued); |
626 | hostdata->disconnected_queue = NULL; | 626 | INIT_LIST_HEAD(&hostdata->disconnected); |
627 | |||
627 | hostdata->flags = flags; | 628 | hostdata->flags = flags; |
628 | 629 | ||
629 | INIT_WORK(&hostdata->main_task, NCR5380_main); | 630 | INIT_WORK(&hostdata->main_task, NCR5380_main); |
@@ -738,7 +739,7 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, | |||
738 | struct scsi_cmnd *cmd) | 739 | struct scsi_cmnd *cmd) |
739 | { | 740 | { |
740 | struct NCR5380_hostdata *hostdata = shost_priv(instance); | 741 | struct NCR5380_hostdata *hostdata = shost_priv(instance); |
741 | struct scsi_cmnd *tmp; | 742 | struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); |
742 | unsigned long flags; | 743 | unsigned long flags; |
743 | 744 | ||
744 | #if (NDEBUG & NDEBUG_NO_WRITE) | 745 | #if (NDEBUG & NDEBUG_NO_WRITE) |
@@ -752,12 +753,6 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, | |||
752 | } | 753 | } |
753 | #endif /* (NDEBUG & NDEBUG_NO_WRITE) */ | 754 | #endif /* (NDEBUG & NDEBUG_NO_WRITE) */ |
754 | 755 | ||
755 | /* | ||
756 | * We use the host_scribble field as a pointer to the next command | ||
757 | * in a queue | ||
758 | */ | ||
759 | |||
760 | cmd->host_scribble = NULL; | ||
761 | cmd->result = 0; | 756 | cmd->result = 0; |
762 | 757 | ||
763 | spin_lock_irqsave(&hostdata->lock, flags); | 758 | spin_lock_irqsave(&hostdata->lock, flags); |
@@ -769,13 +764,11 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, | |||
769 | * sense data is only guaranteed to be valid while the condition exists. | 764 | * sense data is only guaranteed to be valid while the condition exists. |
770 | */ | 765 | */ |
771 | 766 | ||
772 | if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { | 767 | if (cmd->cmnd[0] == REQUEST_SENSE) |
773 | cmd->host_scribble = (unsigned char *) hostdata->issue_queue; | 768 | list_add(&ncmd->list, &hostdata->unissued); |
774 | hostdata->issue_queue = cmd; | 769 | else |
775 | } else { | 770 | list_add_tail(&ncmd->list, &hostdata->unissued); |
776 | for (tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp->host_scribble; tmp = (struct scsi_cmnd *) tmp->host_scribble); | 771 | |
777 | tmp->host_scribble = (unsigned char *) cmd; | ||
778 | } | ||
779 | spin_unlock_irqrestore(&hostdata->lock, flags); | 772 | spin_unlock_irqrestore(&hostdata->lock, flags); |
780 | 773 | ||
781 | dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n", | 774 | dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n", |
@@ -803,7 +796,7 @@ static void NCR5380_main(struct work_struct *work) | |||
803 | struct NCR5380_hostdata *hostdata = | 796 | struct NCR5380_hostdata *hostdata = |
804 | container_of(work, struct NCR5380_hostdata, main_task); | 797 | container_of(work, struct NCR5380_hostdata, main_task); |
805 | struct Scsi_Host *instance = hostdata->host; | 798 | struct Scsi_Host *instance = hostdata->host; |
806 | struct scsi_cmnd *tmp, *prev; | 799 | struct NCR5380_cmd *ncmd, *n; |
807 | int done; | 800 | int done; |
808 | 801 | ||
809 | spin_lock_irq(&hostdata->lock); | 802 | spin_lock_irq(&hostdata->lock); |
@@ -816,23 +809,20 @@ static void NCR5380_main(struct work_struct *work) | |||
816 | * Search through the issue_queue for a command destined | 809 | * Search through the issue_queue for a command destined |
817 | * for a target that's not busy. | 810 | * for a target that's not busy. |
818 | */ | 811 | */ |
819 | for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble) | 812 | list_for_each_entry_safe(ncmd, n, &hostdata->unissued, |
820 | { | 813 | list) { |
814 | struct scsi_cmnd *tmp = NCR5380_to_scmd(ncmd); | ||
815 | |||
821 | dsprintk(NDEBUG_QUEUES, instance, "main: tmp=%p target=%d busy=%d lun=%llu\n", | 816 | dsprintk(NDEBUG_QUEUES, instance, "main: tmp=%p target=%d busy=%d lun=%llu\n", |
822 | tmp, scmd_id(tmp), hostdata->busy[scmd_id(tmp)], | 817 | tmp, scmd_id(tmp), hostdata->busy[scmd_id(tmp)], |
823 | tmp->device->lun); | 818 | tmp->device->lun); |
824 | /* When we find one, remove it from the issue queue. */ | 819 | /* When we find one, remove it from the issue queue. */ |
825 | if (!(hostdata->busy[tmp->device->id] & | 820 | if (!(hostdata->busy[tmp->device->id] & |
826 | (1 << (u8)(tmp->device->lun & 0xff)))) { | 821 | (1 << (u8)(tmp->device->lun & 0xff)))) { |
827 | if (prev) { | 822 | list_del(&ncmd->list); |
828 | prev->host_scribble = tmp->host_scribble; | ||
829 | } else { | ||
830 | hostdata->issue_queue = (struct scsi_cmnd *) tmp->host_scribble; | ||
831 | } | ||
832 | tmp->host_scribble = NULL; | ||
833 | dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, | 823 | dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, |
834 | instance, "main: removed %p from issue queue %p\n", | 824 | instance, "main: removed %p from issue queue\n", |
835 | tmp, prev); | 825 | tmp); |
836 | 826 | ||
837 | /* | 827 | /* |
838 | * Attempt to establish an I_T_L nexus here. | 828 | * Attempt to establish an I_T_L nexus here. |
@@ -851,8 +841,7 @@ static void NCR5380_main(struct work_struct *work) | |||
851 | /* OK or bad target */ | 841 | /* OK or bad target */ |
852 | } else { | 842 | } else { |
853 | /* Need to retry */ | 843 | /* Need to retry */ |
854 | tmp->host_scribble = (unsigned char *) hostdata->issue_queue; | 844 | list_add(&ncmd->list, &hostdata->unissued); |
855 | hostdata->issue_queue = tmp; | ||
856 | dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, | 845 | dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, |
857 | instance, "main: select() failed, %p returned to issue queue\n", | 846 | instance, "main: select() failed, %p returned to issue queue\n", |
858 | tmp); | 847 | tmp); |
@@ -1744,6 +1733,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { | |||
1744 | struct scsi_cmnd *cmd; | 1733 | struct scsi_cmnd *cmd; |
1745 | 1734 | ||
1746 | while ((cmd = hostdata->connected)) { | 1735 | while ((cmd = hostdata->connected)) { |
1736 | struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); | ||
1737 | |||
1747 | tmp = NCR5380_read(STATUS_REG); | 1738 | tmp = NCR5380_read(STATUS_REG); |
1748 | /* We only have a valid SCSI phase when REQ is asserted */ | 1739 | /* We only have a valid SCSI phase when REQ is asserted */ |
1749 | if (tmp & SR_REQ) { | 1740 | if (tmp & SR_REQ) { |
@@ -1875,9 +1866,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { | |||
1875 | if ((cmd->cmnd[0] != REQUEST_SENSE) && (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { | 1866 | if ((cmd->cmnd[0] != REQUEST_SENSE) && (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { |
1876 | scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); | 1867 | scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); |
1877 | 1868 | ||
1878 | cmd->host_scribble = (unsigned char *) | 1869 | list_add(&ncmd->list, &hostdata->unissued); |
1879 | hostdata->issue_queue; | ||
1880 | hostdata->issue_queue = (struct scsi_cmnd *) cmd; | ||
1881 | dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, | 1870 | dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, |
1882 | instance, "REQUEST SENSE cmd %p added to head of issue queue\n", | 1871 | instance, "REQUEST SENSE cmd %p added to head of issue queue\n", |
1883 | cmd); | 1872 | cmd); |
@@ -1911,10 +1900,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { | |||
1911 | case DISCONNECT:{ | 1900 | case DISCONNECT:{ |
1912 | /* Accept message by clearing ACK */ | 1901 | /* Accept message by clearing ACK */ |
1913 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 1902 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
1914 | cmd->host_scribble = (unsigned char *) | ||
1915 | hostdata->disconnected_queue; | ||
1916 | hostdata->connected = NULL; | 1903 | hostdata->connected = NULL; |
1917 | hostdata->disconnected_queue = cmd; | 1904 | list_add(&ncmd->list, &hostdata->disconnected); |
1918 | dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES, | 1905 | dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES, |
1919 | instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", | 1906 | instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", |
1920 | cmd, scmd_id(cmd), cmd->device->lun); | 1907 | cmd, scmd_id(cmd), cmd->device->lun); |
@@ -2087,7 +2074,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { | |||
2087 | int len; | 2074 | int len; |
2088 | unsigned char msg[3]; | 2075 | unsigned char msg[3]; |
2089 | unsigned char *data; | 2076 | unsigned char *data; |
2090 | struct scsi_cmnd *tmp = NULL, *prev; | 2077 | struct NCR5380_cmd *ncmd; |
2078 | struct scsi_cmnd *tmp; | ||
2091 | 2079 | ||
2092 | /* | 2080 | /* |
2093 | * Disable arbitration, etc. since the host adapter obviously | 2081 | * Disable arbitration, etc. since the host adapter obviously |
@@ -2156,16 +2144,14 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { | |||
2156 | * just reestablished, and remove it from the disconnected queue. | 2144 | * just reestablished, and remove it from the disconnected queue. |
2157 | */ | 2145 | */ |
2158 | 2146 | ||
2159 | for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL; | 2147 | tmp = NULL; |
2160 | tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble) { | 2148 | list_for_each_entry(ncmd, &hostdata->disconnected, list) { |
2161 | if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun)) { | 2149 | struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); |
2162 | if (prev) { | 2150 | |
2163 | prev->host_scribble = tmp->host_scribble; | 2151 | if (target_mask == (1 << scmd_id(cmd)) && |
2164 | } else { | 2152 | lun == (u8)cmd->device->lun) { |
2165 | hostdata->disconnected_queue = | 2153 | list_del(&ncmd->list); |
2166 | (struct scsi_cmnd *) tmp->host_scribble; | 2154 | tmp = cmd; |
2167 | } | ||
2168 | tmp->host_scribble = NULL; | ||
2169 | break; | 2155 | break; |
2170 | } | 2156 | } |
2171 | } | 2157 | } |
@@ -2261,146 +2247,18 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) | |||
2261 | { | 2247 | { |
2262 | struct Scsi_Host *instance = cmd->device->host; | 2248 | struct Scsi_Host *instance = cmd->device->host; |
2263 | struct NCR5380_hostdata *hostdata = shost_priv(instance); | 2249 | struct NCR5380_hostdata *hostdata = shost_priv(instance); |
2264 | struct scsi_cmnd *tmp, **prev; | ||
2265 | unsigned long flags; | 2250 | unsigned long flags; |
2266 | 2251 | ||
2267 | scmd_printk(KERN_WARNING, cmd, "aborting command\n"); | ||
2268 | |||
2269 | spin_lock_irqsave(&hostdata->lock, flags); | 2252 | spin_lock_irqsave(&hostdata->lock, flags); |
2270 | 2253 | ||
2254 | #if (NDEBUG & NDEBUG_ANY) | ||
2255 | scmd_printk(KERN_INFO, cmd, "aborting command\n"); | ||
2256 | #endif | ||
2271 | NCR5380_dprint(NDEBUG_ANY, instance); | 2257 | NCR5380_dprint(NDEBUG_ANY, instance); |
2272 | NCR5380_dprint_phase(NDEBUG_ANY, instance); | 2258 | NCR5380_dprint_phase(NDEBUG_ANY, instance); |
2273 | 2259 | ||
2274 | dprintk(NDEBUG_ABORT, "scsi%d : abort called\n", instance->host_no); | ||
2275 | dprintk(NDEBUG_ABORT, " basr 0x%X, sr 0x%X\n", NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG)); | ||
2276 | |||
2277 | #if 0 | ||
2278 | /* | ||
2279 | * Case 1 : If the command is the currently executing command, | ||
2280 | * we'll set the aborted flag and return control so that | ||
2281 | * information transfer routine can exit cleanly. | ||
2282 | */ | ||
2283 | |||
2284 | if (hostdata->connected == cmd) { | ||
2285 | dprintk(NDEBUG_ABORT, "scsi%d : aborting connected command\n", instance->host_no); | ||
2286 | /* | ||
2287 | * We should perform BSY checking, and make sure we haven't slipped | ||
2288 | * into BUS FREE. | ||
2289 | */ | ||
2290 | |||
2291 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); | ||
2292 | /* | ||
2293 | * Since we can't change phases until we've completed the current | ||
2294 | * handshake, we have to source or sink a byte of data if the current | ||
2295 | * phase is not MSGOUT. | ||
2296 | */ | ||
2297 | |||
2298 | /* | ||
2299 | * Return control to the executing NCR drive so we can clear the | ||
2300 | * aborted flag and get back into our main loop. | ||
2301 | */ | ||
2302 | |||
2303 | return SUCCESS; | ||
2304 | } | ||
2305 | #endif | ||
2306 | |||
2307 | /* | ||
2308 | * Case 2 : If the command hasn't been issued yet, we simply remove it | ||
2309 | * from the issue queue. | ||
2310 | */ | ||
2311 | |||
2312 | dprintk(NDEBUG_ABORT, "scsi%d : abort going into loop.\n", instance->host_no); | ||
2313 | for (prev = (struct scsi_cmnd **) &(hostdata->issue_queue), tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp; prev = (struct scsi_cmnd **) &(tmp->host_scribble), tmp = (struct scsi_cmnd *) tmp->host_scribble) | ||
2314 | if (cmd == tmp) { | ||
2315 | (*prev) = (struct scsi_cmnd *) tmp->host_scribble; | ||
2316 | tmp->host_scribble = NULL; | ||
2317 | spin_unlock_irqrestore(&hostdata->lock, flags); | ||
2318 | tmp->result = DID_ABORT << 16; | ||
2319 | dprintk(NDEBUG_ABORT, "scsi%d : abort removed command from issue queue.\n", instance->host_no); | ||
2320 | tmp->scsi_done(tmp); | ||
2321 | return SUCCESS; | ||
2322 | } | ||
2323 | #if (NDEBUG & NDEBUG_ABORT) | ||
2324 | /* KLL */ | ||
2325 | else if (prev == tmp) | ||
2326 | printk(KERN_ERR "scsi%d : LOOP\n", instance->host_no); | ||
2327 | #endif | ||
2328 | |||
2329 | /* | ||
2330 | * Case 3 : If any commands are connected, we're going to fail the abort | ||
2331 | * and let the high level SCSI driver retry at a later time or | ||
2332 | * issue a reset. | ||
2333 | * | ||
2334 | * Timeouts, and therefore aborted commands, will be highly unlikely | ||
2335 | * and handling them cleanly in this situation would make the common | ||
2336 | * case of noresets less efficient, and would pollute our code. So, | ||
2337 | * we fail. | ||
2338 | */ | ||
2339 | |||
2340 | if (hostdata->connected) { | ||
2341 | spin_unlock_irqrestore(&hostdata->lock, flags); | ||
2342 | dprintk(NDEBUG_ABORT, "scsi%d : abort failed, command connected.\n", instance->host_no); | ||
2343 | return FAILED; | ||
2344 | } | ||
2345 | /* | ||
2346 | * Case 4: If the command is currently disconnected from the bus, and | ||
2347 | * there are no connected commands, we reconnect the I_T_L or | ||
2348 | * I_T_L_Q nexus associated with it, go into message out, and send | ||
2349 | * an abort message. | ||
2350 | * | ||
2351 | * This case is especially ugly. In order to reestablish the nexus, we | ||
2352 | * need to call NCR5380_select(). The easiest way to implement this | ||
2353 | * function was to abort if the bus was busy, and let the interrupt | ||
2354 | * handler triggered on the SEL for reselect take care of lost arbitrations | ||
2355 | * where necessary, meaning interrupts need to be enabled. | ||
2356 | * | ||
2357 | * When interrupts are enabled, the queues may change - so we | ||
2358 | * can't remove it from the disconnected queue before selecting it | ||
2359 | * because that could cause a failure in hashing the nexus if that | ||
2360 | * device reselected. | ||
2361 | * | ||
2362 | * Since the queues may change, we can't use the pointers from when we | ||
2363 | * first locate it. | ||
2364 | * | ||
2365 | * So, we must first locate the command, and if NCR5380_select() | ||
2366 | * succeeds, then issue the abort, relocate the command and remove | ||
2367 | * it from the disconnected queue. | ||
2368 | */ | ||
2369 | |||
2370 | for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; tmp = (struct scsi_cmnd *) tmp->host_scribble) | ||
2371 | if (cmd == tmp) { | ||
2372 | dprintk(NDEBUG_ABORT, "scsi%d : aborting disconnected command.\n", instance->host_no); | ||
2373 | |||
2374 | if (NCR5380_select(instance, cmd)) { | ||
2375 | spin_unlock_irq(&hostdata->lock); | ||
2376 | return FAILED; | ||
2377 | } | ||
2378 | dprintk(NDEBUG_ABORT, "scsi%d : nexus reestablished.\n", instance->host_no); | ||
2379 | |||
2380 | do_abort(instance); | ||
2381 | |||
2382 | for (prev = (struct scsi_cmnd **) &(hostdata->disconnected_queue), tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; prev = (struct scsi_cmnd **) &(tmp->host_scribble), tmp = (struct scsi_cmnd *) tmp->host_scribble) | ||
2383 | if (cmd == tmp) { | ||
2384 | *prev = (struct scsi_cmnd *) tmp->host_scribble; | ||
2385 | tmp->host_scribble = NULL; | ||
2386 | spin_unlock_irqrestore(&hostdata->lock, flags); | ||
2387 | tmp->result = DID_ABORT << 16; | ||
2388 | tmp->scsi_done(tmp); | ||
2389 | return SUCCESS; | ||
2390 | } | ||
2391 | } | ||
2392 | /* | ||
2393 | * Case 5 : If we reached this point, the command was not found in any of | ||
2394 | * the queues. | ||
2395 | * | ||
2396 | * We probably reached this point because of an unlikely race condition | ||
2397 | * between the command completing successfully and the abortion code, | ||
2398 | * so we won't panic, but we will notify the user in case something really | ||
2399 | * broke. | ||
2400 | */ | ||
2401 | spin_unlock_irqrestore(&hostdata->lock, flags); | 2260 | spin_unlock_irqrestore(&hostdata->lock, flags); |
2402 | printk(KERN_WARNING "scsi%d : warning : SCSI command probably completed successfully\n" | 2261 | |
2403 | " before abortion\n", instance->host_no); | ||
2404 | return FAILED; | 2262 | return FAILED; |
2405 | } | 2263 | } |
2406 | 2264 | ||
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 87c2f2104e68..56252a5516d7 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/list.h> | ||
27 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
28 | #include <scsi/scsi_dbg.h> | 29 | #include <scsi/scsi_dbg.h> |
29 | #include <scsi/scsi_eh.h> | 30 | #include <scsi/scsi_eh.h> |
@@ -254,8 +255,8 @@ struct NCR5380_hostdata { | |||
254 | #endif | 255 | #endif |
255 | unsigned char last_message; /* last message OUT */ | 256 | unsigned char last_message; /* last message OUT */ |
256 | struct scsi_cmnd *connected; /* currently connected cmnd */ | 257 | struct scsi_cmnd *connected; /* currently connected cmnd */ |
257 | struct scsi_cmnd *issue_queue; /* waiting to be issued */ | 258 | struct list_head unissued; /* waiting to be issued */ |
258 | struct scsi_cmnd *disconnected_queue; /* waiting for reconnect */ | 259 | struct list_head disconnected; /* waiting for reconnect */ |
259 | spinlock_t lock; /* protects this struct */ | 260 | spinlock_t lock; /* protects this struct */ |
260 | int flags; | 261 | int flags; |
261 | struct scsi_eh_save ses; | 262 | struct scsi_eh_save ses; |
@@ -277,6 +278,17 @@ struct NCR5380_hostdata { | |||
277 | 278 | ||
278 | #ifdef __KERNEL__ | 279 | #ifdef __KERNEL__ |
279 | 280 | ||
281 | struct NCR5380_cmd { | ||
282 | struct list_head list; | ||
283 | }; | ||
284 | |||
285 | #define NCR5380_CMD_SIZE (sizeof(struct NCR5380_cmd)) | ||
286 | |||
287 | static inline struct scsi_cmnd *NCR5380_to_scmd(struct NCR5380_cmd *ncmd_ptr) | ||
288 | { | ||
289 | return ((struct scsi_cmnd *)ncmd_ptr) - 1; | ||
290 | } | ||
291 | |||
280 | #ifndef NDEBUG | 292 | #ifndef NDEBUG |
281 | #define NDEBUG (0) | 293 | #define NDEBUG (0) |
282 | #endif | 294 | #endif |
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 921c982886ae..b526ba579ba3 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c | |||
@@ -208,6 +208,7 @@ static struct scsi_host_template cumanascsi_template = { | |||
208 | .cmd_per_lun = 2, | 208 | .cmd_per_lun = 2, |
209 | .use_clustering = DISABLE_CLUSTERING, | 209 | .use_clustering = DISABLE_CLUSTERING, |
210 | .proc_name = "CumanaSCSI-1", | 210 | .proc_name = "CumanaSCSI-1", |
211 | .cmd_size = NCR5380_CMD_SIZE, | ||
211 | }; | 212 | }; |
212 | 213 | ||
213 | static int cumanascsi1_probe(struct expansion_card *ec, | 214 | static int cumanascsi1_probe(struct expansion_card *ec, |
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 4eef3cdd9aa0..70e648513275 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c | |||
@@ -114,6 +114,7 @@ static struct scsi_host_template oakscsi_template = { | |||
114 | .cmd_per_lun = 2, | 114 | .cmd_per_lun = 2, |
115 | .use_clustering = DISABLE_CLUSTERING, | 115 | .use_clustering = DISABLE_CLUSTERING, |
116 | .proc_name = "oakscsi", | 116 | .proc_name = "oakscsi", |
117 | .cmd_size = NCR5380_CMD_SIZE, | ||
117 | }; | 118 | }; |
118 | 119 | ||
119 | static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) | 120 | static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) |
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 809ef25b7049..12b98cbe7b44 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c | |||
@@ -175,10 +175,6 @@ | |||
175 | * possible) function may be used. | 175 | * possible) function may be used. |
176 | */ | 176 | */ |
177 | 177 | ||
178 | #define NEXT(cmd) ((struct scsi_cmnd *)(cmd)->host_scribble) | ||
179 | #define SET_NEXT(cmd,next) ((cmd)->host_scribble = (void *)(next)) | ||
180 | #define NEXTADDR(cmd) ((struct scsi_cmnd **)&(cmd)->host_scribble) | ||
181 | |||
182 | #define HOSTNO instance->host_no | 178 | #define HOSTNO instance->host_no |
183 | 179 | ||
184 | static int do_abort(struct Scsi_Host *); | 180 | static int do_abort(struct Scsi_Host *); |
@@ -665,8 +661,9 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) | |||
665 | #endif | 661 | #endif |
666 | spin_lock_init(&hostdata->lock); | 662 | spin_lock_init(&hostdata->lock); |
667 | hostdata->connected = NULL; | 663 | hostdata->connected = NULL; |
668 | hostdata->issue_queue = NULL; | 664 | INIT_LIST_HEAD(&hostdata->unissued); |
669 | hostdata->disconnected_queue = NULL; | 665 | INIT_LIST_HEAD(&hostdata->disconnected); |
666 | |||
670 | hostdata->flags = flags; | 667 | hostdata->flags = flags; |
671 | 668 | ||
672 | INIT_WORK(&hostdata->main_task, NCR5380_main); | 669 | INIT_WORK(&hostdata->main_task, NCR5380_main); |
@@ -781,7 +778,7 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, | |||
781 | struct scsi_cmnd *cmd) | 778 | struct scsi_cmnd *cmd) |
782 | { | 779 | { |
783 | struct NCR5380_hostdata *hostdata = shost_priv(instance); | 780 | struct NCR5380_hostdata *hostdata = shost_priv(instance); |
784 | struct scsi_cmnd *tmp; | 781 | struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); |
785 | unsigned long flags; | 782 | unsigned long flags; |
786 | 783 | ||
787 | #if (NDEBUG & NDEBUG_NO_WRITE) | 784 | #if (NDEBUG & NDEBUG_NO_WRITE) |
@@ -795,12 +792,6 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, | |||
795 | } | 792 | } |
796 | #endif /* (NDEBUG & NDEBUG_NO_WRITE) */ | 793 | #endif /* (NDEBUG & NDEBUG_NO_WRITE) */ |
797 | 794 | ||
798 | /* | ||
799 | * We use the host_scribble field as a pointer to the next command | ||
800 | * in a queue | ||
801 | */ | ||
802 | |||
803 | SET_NEXT(cmd, NULL); | ||
804 | cmd->result = 0; | 795 | cmd->result = 0; |
805 | 796 | ||
806 | /* | 797 | /* |
@@ -834,15 +825,11 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, | |||
834 | * sense data is only guaranteed to be valid while the condition exists. | 825 | * sense data is only guaranteed to be valid while the condition exists. |
835 | */ | 826 | */ |
836 | 827 | ||
837 | if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { | 828 | if (cmd->cmnd[0] == REQUEST_SENSE) |
838 | SET_NEXT(cmd, hostdata->issue_queue); | 829 | list_add(&ncmd->list, &hostdata->unissued); |
839 | hostdata->issue_queue = cmd; | 830 | else |
840 | } else { | 831 | list_add_tail(&ncmd->list, &hostdata->unissued); |
841 | for (tmp = (struct scsi_cmnd *)hostdata->issue_queue; | 832 | |
842 | NEXT(tmp); tmp = NEXT(tmp)) | ||
843 | ; | ||
844 | SET_NEXT(tmp, cmd); | ||
845 | } | ||
846 | spin_unlock_irqrestore(&hostdata->lock, flags); | 833 | spin_unlock_irqrestore(&hostdata->lock, flags); |
847 | 834 | ||
848 | dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n", | 835 | dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n", |
@@ -858,8 +845,8 @@ static inline void maybe_release_dma_irq(struct Scsi_Host *instance) | |||
858 | struct NCR5380_hostdata *hostdata = shost_priv(instance); | 845 | struct NCR5380_hostdata *hostdata = shost_priv(instance); |
859 | 846 | ||
860 | /* Caller does the locking needed to set & test these data atomically */ | 847 | /* Caller does the locking needed to set & test these data atomically */ |
861 | if (!hostdata->disconnected_queue && | 848 | if (list_empty(&hostdata->disconnected) && |
862 | !hostdata->issue_queue && | 849 | list_empty(&hostdata->unissued) && |
863 | !hostdata->connected && | 850 | !hostdata->connected && |
864 | !hostdata->retain_dma_intr) | 851 | !hostdata->retain_dma_intr) |
865 | NCR5380_release_dma_irq(instance); | 852 | NCR5380_release_dma_irq(instance); |
@@ -881,7 +868,7 @@ static void NCR5380_main(struct work_struct *work) | |||
881 | struct NCR5380_hostdata *hostdata = | 868 | struct NCR5380_hostdata *hostdata = |
882 | container_of(work, struct NCR5380_hostdata, main_task); | 869 | container_of(work, struct NCR5380_hostdata, main_task); |
883 | struct Scsi_Host *instance = hostdata->host; | 870 | struct Scsi_Host *instance = hostdata->host; |
884 | struct scsi_cmnd *tmp, *prev; | 871 | struct NCR5380_cmd *ncmd, *n; |
885 | int done; | 872 | int done; |
886 | 873 | ||
887 | /* | 874 | /* |
@@ -900,17 +887,9 @@ static void NCR5380_main(struct work_struct *work) | |||
900 | * Search through the issue_queue for a command destined | 887 | * Search through the issue_queue for a command destined |
901 | * for a target that's not busy. | 888 | * for a target that's not busy. |
902 | */ | 889 | */ |
903 | #if (NDEBUG & NDEBUG_LISTS) | 890 | list_for_each_entry_safe(ncmd, n, &hostdata->unissued, |
904 | for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL; | 891 | list) { |
905 | tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp)) | 892 | struct scsi_cmnd *tmp = NCR5380_to_scmd(ncmd); |
906 | ; | ||
907 | /*printk("%p ", tmp);*/ | ||
908 | if ((tmp == prev) && tmp) | ||
909 | printk(" LOOP\n"); | ||
910 | /* else printk("\n"); */ | ||
911 | #endif | ||
912 | for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, | ||
913 | prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) { | ||
914 | u8 lun = tmp->device->lun; | 893 | u8 lun = tmp->device->lun; |
915 | 894 | ||
916 | dsprintk(NDEBUG_QUEUES, instance, "main: tmp=%p target=%d busy=%d lun=%d\n", | 895 | dsprintk(NDEBUG_QUEUES, instance, "main: tmp=%p target=%d busy=%d lun=%d\n", |
@@ -923,15 +902,10 @@ static void NCR5380_main(struct work_struct *work) | |||
923 | !(hostdata->busy[tmp->device->id] & (1 << lun)) | 902 | !(hostdata->busy[tmp->device->id] & (1 << lun)) |
924 | #endif | 903 | #endif |
925 | ) { | 904 | ) { |
926 | if (prev) { | 905 | list_del(&ncmd->list); |
927 | SET_NEXT(prev, NEXT(tmp)); | ||
928 | } else { | ||
929 | hostdata->issue_queue = NEXT(tmp); | ||
930 | } | ||
931 | SET_NEXT(tmp, NULL); | ||
932 | dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, | 906 | dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, |
933 | instance, "main: removed %p from issue queue %p\n", | 907 | instance, "main: removed %p from issue queue\n", |
934 | tmp, prev); | 908 | tmp); |
935 | 909 | ||
936 | hostdata->retain_dma_intr++; | 910 | hostdata->retain_dma_intr++; |
937 | 911 | ||
@@ -960,8 +934,7 @@ static void NCR5380_main(struct work_struct *work) | |||
960 | maybe_release_dma_irq(instance); | 934 | maybe_release_dma_irq(instance); |
961 | } else { | 935 | } else { |
962 | /* Need to retry */ | 936 | /* Need to retry */ |
963 | SET_NEXT(tmp, hostdata->issue_queue); | 937 | list_add(&ncmd->list, &hostdata->unissued); |
964 | hostdata->issue_queue = tmp; | ||
965 | dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, | 938 | dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, |
966 | instance, "main: select() failed, %p returned to issue queue\n", | 939 | instance, "main: select() failed, %p returned to issue queue\n", |
967 | tmp); | 940 | tmp); |
@@ -1834,6 +1807,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) | |||
1834 | #endif | 1807 | #endif |
1835 | 1808 | ||
1836 | while ((cmd = hostdata->connected)) { | 1809 | while ((cmd = hostdata->connected)) { |
1810 | struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); | ||
1811 | |||
1837 | tmp = NCR5380_read(STATUS_REG); | 1812 | tmp = NCR5380_read(STATUS_REG); |
1838 | /* We only have a valid SCSI phase when REQ is asserted */ | 1813 | /* We only have a valid SCSI phase when REQ is asserted */ |
1839 | if (tmp & SR_REQ) { | 1814 | if (tmp & SR_REQ) { |
@@ -2042,8 +2017,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) | |||
2042 | (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { | 2017 | (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { |
2043 | scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); | 2018 | scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); |
2044 | 2019 | ||
2045 | SET_NEXT(cmd, hostdata->issue_queue); | 2020 | list_add(&ncmd->list, &hostdata->unissued); |
2046 | hostdata->issue_queue = (struct scsi_cmnd *) cmd; | ||
2047 | dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, | 2021 | dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, |
2048 | instance, "REQUEST SENSE cmd %p added to head of issue queue\n", | 2022 | instance, "REQUEST SENSE cmd %p added to head of issue queue\n", |
2049 | cmd); | 2023 | cmd); |
@@ -2092,9 +2066,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) | |||
2092 | case DISCONNECT: | 2066 | case DISCONNECT: |
2093 | /* Accept message by clearing ACK */ | 2067 | /* Accept message by clearing ACK */ |
2094 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 2068 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
2095 | SET_NEXT(cmd, hostdata->disconnected_queue); | ||
2096 | hostdata->connected = NULL; | 2069 | hostdata->connected = NULL; |
2097 | hostdata->disconnected_queue = cmd; | 2070 | list_add(&ncmd->list, &hostdata->disconnected); |
2098 | dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES, | 2071 | dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES, |
2099 | instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", | 2072 | instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", |
2100 | cmd, scmd_id(cmd), cmd->device->lun); | 2073 | cmd, scmd_id(cmd), cmd->device->lun); |
@@ -2288,7 +2261,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) | |||
2288 | unsigned char msg[3]; | 2261 | unsigned char msg[3]; |
2289 | int __maybe_unused len; | 2262 | int __maybe_unused len; |
2290 | unsigned char __maybe_unused *data, __maybe_unused phase; | 2263 | unsigned char __maybe_unused *data, __maybe_unused phase; |
2291 | struct scsi_cmnd *tmp = NULL, *prev; | 2264 | struct NCR5380_cmd *ncmd; |
2265 | struct scsi_cmnd *tmp; | ||
2292 | 2266 | ||
2293 | /* | 2267 | /* |
2294 | * Disable arbitration, etc. since the host adapter obviously | 2268 | * Disable arbitration, etc. since the host adapter obviously |
@@ -2379,19 +2353,18 @@ static void NCR5380_reselect(struct Scsi_Host *instance) | |||
2379 | * just reestablished, and remove it from the disconnected queue. | 2353 | * just reestablished, and remove it from the disconnected queue. |
2380 | */ | 2354 | */ |
2381 | 2355 | ||
2382 | for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL; | 2356 | tmp = NULL; |
2383 | tmp; prev = tmp, tmp = NEXT(tmp)) { | 2357 | list_for_each_entry(ncmd, &hostdata->disconnected, list) { |
2384 | if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun) | 2358 | struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); |
2359 | |||
2360 | if (target_mask == (1 << scmd_id(cmd)) && | ||
2361 | lun == (u8)cmd->device->lun | ||
2385 | #ifdef SUPPORT_TAGS | 2362 | #ifdef SUPPORT_TAGS |
2386 | && (tag == tmp->tag) | 2363 | && (tag == cmd->tag) |
2387 | #endif | 2364 | #endif |
2388 | ) { | 2365 | ) { |
2389 | if (prev) { | 2366 | list_del(&ncmd->list); |
2390 | SET_NEXT(prev, NEXT(tmp)); | 2367 | tmp = cmd; |
2391 | } else { | ||
2392 | hostdata->disconnected_queue = NEXT(tmp); | ||
2393 | } | ||
2394 | SET_NEXT(tmp, NULL); | ||
2395 | break; | 2368 | break; |
2396 | } | 2369 | } |
2397 | } | 2370 | } |
@@ -2489,188 +2462,18 @@ int NCR5380_abort(struct scsi_cmnd *cmd) | |||
2489 | { | 2462 | { |
2490 | struct Scsi_Host *instance = cmd->device->host; | 2463 | struct Scsi_Host *instance = cmd->device->host; |
2491 | struct NCR5380_hostdata *hostdata = shost_priv(instance); | 2464 | struct NCR5380_hostdata *hostdata = shost_priv(instance); |
2492 | struct scsi_cmnd *tmp, **prev; | ||
2493 | unsigned long flags; | 2465 | unsigned long flags; |
2494 | 2466 | ||
2495 | scmd_printk(KERN_NOTICE, cmd, "aborting command\n"); | ||
2496 | |||
2497 | spin_lock_irqsave(&hostdata->lock, flags); | 2467 | spin_lock_irqsave(&hostdata->lock, flags); |
2498 | 2468 | ||
2469 | #if (NDEBUG & NDEBUG_ANY) | ||
2470 | scmd_printk(KERN_INFO, cmd, "aborting command\n"); | ||
2471 | #endif | ||
2499 | NCR5380_dprint(NDEBUG_ANY, instance); | 2472 | NCR5380_dprint(NDEBUG_ANY, instance); |
2500 | NCR5380_dprint_phase(NDEBUG_ANY, instance); | 2473 | NCR5380_dprint_phase(NDEBUG_ANY, instance); |
2501 | 2474 | ||
2502 | dprintk(NDEBUG_ABORT, "scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO, | ||
2503 | NCR5380_read(BUS_AND_STATUS_REG), | ||
2504 | NCR5380_read(STATUS_REG)); | ||
2505 | |||
2506 | #if 1 | ||
2507 | /* | ||
2508 | * Case 1 : If the command is the currently executing command, | ||
2509 | * we'll set the aborted flag and return control so that | ||
2510 | * information transfer routine can exit cleanly. | ||
2511 | */ | ||
2512 | |||
2513 | if (hostdata->connected == cmd) { | ||
2514 | |||
2515 | dprintk(NDEBUG_ABORT, "scsi%d: aborting connected command\n", HOSTNO); | ||
2516 | /* | ||
2517 | * We should perform BSY checking, and make sure we haven't slipped | ||
2518 | * into BUS FREE. | ||
2519 | */ | ||
2520 | |||
2521 | /* NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */ | ||
2522 | /* | ||
2523 | * Since we can't change phases until we've completed the current | ||
2524 | * handshake, we have to source or sink a byte of data if the current | ||
2525 | * phase is not MSGOUT. | ||
2526 | */ | ||
2527 | |||
2528 | /* | ||
2529 | * Return control to the executing NCR drive so we can clear the | ||
2530 | * aborted flag and get back into our main loop. | ||
2531 | */ | ||
2532 | |||
2533 | if (do_abort(instance) == 0) { | ||
2534 | hostdata->connected = NULL; | ||
2535 | cmd->result = DID_ABORT << 16; | ||
2536 | #ifdef SUPPORT_TAGS | ||
2537 | cmd_free_tag(cmd); | ||
2538 | #else | ||
2539 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | ||
2540 | #endif | ||
2541 | maybe_release_dma_irq(instance); | ||
2542 | spin_unlock_irqrestore(&hostdata->lock, flags); | ||
2543 | cmd->scsi_done(cmd); | ||
2544 | return SUCCESS; | ||
2545 | } else { | ||
2546 | spin_unlock_irqrestore(&hostdata->lock, flags); | ||
2547 | printk("scsi%d: abort of connected command failed!\n", HOSTNO); | ||
2548 | return FAILED; | ||
2549 | } | ||
2550 | } | ||
2551 | #endif | ||
2552 | |||
2553 | /* | ||
2554 | * Case 2 : If the command hasn't been issued yet, we simply remove it | ||
2555 | * from the issue queue. | ||
2556 | */ | ||
2557 | for (prev = (struct scsi_cmnd **)&(hostdata->issue_queue), | ||
2558 | tmp = (struct scsi_cmnd *)hostdata->issue_queue; | ||
2559 | tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) { | ||
2560 | if (cmd == tmp) { | ||
2561 | (*prev) = NEXT(tmp); | ||
2562 | SET_NEXT(tmp, NULL); | ||
2563 | tmp->result = DID_ABORT << 16; | ||
2564 | maybe_release_dma_irq(instance); | ||
2565 | spin_unlock_irqrestore(&hostdata->lock, flags); | ||
2566 | dprintk(NDEBUG_ABORT, "scsi%d: abort removed command from issue queue.\n", | ||
2567 | HOSTNO); | ||
2568 | /* Tagged queuing note: no tag to free here, hasn't been assigned | ||
2569 | * yet... */ | ||
2570 | tmp->scsi_done(tmp); | ||
2571 | return SUCCESS; | ||
2572 | } | ||
2573 | } | ||
2574 | |||
2575 | /* | ||
2576 | * Case 3 : If any commands are connected, we're going to fail the abort | ||
2577 | * and let the high level SCSI driver retry at a later time or | ||
2578 | * issue a reset. | ||
2579 | * | ||
2580 | * Timeouts, and therefore aborted commands, will be highly unlikely | ||
2581 | * and handling them cleanly in this situation would make the common | ||
2582 | * case of noresets less efficient, and would pollute our code. So, | ||
2583 | * we fail. | ||
2584 | */ | ||
2585 | |||
2586 | if (hostdata->connected) { | ||
2587 | spin_unlock_irqrestore(&hostdata->lock, flags); | ||
2588 | dprintk(NDEBUG_ABORT, "scsi%d: abort failed, command connected.\n", HOSTNO); | ||
2589 | return FAILED; | ||
2590 | } | ||
2591 | |||
2592 | /* | ||
2593 | * Case 4: If the command is currently disconnected from the bus, and | ||
2594 | * there are no connected commands, we reconnect the I_T_L or | ||
2595 | * I_T_L_Q nexus associated with it, go into message out, and send | ||
2596 | * an abort message. | ||
2597 | * | ||
2598 | * This case is especially ugly. In order to reestablish the nexus, we | ||
2599 | * need to call NCR5380_select(). The easiest way to implement this | ||
2600 | * function was to abort if the bus was busy, and let the interrupt | ||
2601 | * handler triggered on the SEL for reselect take care of lost arbitrations | ||
2602 | * where necessary, meaning interrupts need to be enabled. | ||
2603 | * | ||
2604 | * When interrupts are enabled, the queues may change - so we | ||
2605 | * can't remove it from the disconnected queue before selecting it | ||
2606 | * because that could cause a failure in hashing the nexus if that | ||
2607 | * device reselected. | ||
2608 | * | ||
2609 | * Since the queues may change, we can't use the pointers from when we | ||
2610 | * first locate it. | ||
2611 | * | ||
2612 | * So, we must first locate the command, and if NCR5380_select() | ||
2613 | * succeeds, then issue the abort, relocate the command and remove | ||
2614 | * it from the disconnected queue. | ||
2615 | */ | ||
2616 | |||
2617 | for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; | ||
2618 | tmp = NEXT(tmp)) { | ||
2619 | if (cmd == tmp) { | ||
2620 | dprintk(NDEBUG_ABORT, "scsi%d: aborting disconnected command.\n", HOSTNO); | ||
2621 | |||
2622 | if (NCR5380_select(instance, cmd)) { | ||
2623 | spin_unlock_irq(&hostdata->lock); | ||
2624 | return FAILED; | ||
2625 | } | ||
2626 | dprintk(NDEBUG_ABORT, "scsi%d: nexus reestablished.\n", HOSTNO); | ||
2627 | |||
2628 | do_abort(instance); | ||
2629 | |||
2630 | for (prev = (struct scsi_cmnd **)&(hostdata->disconnected_queue), | ||
2631 | tmp = (struct scsi_cmnd *)hostdata->disconnected_queue; | ||
2632 | tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) { | ||
2633 | if (cmd == tmp) { | ||
2634 | *prev = NEXT(tmp); | ||
2635 | SET_NEXT(tmp, NULL); | ||
2636 | tmp->result = DID_ABORT << 16; | ||
2637 | /* We must unlock the tag/LUN immediately here, since the | ||
2638 | * target goes to BUS FREE and doesn't send us another | ||
2639 | * message (COMMAND_COMPLETE or the like) | ||
2640 | */ | ||
2641 | #ifdef SUPPORT_TAGS | ||
2642 | cmd_free_tag(tmp); | ||
2643 | #else | ||
2644 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | ||
2645 | #endif | ||
2646 | maybe_release_dma_irq(instance); | ||
2647 | spin_unlock_irqrestore(&hostdata->lock, flags); | ||
2648 | tmp->scsi_done(tmp); | ||
2649 | return SUCCESS; | ||
2650 | } | ||
2651 | } | ||
2652 | } | ||
2653 | } | ||
2654 | |||
2655 | /* Maybe it is sufficient just to release the ST-DMA lock... (if | ||
2656 | * possible at all) At least, we should check if the lock could be | ||
2657 | * released after the abort, in case it is kept due to some bug. | ||
2658 | */ | ||
2659 | maybe_release_dma_irq(instance); | ||
2660 | spin_unlock_irqrestore(&hostdata->lock, flags); | 2475 | spin_unlock_irqrestore(&hostdata->lock, flags); |
2661 | 2476 | ||
2662 | /* | ||
2663 | * Case 5 : If we reached this point, the command was not found in any of | ||
2664 | * the queues. | ||
2665 | * | ||
2666 | * We probably reached this point because of an unlikely race condition | ||
2667 | * between the command completing successfully and the abortion code, | ||
2668 | * so we won't panic, but we will notify the user in case something really | ||
2669 | * broke. | ||
2670 | */ | ||
2671 | |||
2672 | printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO); | ||
2673 | |||
2674 | return FAILED; | 2477 | return FAILED; |
2675 | } | 2478 | } |
2676 | 2479 | ||
@@ -2710,16 +2513,18 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) | |||
2710 | * commands! | 2513 | * commands! |
2711 | */ | 2514 | */ |
2712 | 2515 | ||
2713 | if (hostdata->issue_queue) | ||
2714 | dsprintk(NDEBUG_ABORT, instance, "reset aborted issued command(s)\n"); | ||
2715 | if (hostdata->connected) | 2516 | if (hostdata->connected) |
2716 | dsprintk(NDEBUG_ABORT, instance, "reset aborted a connected command\n"); | 2517 | dsprintk(NDEBUG_ABORT, instance, "reset aborted a connected command\n"); |
2717 | if (hostdata->disconnected_queue) | ||
2718 | dsprintk(NDEBUG_ABORT, instance, "reset aborted disconnected command(s)\n"); | ||
2719 | |||
2720 | hostdata->issue_queue = NULL; | ||
2721 | hostdata->connected = NULL; | 2518 | hostdata->connected = NULL; |
2722 | hostdata->disconnected_queue = NULL; | 2519 | |
2520 | if (!list_empty(&hostdata->unissued)) | ||
2521 | dsprintk(NDEBUG_ABORT, instance, "reset aborted unissued list\n"); | ||
2522 | INIT_LIST_HEAD(&hostdata->unissued); | ||
2523 | |||
2524 | if (!list_empty(&hostdata->disconnected)) | ||
2525 | dsprintk(NDEBUG_ABORT, instance, "reset aborted disconnected list\n"); | ||
2526 | INIT_LIST_HEAD(&hostdata->disconnected); | ||
2527 | |||
2723 | #ifdef SUPPORT_TAGS | 2528 | #ifdef SUPPORT_TAGS |
2724 | free_all_tags(hostdata); | 2529 | free_all_tags(hostdata); |
2725 | #endif | 2530 | #endif |
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index e271b08ccbb2..263cf06a8f30 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c | |||
@@ -780,6 +780,7 @@ static struct scsi_host_template atari_scsi_template = { | |||
780 | .eh_bus_reset_handler = atari_scsi_bus_reset, | 780 | .eh_bus_reset_handler = atari_scsi_bus_reset, |
781 | .this_id = 7, | 781 | .this_id = 7, |
782 | .use_clustering = DISABLE_CLUSTERING, | 782 | .use_clustering = DISABLE_CLUSTERING, |
783 | .cmd_size = NCR5380_CMD_SIZE, | ||
783 | }; | 784 | }; |
784 | 785 | ||
785 | static int __init atari_scsi_probe(struct platform_device *pdev) | 786 | static int __init atari_scsi_probe(struct platform_device *pdev) |
diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 51e63fe957c5..ddb4e616bfed 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c | |||
@@ -61,6 +61,7 @@ static struct scsi_host_template dmx3191d_driver_template = { | |||
61 | .sg_tablesize = SG_ALL, | 61 | .sg_tablesize = SG_ALL, |
62 | .cmd_per_lun = 2, | 62 | .cmd_per_lun = 2, |
63 | .use_clustering = DISABLE_CLUSTERING, | 63 | .use_clustering = DISABLE_CLUSTERING, |
64 | .cmd_size = NCR5380_CMD_SIZE, | ||
64 | }; | 65 | }; |
65 | 66 | ||
66 | static int dmx3191d_probe_one(struct pci_dev *pdev, | 67 | static int dmx3191d_probe_one(struct pci_dev *pdev, |
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index d74661458f15..f6166e34e3b0 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c | |||
@@ -452,5 +452,6 @@ static struct scsi_host_template driver_template = { | |||
452 | .sg_tablesize = SG_ALL, | 452 | .sg_tablesize = SG_ALL, |
453 | .cmd_per_lun = 2, | 453 | .cmd_per_lun = 2, |
454 | .use_clustering = DISABLE_CLUSTERING, | 454 | .use_clustering = DISABLE_CLUSTERING, |
455 | .cmd_size = NCR5380_CMD_SIZE, | ||
455 | }; | 456 | }; |
456 | #include "scsi_module.c" | 457 | #include "scsi_module.c" |
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 0f2b3d9a6ae8..30472064170e 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c | |||
@@ -728,6 +728,7 @@ static struct scsi_host_template driver_template = { | |||
728 | .sg_tablesize = SG_ALL, | 728 | .sg_tablesize = SG_ALL, |
729 | .cmd_per_lun = 2, | 729 | .cmd_per_lun = 2, |
730 | .use_clustering = DISABLE_CLUSTERING, | 730 | .use_clustering = DISABLE_CLUSTERING, |
731 | .cmd_size = NCR5380_CMD_SIZE, | ||
731 | }; | 732 | }; |
732 | 733 | ||
733 | #include "scsi_module.c" | 734 | #include "scsi_module.c" |
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index e75bed25dd15..18f74b4a0b95 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c | |||
@@ -323,6 +323,7 @@ static struct scsi_host_template mac_scsi_template = { | |||
323 | .sg_tablesize = SG_ALL, | 323 | .sg_tablesize = SG_ALL, |
324 | .cmd_per_lun = 2, | 324 | .cmd_per_lun = 2, |
325 | .use_clustering = DISABLE_CLUSTERING, | 325 | .use_clustering = DISABLE_CLUSTERING, |
326 | .cmd_size = NCR5380_CMD_SIZE, | ||
326 | }; | 327 | }; |
327 | 328 | ||
328 | static int __init mac_scsi_probe(struct platform_device *pdev) | 329 | static int __init mac_scsi_probe(struct platform_device *pdev) |
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 5f8a8295a5c1..77789405f4a9 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c | |||
@@ -562,6 +562,7 @@ static struct scsi_host_template driver_template = { | |||
562 | .sg_tablesize = SG_ALL, | 562 | .sg_tablesize = SG_ALL, |
563 | .cmd_per_lun = 2, | 563 | .cmd_per_lun = 2, |
564 | .use_clustering = DISABLE_CLUSTERING, | 564 | .use_clustering = DISABLE_CLUSTERING, |
565 | .cmd_size = NCR5380_CMD_SIZE, | ||
565 | }; | 566 | }; |
566 | #include "scsi_module.c" | 567 | #include "scsi_module.c" |
567 | 568 | ||
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 14835540fecb..c10782b4843e 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c | |||
@@ -468,6 +468,7 @@ static struct scsi_host_template sun3_scsi_template = { | |||
468 | .sg_tablesize = SG_NONE, | 468 | .sg_tablesize = SG_NONE, |
469 | .cmd_per_lun = 2, | 469 | .cmd_per_lun = 2, |
470 | .use_clustering = DISABLE_CLUSTERING, | 470 | .use_clustering = DISABLE_CLUSTERING, |
471 | .cmd_size = NCR5380_CMD_SIZE, | ||
471 | }; | 472 | }; |
472 | 473 | ||
473 | static int __init sun3_scsi_probe(struct platform_device *pdev) | 474 | static int __init sun3_scsi_probe(struct platform_device *pdev) |
diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index d1ed1f532a24..e50881ab9eb4 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c | |||
@@ -406,5 +406,6 @@ static struct scsi_host_template driver_template = { | |||
406 | .sg_tablesize = SG_ALL, | 406 | .sg_tablesize = SG_ALL, |
407 | .cmd_per_lun = 2, | 407 | .cmd_per_lun = 2, |
408 | .use_clustering = DISABLE_CLUSTERING, | 408 | .use_clustering = DISABLE_CLUSTERING, |
409 | .cmd_size = NCR5380_CMD_SIZE, | ||
409 | }; | 410 | }; |
410 | #include "scsi_module.c" | 411 | #include "scsi_module.c" |