aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic7xxx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aic7xxx')
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c183
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h8
2 files changed, 79 insertions, 112 deletions
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index ca796b9d737b..c03f29486071 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -430,7 +430,6 @@ static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
430static void ahc_linux_sem_timeout(u_long arg); 430static void ahc_linux_sem_timeout(u_long arg);
431static void ahc_linux_freeze_simq(struct ahc_softc *ahc); 431static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
432static void ahc_linux_release_simq(u_long arg); 432static void ahc_linux_release_simq(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); 433static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
435static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); 434static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
436static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, 435static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
@@ -457,7 +456,7 @@ static int ahc_linux_next_unit(void);
457/********************************* Inlines ************************************/ 456/********************************* Inlines ************************************/
458static __inline struct ahc_linux_device* 457static __inline struct ahc_linux_device*
459 ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, 458 ahc_linux_get_device(struct ahc_softc *ahc, u_int channel,
460 u_int target, u_int lun, int alloc); 459 u_int target, u_int lun);
461static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); 460static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
462 461
463static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, 462static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
@@ -466,7 +465,7 @@ static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
466 465
467static __inline struct ahc_linux_device* 466static __inline struct ahc_linux_device*
468ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, 467ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target,
469 u_int lun, int alloc) 468 u_int lun)
470{ 469{
471 struct ahc_linux_target *targ; 470 struct ahc_linux_target *targ;
472 struct ahc_linux_device *dev; 471 struct ahc_linux_device *dev;
@@ -476,18 +475,9 @@ ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target,
476 if (channel != 0) 475 if (channel != 0)
477 target_offset += 8; 476 target_offset += 8;
478 targ = ahc->platform_data->targets[target_offset]; 477 targ = ahc->platform_data->targets[target_offset];
479 if (targ == NULL) { 478 BUG_ON(targ == NULL);
480 if (alloc != 0) {
481 targ = ahc_linux_alloc_target(ahc, channel, target);
482 if (targ == NULL)
483 return (NULL);
484 } else
485 return (NULL);
486 }
487 dev = targ->devices[lun]; 479 dev = targ->devices[lun];
488 if (dev == NULL && alloc != 0) 480 return dev;
489 dev = ahc_linux_alloc_device(ahc, targ, lun);
490 return (dev);
491} 481}
492 482
493static __inline void 483static __inline void
@@ -640,7 +630,7 @@ ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
640 return SCSI_MLQUEUE_HOST_BUSY; 630 return SCSI_MLQUEUE_HOST_BUSY;
641 631
642 dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id, 632 dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
643 cmd->device->lun, /*alloc*/TRUE); 633 cmd->device->lun);
644 BUG_ON(dev == NULL); 634 BUG_ON(dev == NULL);
645 635
646 cmd->result = CAM_REQ_INPROG << 16; 636 cmd->result = CAM_REQ_INPROG << 16;
@@ -652,11 +642,69 @@ static int
652ahc_linux_slave_alloc(struct scsi_device *device) 642ahc_linux_slave_alloc(struct scsi_device *device)
653{ 643{
654 struct ahc_softc *ahc; 644 struct ahc_softc *ahc;
645 struct ahc_linux_target *targ;
646 struct scsi_target *starget = device->sdev_target;
647 struct ahc_linux_device *dev;
648 u_int target_offset;
649
650 target_offset = starget->id;
651 if (starget->channel != 0)
652 target_offset += 8;
655 653
656 ahc = *((struct ahc_softc **)device->host->hostdata); 654 ahc = *((struct ahc_softc **)device->host->hostdata);
657 if (bootverbose) 655 if (bootverbose)
658 printf("%s: Slave Alloc %d\n", ahc_name(ahc), device->id); 656 printf("%s: Slave Alloc %d\n", ahc_name(ahc), device->id);
659 return (0); 657 targ = ahc->platform_data->targets[target_offset];
658 if (targ == NULL) {
659 targ = ahc_linux_alloc_target(ahc, starget->channel, starget->id);
660 struct seeprom_config *sc = ahc->seep_config;
661 if (targ == NULL)
662 return -ENOMEM;
663 if (sc) {
664 unsigned short scsirate;
665 struct ahc_devinfo devinfo;
666 struct ahc_initiator_tinfo *tinfo;
667 struct ahc_tmode_tstate *tstate;
668 char channel = starget->channel + 'A';
669 unsigned int our_id = ahc->our_id;
670
671 if (starget->channel)
672 our_id = ahc->our_id_b;
673
674 if ((ahc->features & AHC_ULTRA2) != 0) {
675 scsirate = sc->device_flags[target_offset] & CFXFER;
676 } else {
677 scsirate = (sc->device_flags[target_offset] & CFXFER) << 4;
678 if (sc->device_flags[target_offset] & CFSYNCH)
679 scsirate |= SOFS;
680 }
681 if (sc->device_flags[target_offset] & CFWIDEB) {
682 scsirate |= WIDEXFER;
683 spi_max_width(starget) = 1;
684 } else
685 spi_max_width(starget) = 0;
686 spi_min_period(starget) =
687 ahc_find_period(ahc, scsirate, AHC_SYNCRATE_DT);
688 tinfo = ahc_fetch_transinfo(ahc, channel, ahc->our_id,
689 targ->target, &tstate);
690 ahc_compile_devinfo(&devinfo, our_id, targ->target,
691 CAM_LUN_WILDCARD, channel,
692 ROLE_INITIATOR);
693 ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0,
694 AHC_TRANS_GOAL, /*paused*/FALSE);
695 ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
696 AHC_TRANS_GOAL, /*paused*/FALSE);
697 }
698
699 }
700 dev = targ->devices[device->lun];
701 if (dev == NULL) {
702 dev = ahc_linux_alloc_device(ahc, targ, device->lun);
703 if (dev == NULL)
704 return -ENOMEM;
705 }
706
707 return 0;
660} 708}
661 709
662static int 710static int
@@ -666,27 +714,20 @@ ahc_linux_slave_configure(struct scsi_device *device)
666 struct ahc_linux_device *dev; 714 struct ahc_linux_device *dev;
667 715
668 ahc = *((struct ahc_softc **)device->host->hostdata); 716 ahc = *((struct ahc_softc **)device->host->hostdata);
717
669 if (bootverbose) 718 if (bootverbose)
670 printf("%s: Slave Configure %d\n", ahc_name(ahc), device->id); 719 printf("%s: Slave Configure %d\n", ahc_name(ahc), device->id);
671 /* 720
672 * Since Linux has attached to the device, configure 721 dev = ahc_linux_get_device(ahc, device->channel, device->id,
673 * it so we don't free and allocate the device 722 device->lun);
674 * structure on every command. 723 dev->scsi_device = device;
675 */ 724 ahc_linux_device_queue_depth(ahc, dev);
676 dev = ahc_linux_get_device(ahc, device->channel,
677 device->id, device->lun,
678 /*alloc*/TRUE);
679 if (dev != NULL) {
680 dev->flags &= ~AHC_DEV_UNCONFIGURED;
681 dev->scsi_device = device;
682 ahc_linux_device_queue_depth(ahc, dev);
683 }
684 725
685 /* Initial Domain Validation */ 726 /* Initial Domain Validation */
686 if (!spi_initial_dv(device->sdev_target)) 727 if (!spi_initial_dv(device->sdev_target))
687 spi_dv_device(device); 728 spi_dv_device(device);
688 729
689 return (0); 730 return 0;
690} 731}
691 732
692static void 733static void
@@ -699,22 +740,11 @@ ahc_linux_slave_destroy(struct scsi_device *device)
699 if (bootverbose) 740 if (bootverbose)
700 printf("%s: Slave Destroy %d\n", ahc_name(ahc), device->id); 741 printf("%s: Slave Destroy %d\n", ahc_name(ahc), device->id);
701 dev = ahc_linux_get_device(ahc, device->channel, 742 dev = ahc_linux_get_device(ahc, device->channel,
702 device->id, device->lun, 743 device->id, device->lun);
703 /*alloc*/FALSE); 744
704 /* 745 BUG_ON(dev->active);
705 * Filter out "silly" deletions of real devices by only 746
706 * deleting devices that have had slave_configure() 747 ahc_linux_free_device(ahc, dev);
707 * called on them. All other devices that have not
708 * been configured will automatically be deleted by
709 * the refcounting process.
710 */
711 if (dev != NULL
712 && (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) {
713 dev->flags |= AHC_DEV_UNCONFIGURED;
714 if (dev->active == 0
715 && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
716 ahc_linux_free_device(ahc, dev);
717 }
718} 748}
719 749
720#if defined(__i386__) 750#if defined(__i386__)
@@ -1361,7 +1391,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
1361 1391
1362 dev = ahc_linux_get_device(ahc, devinfo->channel - 'A', 1392 dev = ahc_linux_get_device(ahc, devinfo->channel - 'A',
1363 devinfo->target, 1393 devinfo->target,
1364 devinfo->lun, /*alloc*/FALSE); 1394 devinfo->lun);
1365 if (dev == NULL) 1395 if (dev == NULL)
1366 return; 1396 return;
1367 was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED); 1397 was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED);
@@ -1793,8 +1823,6 @@ ahc_linux_alloc_device(struct ahc_softc *ahc,
1793 if (dev == NULL) 1823 if (dev == NULL)
1794 return (NULL); 1824 return (NULL);
1795 memset(dev, 0, sizeof(*dev)); 1825 memset(dev, 0, sizeof(*dev));
1796 init_timer(&dev->timer);
1797 dev->flags = AHC_DEV_UNCONFIGURED;
1798 dev->lun = lun; 1826 dev->lun = lun;
1799 dev->target = targ; 1827 dev->target = targ;
1800 1828
@@ -1817,7 +1845,7 @@ ahc_linux_alloc_device(struct ahc_softc *ahc,
1817} 1845}
1818 1846
1819static void 1847static void
1820__ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) 1848ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
1821{ 1849{
1822 struct ahc_linux_target *targ; 1850 struct ahc_linux_target *targ;
1823 1851
@@ -1829,13 +1857,6 @@ __ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
1829 ahc_linux_free_target(ahc, targ); 1857 ahc_linux_free_target(ahc, targ);
1830} 1858}
1831 1859
1832static void
1833ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
1834{
1835 del_timer_sync(&dev->timer);
1836 __ahc_linux_free_device(ahc, dev);
1837}
1838
1839void 1860void
1840ahc_send_async(struct ahc_softc *ahc, char channel, 1861ahc_send_async(struct ahc_softc *ahc, char channel,
1841 u_int target, u_int lun, ac_code code, void *arg) 1862 u_int target, u_int lun, ac_code code, void *arg)
@@ -2008,8 +2029,6 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
2008 } 2029 }
2009 } else if (ahc_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { 2030 } else if (ahc_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
2010 ahc_linux_handle_scsi_status(ahc, dev, scb); 2031 ahc_linux_handle_scsi_status(ahc, dev, scb);
2011 } else if (ahc_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
2012 dev->flags |= AHC_DEV_UNCONFIGURED;
2013 } 2032 }
2014 2033
2015 if (dev->openings == 1 2034 if (dev->openings == 1
@@ -2031,11 +2050,6 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
2031 if (dev->active == 0) 2050 if (dev->active == 0)
2032 dev->commands_since_idle_or_otag = 0; 2051 dev->commands_since_idle_or_otag = 0;
2033 2052
2034 if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0
2035 && dev->active == 0
2036 && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
2037 ahc_linux_free_device(ahc, dev);
2038
2039 if ((scb->flags & SCB_RECOVERY_SCB) != 0) { 2053 if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
2040 printf("Recovery SCB completes\n"); 2054 printf("Recovery SCB completes\n");
2041 if (ahc_get_transaction_status(scb) == CAM_BDR_SENT 2055 if (ahc_get_transaction_status(scb) == CAM_BDR_SENT
@@ -2174,27 +2188,6 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc,
2174 ahc_platform_set_tags(ahc, &devinfo, 2188 ahc_platform_set_tags(ahc, &devinfo,
2175 (dev->flags & AHC_DEV_Q_BASIC) 2189 (dev->flags & AHC_DEV_Q_BASIC)
2176 ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED); 2190 ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED);
2177 /* FALLTHROUGH */
2178 }
2179 case SCSI_STATUS_BUSY:
2180 {
2181 /*
2182 * Set a short timer to defer sending commands for
2183 * a bit since Linux will not delay in this case.
2184 */
2185 if ((dev->flags & AHC_DEV_TIMER_ACTIVE) != 0) {
2186 printf("%s:%c:%d: Device Timer still active during "
2187 "busy processing\n", ahc_name(ahc),
2188 dev->target->channel, dev->target->target);
2189 break;
2190 }
2191 dev->flags |= AHC_DEV_TIMER_ACTIVE;
2192 dev->qfrozen++;
2193 init_timer(&dev->timer);
2194 dev->timer.data = (u_long)dev;
2195 dev->timer.expires = jiffies + (HZ/2);
2196 dev->timer.function = ahc_linux_dev_timed_unfreeze;
2197 add_timer(&dev->timer);
2198 break; 2191 break;
2199 } 2192 }
2200 } 2193 }
@@ -2326,24 +2319,6 @@ ahc_linux_release_simq(u_long arg)
2326 scsi_unblock_requests(ahc->platform_data->host); 2319 scsi_unblock_requests(ahc->platform_data->host);
2327} 2320}
2328 2321
2329static void
2330ahc_linux_dev_timed_unfreeze(u_long arg)
2331{
2332 struct ahc_linux_device *dev;
2333 struct ahc_softc *ahc;
2334 u_long s;
2335
2336 dev = (struct ahc_linux_device *)arg;
2337 ahc = dev->target->ahc;
2338 ahc_lock(ahc, &s);
2339 dev->flags &= ~AHC_DEV_TIMER_ACTIVE;
2340 if (dev->qfrozen > 0)
2341 dev->qfrozen--;
2342 if (dev->active == 0)
2343 __ahc_linux_free_device(ahc, dev);
2344 ahc_unlock(ahc, &s);
2345}
2346
2347static int 2322static int
2348ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) 2323ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
2349{ 2324{
@@ -2384,7 +2359,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
2384 * command, return success. 2359 * command, return success.
2385 */ 2360 */
2386 dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id, 2361 dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
2387 cmd->device->lun, /*alloc*/FALSE); 2362 cmd->device->lun);
2388 2363
2389 if (dev == NULL) { 2364 if (dev == NULL) {
2390 /* 2365 /*
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index e70c1fa47db2..30c200d5bcd5 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -322,13 +322,10 @@ struct ahc_cmd {
322 */ 322 */
323TAILQ_HEAD(ahc_busyq, ahc_cmd); 323TAILQ_HEAD(ahc_busyq, ahc_cmd);
324typedef enum { 324typedef enum {
325 AHC_DEV_UNCONFIGURED = 0x01,
326 AHC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ 325 AHC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
327 AHC_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */
328 AHC_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ 326 AHC_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */
329 AHC_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ 327 AHC_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */
330 AHC_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ 328 AHC_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */
331 AHC_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */
332} ahc_linux_dev_flags; 329} ahc_linux_dev_flags;
333 330
334struct ahc_linux_target; 331struct ahc_linux_target;
@@ -374,11 +371,6 @@ struct ahc_linux_device {
374 ahc_linux_dev_flags flags; 371 ahc_linux_dev_flags flags;
375 372
376 /* 373 /*
377 * Per device timer.
378 */
379 struct timer_list timer;
380
381 /*
382 * The high limit for the tags variable. 374 * The high limit for the tags variable.
383 */ 375 */
384 u_int maxtags; 376 u_int maxtags;