aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c121
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h17
2 files changed, 5 insertions, 133 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);
433static void ahc_linux_dev_timed_unfreeze(u_long arg); 433static void ahc_linux_dev_timed_unfreeze(u_long arg);
434static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); 434static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
435static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); 435static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
436static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc);
437static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, 436static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
438 struct ahc_devinfo *devinfo); 437 struct ahc_devinfo *devinfo);
439static void ahc_linux_device_queue_depth(struct ahc_softc *ahc, 438static void ahc_linux_device_queue_depth(struct ahc_softc *ahc,
@@ -454,29 +453,17 @@ static void ahc_linux_setup_tag_info_global(char *p);
454static aic_option_callback_t ahc_linux_setup_tag_info; 453static aic_option_callback_t ahc_linux_setup_tag_info;
455static int aic7xxx_setup(char *s); 454static int aic7xxx_setup(char *s);
456static int ahc_linux_next_unit(void); 455static int ahc_linux_next_unit(void);
457static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc);
458 456
459/********************************* Inlines ************************************/ 457/********************************* Inlines ************************************/
460static __inline struct ahc_linux_device* 458static __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);
463static __inline void ahc_schedule_completeq(struct ahc_softc *ahc);
464static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); 461static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
465 462
466static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, 463static __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
470static __inline void
471ahc_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
480static __inline struct ahc_linux_device* 467static __inline struct ahc_linux_device*
481ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, 468ahc_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
507static struct ahc_cmd *
508ahc_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
542static __inline void 493static __inline void
543ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) 494ahc_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
1507static void
1508ahc_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
1519static u_int 1451static u_int
1520ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 1452ahc_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
1794ahc_platform_flushwork(struct ahc_softc *ahc) 1725ahc_platform_flushwork(struct ahc_softc *ahc)
1795{ 1726{
1796 1727
1797 while (ahc_linux_run_complete_queue(ahc) != NULL)
1798 ;
1799} 1728}
1800 1729
1801static struct ahc_linux_target* 1730static struct ahc_linux_target*
@@ -2275,22 +2204,6 @@ static void
2275ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) 2204ahc_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
2389static void 2273static 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
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index 9ce7639dc739..e70c1fa47db2 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -436,16 +436,11 @@ struct ahc_linux_target {
436/* 436/*
437 * Per-SCB OSM storage. 437 * Per-SCB OSM storage.
438 */ 438 */
439typedef enum {
440 AHC_UP_EH_SEMAPHORE = 0x1
441} ahc_linux_scb_flags;
442
443struct scb_platform_data { 439struct scb_platform_data {
444 struct ahc_linux_device *dev; 440 struct ahc_linux_device *dev;
445 dma_addr_t buf_busaddr; 441 dma_addr_t buf_busaddr;
446 uint32_t xfer_len; 442 uint32_t xfer_len;
447 uint32_t sense_resid; /* Auto-Sense residual */ 443 uint32_t sense_resid; /* Auto-Sense residual */
448 ahc_linux_scb_flags flags;
449}; 444};
450 445
451/* 446/*
@@ -454,22 +449,14 @@ struct scb_platform_data {
454 * alignment restrictions of the various platforms supported by 449 * alignment restrictions of the various platforms supported by
455 * this driver. 450 * this driver.
456 */ 451 */
457typedef enum {
458 AHC_RUN_CMPLT_Q_TIMER = 0x10
459} ahc_linux_softc_flags;
460
461TAILQ_HEAD(ahc_completeq, ahc_cmd);
462
463struct ahc_platform_data { 452struct ahc_platform_data {
464 /* 453 /*
465 * Fields accessed from interrupt context. 454 * Fields accessed from interrupt context.
466 */ 455 */
467 struct ahc_linux_target *targets[AHC_NUM_TARGETS]; 456 struct ahc_linux_target *targets[AHC_NUM_TARGETS];
468 struct ahc_completeq completeq;
469 457
470 spinlock_t spin_lock; 458 spinlock_t spin_lock;
471 u_int qfrozen; 459 u_int qfrozen;
472 struct timer_list completeq_timer;
473 struct timer_list reset_timer; 460 struct timer_list reset_timer;
474 struct semaphore eh_sem; 461 struct semaphore eh_sem;
475 struct Scsi_Host *host; /* pointer to scsi host */ 462 struct Scsi_Host *host; /* pointer to scsi host */
@@ -477,7 +464,9 @@ struct ahc_platform_data {
477 uint32_t irq; /* IRQ for this adapter */ 464 uint32_t irq; /* IRQ for this adapter */
478 uint32_t bios_address; 465 uint32_t bios_address;
479 uint32_t mem_busaddr; /* Mem Base Addr */ 466 uint32_t mem_busaddr; /* Mem Base Addr */
480 ahc_linux_softc_flags flags; 467
468#define AHC_UP_EH_SEMAPHORE 0x1
469 uint32_t flags;
481}; 470};
482 471
483/************************** OS Utility Wrappers *******************************/ 472/************************** OS Utility Wrappers *******************************/