diff options
Diffstat (limited to 'drivers/scsi/aic7xxx/aic7xxx_osm.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm.c | 121 |
1 files changed, 2 insertions, 119 deletions
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index d0c71da58e85..ca796b9d737b 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -433,7 +433,6 @@ static void ahc_linux_release_simq(u_long arg); | |||
433 | static void ahc_linux_dev_timed_unfreeze(u_long arg); | 433 | static void ahc_linux_dev_timed_unfreeze(u_long arg); |
434 | static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); | 434 | static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); |
435 | static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); | 435 | static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); |
436 | static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc); | ||
437 | static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, | 436 | static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, |
438 | struct ahc_devinfo *devinfo); | 437 | struct ahc_devinfo *devinfo); |
439 | static void ahc_linux_device_queue_depth(struct ahc_softc *ahc, | 438 | static void ahc_linux_device_queue_depth(struct ahc_softc *ahc, |
@@ -454,29 +453,17 @@ static void ahc_linux_setup_tag_info_global(char *p); | |||
454 | static aic_option_callback_t ahc_linux_setup_tag_info; | 453 | static aic_option_callback_t ahc_linux_setup_tag_info; |
455 | static int aic7xxx_setup(char *s); | 454 | static int aic7xxx_setup(char *s); |
456 | static int ahc_linux_next_unit(void); | 455 | static int ahc_linux_next_unit(void); |
457 | static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc); | ||
458 | 456 | ||
459 | /********************************* Inlines ************************************/ | 457 | /********************************* Inlines ************************************/ |
460 | static __inline struct ahc_linux_device* | 458 | static __inline struct ahc_linux_device* |
461 | ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, | 459 | ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, |
462 | u_int target, u_int lun, int alloc); | 460 | u_int target, u_int lun, int alloc); |
463 | static __inline void ahc_schedule_completeq(struct ahc_softc *ahc); | ||
464 | static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); | 461 | static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); |
465 | 462 | ||
466 | static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, | 463 | static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, |
467 | struct ahc_dma_seg *sg, | 464 | struct ahc_dma_seg *sg, |
468 | dma_addr_t addr, bus_size_t len); | 465 | dma_addr_t addr, bus_size_t len); |
469 | 466 | ||
470 | static __inline void | ||
471 | ahc_schedule_completeq(struct ahc_softc *ahc) | ||
472 | { | ||
473 | if ((ahc->platform_data->flags & AHC_RUN_CMPLT_Q_TIMER) == 0) { | ||
474 | ahc->platform_data->flags |= AHC_RUN_CMPLT_Q_TIMER; | ||
475 | ahc->platform_data->completeq_timer.expires = jiffies; | ||
476 | add_timer(&ahc->platform_data->completeq_timer); | ||
477 | } | ||
478 | } | ||
479 | |||
480 | static __inline struct ahc_linux_device* | 467 | static __inline struct ahc_linux_device* |
481 | ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, | 468 | ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, |
482 | u_int lun, int alloc) | 469 | u_int lun, int alloc) |
@@ -503,42 +490,6 @@ ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, | |||
503 | return (dev); | 490 | return (dev); |
504 | } | 491 | } |
505 | 492 | ||
506 | #define AHC_LINUX_MAX_RETURNED_ERRORS 4 | ||
507 | static struct ahc_cmd * | ||
508 | ahc_linux_run_complete_queue(struct ahc_softc *ahc) | ||
509 | { | ||
510 | struct ahc_cmd *acmd; | ||
511 | int with_errors; | ||
512 | |||
513 | with_errors = 0; | ||
514 | while ((acmd = TAILQ_FIRST(&ahc->platform_data->completeq)) != NULL) { | ||
515 | struct scsi_cmnd *cmd; | ||
516 | |||
517 | if (with_errors > AHC_LINUX_MAX_RETURNED_ERRORS) { | ||
518 | /* | ||
519 | * Linux uses stack recursion to requeue | ||
520 | * commands that need to be retried. Avoid | ||
521 | * blowing out the stack by "spoon feeding" | ||
522 | * commands that completed with error back | ||
523 | * the operating system in case they are going | ||
524 | * to be retried. "ick" | ||
525 | */ | ||
526 | ahc_schedule_completeq(ahc); | ||
527 | break; | ||
528 | } | ||
529 | TAILQ_REMOVE(&ahc->platform_data->completeq, | ||
530 | acmd, acmd_links.tqe); | ||
531 | cmd = &acmd_scsi_cmd(acmd); | ||
532 | cmd->host_scribble = NULL; | ||
533 | if (ahc_cmd_get_transaction_status(cmd) != DID_OK | ||
534 | || (cmd->result & 0xFF) != SCSI_STATUS_OK) | ||
535 | with_errors++; | ||
536 | |||
537 | cmd->scsi_done(cmd); | ||
538 | } | ||
539 | return (acmd); | ||
540 | } | ||
541 | |||
542 | static __inline void | 493 | static __inline void |
543 | ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) | 494 | ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) |
544 | { | 495 | { |
@@ -856,7 +807,6 @@ ahc_linux_bus_reset(struct scsi_cmnd *cmd) | |||
856 | ahc = *(struct ahc_softc **)cmd->device->host->hostdata; | 807 | ahc = *(struct ahc_softc **)cmd->device->host->hostdata; |
857 | found = ahc_reset_channel(ahc, cmd->device->channel + 'A', | 808 | found = ahc_reset_channel(ahc, cmd->device->channel + 'A', |
858 | /*initiate reset*/TRUE); | 809 | /*initiate reset*/TRUE); |
859 | ahc_linux_run_complete_queue(ahc); | ||
860 | 810 | ||
861 | if (bootverbose) | 811 | if (bootverbose) |
862 | printf("%s: SCSI bus reset delivered. " | 812 | printf("%s: SCSI bus reset delivered. " |
@@ -1331,13 +1281,8 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) | |||
1331 | if (ahc->platform_data == NULL) | 1281 | if (ahc->platform_data == NULL) |
1332 | return (ENOMEM); | 1282 | return (ENOMEM); |
1333 | memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); | 1283 | memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); |
1334 | TAILQ_INIT(&ahc->platform_data->completeq); | ||
1335 | ahc->platform_data->irq = AHC_LINUX_NOIRQ; | 1284 | ahc->platform_data->irq = AHC_LINUX_NOIRQ; |
1336 | ahc_lockinit(ahc); | 1285 | ahc_lockinit(ahc); |
1337 | init_timer(&ahc->platform_data->completeq_timer); | ||
1338 | ahc->platform_data->completeq_timer.data = (u_long)ahc; | ||
1339 | ahc->platform_data->completeq_timer.function = | ||
1340 | (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue; | ||
1341 | init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); | 1286 | init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); |
1342 | ahc->seltime = (aic7xxx_seltime & 0x3) << 4; | 1287 | ahc->seltime = (aic7xxx_seltime & 0x3) << 4; |
1343 | ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; | 1288 | ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; |
@@ -1355,7 +1300,6 @@ ahc_platform_free(struct ahc_softc *ahc) | |||
1355 | int i, j; | 1300 | int i, j; |
1356 | 1301 | ||
1357 | if (ahc->platform_data != NULL) { | 1302 | if (ahc->platform_data != NULL) { |
1358 | del_timer_sync(&ahc->platform_data->completeq_timer); | ||
1359 | if (ahc->platform_data->host != NULL) { | 1303 | if (ahc->platform_data->host != NULL) { |
1360 | scsi_remove_host(ahc->platform_data->host); | 1304 | scsi_remove_host(ahc->platform_data->host); |
1361 | scsi_host_put(ahc->platform_data->host); | 1305 | scsi_host_put(ahc->platform_data->host); |
@@ -1504,18 +1448,6 @@ ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel, | |||
1504 | return 0; | 1448 | return 0; |
1505 | } | 1449 | } |
1506 | 1450 | ||
1507 | static void | ||
1508 | ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc) | ||
1509 | { | ||
1510 | u_long flags; | ||
1511 | |||
1512 | ahc_lock(ahc, &flags); | ||
1513 | del_timer(&ahc->platform_data->completeq_timer); | ||
1514 | ahc->platform_data->flags &= ~AHC_RUN_CMPLT_Q_TIMER; | ||
1515 | ahc_linux_run_complete_queue(ahc); | ||
1516 | ahc_unlock(ahc, &flags); | ||
1517 | } | ||
1518 | |||
1519 | static u_int | 1451 | static u_int |
1520 | ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) | 1452 | ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) |
1521 | { | 1453 | { |
@@ -1785,7 +1717,6 @@ ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs) | |||
1785 | ahc = (struct ahc_softc *) dev_id; | 1717 | ahc = (struct ahc_softc *) dev_id; |
1786 | ahc_lock(ahc, &flags); | 1718 | ahc_lock(ahc, &flags); |
1787 | ours = ahc_intr(ahc); | 1719 | ours = ahc_intr(ahc); |
1788 | ahc_linux_run_complete_queue(ahc); | ||
1789 | ahc_unlock(ahc, &flags); | 1720 | ahc_unlock(ahc, &flags); |
1790 | return IRQ_RETVAL(ours); | 1721 | return IRQ_RETVAL(ours); |
1791 | } | 1722 | } |
@@ -1794,8 +1725,6 @@ void | |||
1794 | ahc_platform_flushwork(struct ahc_softc *ahc) | 1725 | ahc_platform_flushwork(struct ahc_softc *ahc) |
1795 | { | 1726 | { |
1796 | 1727 | ||
1797 | while (ahc_linux_run_complete_queue(ahc) != NULL) | ||
1798 | ; | ||
1799 | } | 1728 | } |
1800 | 1729 | ||
1801 | static struct ahc_linux_target* | 1730 | static struct ahc_linux_target* |
@@ -2275,22 +2204,6 @@ static void | |||
2275 | ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) | 2204 | ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) |
2276 | { | 2205 | { |
2277 | /* | 2206 | /* |
2278 | * Typically, the complete queue has very few entries | ||
2279 | * queued to it before the queue is emptied by | ||
2280 | * ahc_linux_run_complete_queue, so sorting the entries | ||
2281 | * by generation number should be inexpensive. | ||
2282 | * We perform the sort so that commands that complete | ||
2283 | * with an error are retuned in the order origionally | ||
2284 | * queued to the controller so that any subsequent retries | ||
2285 | * are performed in order. The underlying ahc routines do | ||
2286 | * not guarantee the order that aborted commands will be | ||
2287 | * returned to us. | ||
2288 | */ | ||
2289 | struct ahc_completeq *completeq; | ||
2290 | struct ahc_cmd *list_cmd; | ||
2291 | struct ahc_cmd *acmd; | ||
2292 | |||
2293 | /* | ||
2294 | * Map CAM error codes into Linux Error codes. We | 2207 | * Map CAM error codes into Linux Error codes. We |
2295 | * avoid the conversion so that the DV code has the | 2208 | * avoid the conversion so that the DV code has the |
2296 | * full error information available when making | 2209 | * full error information available when making |
@@ -2343,26 +2256,7 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) | |||
2343 | new_status = DID_ERROR; | 2256 | new_status = DID_ERROR; |
2344 | break; | 2257 | break; |
2345 | case CAM_REQUEUE_REQ: | 2258 | case CAM_REQUEUE_REQ: |
2346 | /* | 2259 | new_status = DID_REQUEUE; |
2347 | * If we want the request requeued, make sure there | ||
2348 | * are sufficent retries. In the old scsi error code, | ||
2349 | * we used to be able to specify a result code that | ||
2350 | * bypassed the retry count. Now we must use this | ||
2351 | * hack. We also "fake" a check condition with | ||
2352 | * a sense code of ABORTED COMMAND. This seems to | ||
2353 | * evoke a retry even if this command is being sent | ||
2354 | * via the eh thread. Ick! Ick! Ick! | ||
2355 | */ | ||
2356 | if (cmd->retries > 0) | ||
2357 | cmd->retries--; | ||
2358 | new_status = DID_OK; | ||
2359 | ahc_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND); | ||
2360 | cmd->result |= (DRIVER_SENSE << 24); | ||
2361 | memset(cmd->sense_buffer, 0, | ||
2362 | sizeof(cmd->sense_buffer)); | ||
2363 | cmd->sense_buffer[0] = SSD_ERRCODE_VALID | ||
2364 | | SSD_CURRENT_ERROR; | ||
2365 | cmd->sense_buffer[2] = SSD_KEY_ABORTED_COMMAND; | ||
2366 | break; | 2260 | break; |
2367 | default: | 2261 | default: |
2368 | /* We should never get here */ | 2262 | /* We should never get here */ |
@@ -2373,17 +2267,7 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) | |||
2373 | ahc_cmd_set_transaction_status(cmd, new_status); | 2267 | ahc_cmd_set_transaction_status(cmd, new_status); |
2374 | } | 2268 | } |
2375 | 2269 | ||
2376 | completeq = &ahc->platform_data->completeq; | 2270 | cmd->scsi_done(cmd); |
2377 | list_cmd = TAILQ_FIRST(completeq); | ||
2378 | acmd = (struct ahc_cmd *)cmd; | ||
2379 | while (list_cmd != NULL | ||
2380 | && acmd_scsi_cmd(list_cmd).serial_number | ||
2381 | < acmd_scsi_cmd(acmd).serial_number) | ||
2382 | list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe); | ||
2383 | if (list_cmd != NULL) | ||
2384 | TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe); | ||
2385 | else | ||
2386 | TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe); | ||
2387 | } | 2271 | } |
2388 | 2272 | ||
2389 | static void | 2273 | static void |
@@ -2747,7 +2631,6 @@ done: | |||
2747 | } | 2631 | } |
2748 | spin_lock_irq(&ahc->platform_data->spin_lock); | 2632 | spin_lock_irq(&ahc->platform_data->spin_lock); |
2749 | } | 2633 | } |
2750 | ahc_linux_run_complete_queue(ahc); | ||
2751 | return (retval); | 2634 | return (retval); |
2752 | } | 2635 | } |
2753 | 2636 | ||