aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c104
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h5
2 files changed, 27 insertions, 82 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 7254ea535a16..fc393bd95f4a 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -373,7 +373,6 @@ static void ahd_linux_handle_scsi_status(struct ahd_softc *,
373 struct scb *); 373 struct scb *);
374static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, 374static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd,
375 struct scsi_cmnd *cmd); 375 struct scsi_cmnd *cmd);
376static void ahd_linux_sem_timeout(u_long arg);
377static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); 376static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
378static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); 377static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
379static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, 378static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
@@ -453,18 +452,13 @@ ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
453 struct ahd_softc *ahd; 452 struct ahd_softc *ahd;
454 struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device); 453 struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
455 int rtn = SCSI_MLQUEUE_HOST_BUSY; 454 int rtn = SCSI_MLQUEUE_HOST_BUSY;
456 unsigned long flags;
457 455
458 ahd = *(struct ahd_softc **)cmd->device->host->hostdata; 456 ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
459 457
460 ahd_lock(ahd, &flags); 458 cmd->scsi_done = scsi_done;
461 if (ahd->platform_data->qfrozen == 0) { 459 cmd->result = CAM_REQ_INPROG << 16;
462 cmd->scsi_done = scsi_done; 460 rtn = ahd_linux_run_command(ahd, dev, cmd);
463 cmd->result = CAM_REQ_INPROG << 16;
464 rtn = ahd_linux_run_command(ahd, dev, cmd);
465 461
466 }
467 ahd_unlock(ahd, &flags);
468 return rtn; 462 return rtn;
469} 463}
470 464
@@ -682,7 +676,6 @@ static int
682ahd_linux_bus_reset(struct scsi_cmnd *cmd) 676ahd_linux_bus_reset(struct scsi_cmnd *cmd)
683{ 677{
684 struct ahd_softc *ahd; 678 struct ahd_softc *ahd;
685 u_long s;
686 int found; 679 int found;
687 680
688 ahd = *(struct ahd_softc **)cmd->device->host->hostdata; 681 ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
@@ -691,10 +684,8 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd)
691 printf("%s: Bus reset called for cmd %p\n", 684 printf("%s: Bus reset called for cmd %p\n",
692 ahd_name(ahd), cmd); 685 ahd_name(ahd), cmd);
693#endif 686#endif
694 ahd_lock(ahd, &s);
695 found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A', 687 found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A',
696 /*initiate reset*/TRUE); 688 /*initiate reset*/TRUE);
697 ahd_unlock(ahd, &s);
698 689
699 if (bootverbose) 690 if (bootverbose)
700 printf("%s: SCSI bus reset delivered. " 691 printf("%s: SCSI bus reset delivered. "
@@ -1194,7 +1185,6 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
1194 memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); 1185 memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
1195 ahd->platform_data->irq = AHD_LINUX_NOIRQ; 1186 ahd->platform_data->irq = AHD_LINUX_NOIRQ;
1196 ahd_lockinit(ahd); 1187 ahd_lockinit(ahd);
1197 init_MUTEX_LOCKED(&ahd->platform_data->eh_sem);
1198 ahd->seltime = (aic79xx_seltime & 0x3) << 4; 1188 ahd->seltime = (aic79xx_seltime & 0x3) << 4;
1199 return (0); 1189 return (0);
1200} 1190}
@@ -1443,6 +1433,9 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
1443 struct ahd_tmode_tstate *tstate; 1433 struct ahd_tmode_tstate *tstate;
1444 u_int col_idx; 1434 u_int col_idx;
1445 uint16_t mask; 1435 uint16_t mask;
1436 unsigned long flags;
1437
1438 ahd_lock(ahd, &flags);
1446 1439
1447 /* 1440 /*
1448 * Get an scb to use. 1441 * Get an scb to use.
@@ -1458,6 +1451,7 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
1458 } 1451 }
1459 if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) { 1452 if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
1460 ahd->flags |= AHD_RESOURCE_SHORTAGE; 1453 ahd->flags |= AHD_RESOURCE_SHORTAGE;
1454 ahd_unlock(ahd, &flags);
1461 return SCSI_MLQUEUE_HOST_BUSY; 1455 return SCSI_MLQUEUE_HOST_BUSY;
1462 } 1456 }
1463 1457
@@ -1583,6 +1577,8 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
1583 scb->flags |= SCB_ACTIVE; 1577 scb->flags |= SCB_ACTIVE;
1584 ahd_queue_scb(ahd, scb); 1578 ahd_queue_scb(ahd, scb);
1585 1579
1580 ahd_unlock(ahd, &flags);
1581
1586 return 0; 1582 return 0;
1587} 1583}
1588 1584
@@ -1618,7 +1614,6 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
1618 { 1614 {
1619 char buf[80]; 1615 char buf[80];
1620 struct scsi_target *starget; 1616 struct scsi_target *starget;
1621 struct ahd_linux_target *targ;
1622 struct info_str info; 1617 struct info_str info;
1623 struct ahd_initiator_tinfo *tinfo; 1618 struct ahd_initiator_tinfo *tinfo;
1624 struct ahd_tmode_tstate *tstate; 1619 struct ahd_tmode_tstate *tstate;
@@ -1651,7 +1646,6 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
1651 starget = ahd->platform_data->starget[target]; 1646 starget = ahd->platform_data->starget[target];
1652 if (starget == NULL) 1647 if (starget == NULL)
1653 break; 1648 break;
1654 targ = scsi_transport_target_data(starget);
1655 1649
1656 target_ppr_options = 1650 target_ppr_options =
1657 (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0) 1651 (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
@@ -1803,10 +1797,9 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
1803 if (ahd_get_transaction_status(scb) == CAM_BDR_SENT 1797 if (ahd_get_transaction_status(scb) == CAM_BDR_SENT
1804 || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) 1798 || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
1805 ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); 1799 ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
1806 if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { 1800
1807 ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; 1801 if (ahd->platform_data->eh_done)
1808 up(&ahd->platform_data->eh_sem); 1802 complete(ahd->platform_data->eh_done);
1809 }
1810 } 1803 }
1811 1804
1812 ahd_free_scb(ahd, scb); 1805 ahd_free_scb(ahd, scb);
@@ -2030,60 +2023,16 @@ ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
2030 cmd->scsi_done(cmd); 2023 cmd->scsi_done(cmd);
2031} 2024}
2032 2025
2033static void
2034ahd_linux_sem_timeout(u_long arg)
2035{
2036 struct ahd_softc *ahd;
2037 u_long s;
2038
2039 ahd = (struct ahd_softc *)arg;
2040
2041 ahd_lock(ahd, &s);
2042 if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
2043 ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
2044 up(&ahd->platform_data->eh_sem);
2045 }
2046 ahd_unlock(ahd, &s);
2047}
2048
2049void 2026void
2050ahd_freeze_simq(struct ahd_softc *ahd) 2027ahd_freeze_simq(struct ahd_softc *ahd)
2051{ 2028{
2052 unsigned long s; 2029 scsi_block_requests(ahd->platform_data->host);
2053
2054 ahd_lock(ahd, &s);
2055 ahd->platform_data->qfrozen++;
2056 if (ahd->platform_data->qfrozen == 1) {
2057 scsi_block_requests(ahd->platform_data->host);
2058 ahd_platform_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
2059 CAM_LUN_WILDCARD, SCB_LIST_NULL,
2060 ROLE_INITIATOR, CAM_REQUEUE_REQ);
2061 }
2062 ahd_unlock(ahd, &s);
2063} 2030}
2064 2031
2065void 2032void
2066ahd_release_simq(struct ahd_softc *ahd) 2033ahd_release_simq(struct ahd_softc *ahd)
2067{ 2034{
2068 u_long s; 2035 scsi_unblock_requests(ahd->platform_data->host);
2069 int unblock_reqs;
2070
2071 unblock_reqs = 0;
2072 ahd_lock(ahd, &s);
2073 if (ahd->platform_data->qfrozen > 0)
2074 ahd->platform_data->qfrozen--;
2075 if (ahd->platform_data->qfrozen == 0) {
2076 unblock_reqs = 1;
2077 }
2078 ahd_unlock(ahd, &s);
2079 /*
2080 * There is still a race here. The mid-layer
2081 * should keep its own freeze count and use
2082 * a bottom half handler to run the queues
2083 * so we can unblock with our own lock held.
2084 */
2085 if (unblock_reqs)
2086 scsi_unblock_requests(ahd->platform_data->host);
2087} 2036}
2088 2037
2089static int 2038static int
@@ -2344,30 +2293,29 @@ done:
2344 if (paused) 2293 if (paused)
2345 ahd_unpause(ahd); 2294 ahd_unpause(ahd);
2346 if (wait) { 2295 if (wait) {
2347 struct timer_list timer; 2296 DECLARE_COMPLETION(done);
2348 int ret;
2349 2297
2350 ahd->platform_data->flags |= AHD_SCB_UP_EH_SEM; 2298 ahd->platform_data->eh_done = &done;
2351 ahd_unlock(ahd, &flags); 2299 ahd_unlock(ahd, &flags);
2352 2300
2353 init_timer(&timer);
2354 timer.data = (u_long)ahd;
2355 timer.expires = jiffies + (5 * HZ);
2356 timer.function = ahd_linux_sem_timeout;
2357 add_timer(&timer);
2358 printf("%s: Recovery code sleeping\n", ahd_name(ahd)); 2301 printf("%s: Recovery code sleeping\n", ahd_name(ahd));
2359 down(&ahd->platform_data->eh_sem); 2302 if (!wait_for_completion_timeout(&done, 5 * HZ)) {
2360 printf("%s: Recovery code awake\n", ahd_name(ahd)); 2303 ahd_lock(ahd, &flags);
2361 ret = del_timer_sync(&timer); 2304 ahd->platform_data->eh_done = NULL;
2362 if (ret == 0) { 2305 ahd_unlock(ahd, &flags);
2363 printf("%s: Timer Expired (active %d)\n", 2306 printf("%s: Timer Expired (active %d)\n",
2364 ahd_name(ahd), dev->active); 2307 ahd_name(ahd), dev->active);
2365 retval = FAILED; 2308 retval = FAILED;
2366 } 2309 }
2310 printf("Recovery code awake\n");
2367 } else 2311 } else
2368 ahd_unlock(ahd, &flags); 2312 ahd_unlock(ahd, &flags);
2369 2313
2370 return (retval); 2314 if (retval != SUCCESS)
2315 printf("%s: Command abort returning 0x%x\n",
2316 ahd_name(ahd), retval);
2317
2318 return retval;
2371} 2319}
2372 2320
2373static void ahd_linux_set_width(struct scsi_target *starget, int width) 2321static void ahd_linux_set_width(struct scsi_target *starget, int width)
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 9cb101345107..599e3940db16 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -381,15 +381,12 @@ struct ahd_platform_data {
381 struct scsi_target *starget[AHD_NUM_TARGETS]; 381 struct scsi_target *starget[AHD_NUM_TARGETS];
382 382
383 spinlock_t spin_lock; 383 spinlock_t spin_lock;
384 u_int qfrozen; 384 struct completion *eh_done;
385 struct semaphore eh_sem;
386 struct Scsi_Host *host; /* pointer to scsi host */ 385 struct Scsi_Host *host; /* pointer to scsi host */
387#define AHD_LINUX_NOIRQ ((uint32_t)~0) 386#define AHD_LINUX_NOIRQ ((uint32_t)~0)
388 uint32_t irq; /* IRQ for this adapter */ 387 uint32_t irq; /* IRQ for this adapter */
389 uint32_t bios_address; 388 uint32_t bios_address;
390 uint32_t mem_busaddr; /* Mem Base Addr */ 389 uint32_t mem_busaddr; /* Mem Base Addr */
391#define AHD_SCB_UP_EH_SEM 0x1
392 uint32_t flags;
393}; 390};
394 391
395/************************** OS Utility Wrappers *******************************/ 392/************************** OS Utility Wrappers *******************************/