diff options
-rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm.c | 1681 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm.h | 40 |
2 files changed, 10 insertions, 1711 deletions
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 6b6ee0a52a46..d74b99dab7ec 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -275,39 +275,6 @@ static adapter_tag_info_t aic7xxx_tag_info[] = | |||
275 | }; | 275 | }; |
276 | 276 | ||
277 | /* | 277 | /* |
278 | * DV option: | ||
279 | * | ||
280 | * positive value = DV Enabled | ||
281 | * zero = DV Disabled | ||
282 | * negative value = DV Default for adapter type/seeprom | ||
283 | */ | ||
284 | #ifdef CONFIG_AIC7XXX_DV_SETTING | ||
285 | #define AIC7XXX_CONFIGED_DV CONFIG_AIC7XXX_DV_SETTING | ||
286 | #else | ||
287 | #define AIC7XXX_CONFIGED_DV -1 | ||
288 | #endif | ||
289 | |||
290 | static int8_t aic7xxx_dv_settings[] = | ||
291 | { | ||
292 | AIC7XXX_CONFIGED_DV, | ||
293 | AIC7XXX_CONFIGED_DV, | ||
294 | AIC7XXX_CONFIGED_DV, | ||
295 | AIC7XXX_CONFIGED_DV, | ||
296 | AIC7XXX_CONFIGED_DV, | ||
297 | AIC7XXX_CONFIGED_DV, | ||
298 | AIC7XXX_CONFIGED_DV, | ||
299 | AIC7XXX_CONFIGED_DV, | ||
300 | AIC7XXX_CONFIGED_DV, | ||
301 | AIC7XXX_CONFIGED_DV, | ||
302 | AIC7XXX_CONFIGED_DV, | ||
303 | AIC7XXX_CONFIGED_DV, | ||
304 | AIC7XXX_CONFIGED_DV, | ||
305 | AIC7XXX_CONFIGED_DV, | ||
306 | AIC7XXX_CONFIGED_DV, | ||
307 | AIC7XXX_CONFIGED_DV | ||
308 | }; | ||
309 | |||
310 | /* | ||
311 | * There should be a specific return value for this in scsi.h, but | 278 | * There should be a specific return value for this in scsi.h, but |
312 | * it seems that most drivers ignore it. | 279 | * it seems that most drivers ignore it. |
313 | */ | 280 | */ |
@@ -454,7 +421,6 @@ MODULE_PARM_DESC(aic7xxx, | |||
454 | " tag_info:<tag_str> Set per-target tag depth\n" | 421 | " tag_info:<tag_str> Set per-target tag depth\n" |
455 | " global_tag_depth:<int> Global tag depth for every target\n" | 422 | " global_tag_depth:<int> Global tag depth for every target\n" |
456 | " on every bus\n" | 423 | " on every bus\n" |
457 | " dv:<dv_settings> Set per-controller Domain Validation Setting.\n" | ||
458 | " seltime:<int> Selection Timeout\n" | 424 | " seltime:<int> Selection Timeout\n" |
459 | " (0/256ms,1/128ms,2/64ms,3/32ms)\n" | 425 | " (0/256ms,1/128ms,2/64ms,3/32ms)\n" |
460 | "\n" | 426 | "\n" |
@@ -471,7 +437,6 @@ static void ahc_linux_handle_scsi_status(struct ahc_softc *, | |||
471 | struct scb *); | 437 | struct scb *); |
472 | static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, | 438 | static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, |
473 | Scsi_Cmnd *cmd); | 439 | Scsi_Cmnd *cmd); |
474 | static void ahc_linux_filter_inquiry(struct ahc_softc*, struct ahc_devinfo*); | ||
475 | static void ahc_linux_sem_timeout(u_long arg); | 440 | static void ahc_linux_sem_timeout(u_long arg); |
476 | static void ahc_linux_freeze_simq(struct ahc_softc *ahc); | 441 | static void ahc_linux_freeze_simq(struct ahc_softc *ahc); |
477 | static void ahc_linux_release_simq(u_long arg); | 442 | static void ahc_linux_release_simq(u_long arg); |
@@ -480,49 +445,8 @@ static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag); | |||
480 | static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); | 445 | static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); |
481 | static void ahc_linux_size_nseg(void); | 446 | static void ahc_linux_size_nseg(void); |
482 | static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc); | 447 | static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc); |
483 | static void ahc_linux_start_dv(struct ahc_softc *ahc); | ||
484 | static void ahc_linux_dv_timeout(struct scsi_cmnd *cmd); | ||
485 | static int ahc_linux_dv_thread(void *data); | ||
486 | static void ahc_linux_kill_dv_thread(struct ahc_softc *ahc); | ||
487 | static void ahc_linux_dv_target(struct ahc_softc *ahc, u_int target); | ||
488 | static void ahc_linux_dv_transition(struct ahc_softc *ahc, | ||
489 | struct scsi_cmnd *cmd, | ||
490 | struct ahc_devinfo *devinfo, | ||
491 | struct ahc_linux_target *targ); | ||
492 | static void ahc_linux_dv_fill_cmd(struct ahc_softc *ahc, | ||
493 | struct scsi_cmnd *cmd, | ||
494 | struct ahc_devinfo *devinfo); | ||
495 | static void ahc_linux_dv_inq(struct ahc_softc *ahc, | ||
496 | struct scsi_cmnd *cmd, | ||
497 | struct ahc_devinfo *devinfo, | ||
498 | struct ahc_linux_target *targ, | ||
499 | u_int request_length); | ||
500 | static void ahc_linux_dv_tur(struct ahc_softc *ahc, | ||
501 | struct scsi_cmnd *cmd, | ||
502 | struct ahc_devinfo *devinfo); | ||
503 | static void ahc_linux_dv_rebd(struct ahc_softc *ahc, | ||
504 | struct scsi_cmnd *cmd, | ||
505 | struct ahc_devinfo *devinfo, | ||
506 | struct ahc_linux_target *targ); | ||
507 | static void ahc_linux_dv_web(struct ahc_softc *ahc, | ||
508 | struct scsi_cmnd *cmd, | ||
509 | struct ahc_devinfo *devinfo, | ||
510 | struct ahc_linux_target *targ); | ||
511 | static void ahc_linux_dv_reb(struct ahc_softc *ahc, | ||
512 | struct scsi_cmnd *cmd, | ||
513 | struct ahc_devinfo *devinfo, | ||
514 | struct ahc_linux_target *targ); | ||
515 | static void ahc_linux_dv_su(struct ahc_softc *ahc, | ||
516 | struct scsi_cmnd *cmd, | ||
517 | struct ahc_devinfo *devinfo, | ||
518 | struct ahc_linux_target *targ); | ||
519 | static int ahc_linux_fallback(struct ahc_softc *ahc, | ||
520 | struct ahc_devinfo *devinfo); | ||
521 | static void ahc_linux_dv_complete(Scsi_Cmnd *cmd); | ||
522 | static void ahc_linux_generate_dv_pattern(struct ahc_linux_target *targ); | ||
523 | static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, | 448 | static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, |
524 | struct ahc_devinfo *devinfo); | 449 | struct ahc_devinfo *devinfo); |
525 | static u_int ahc_linux_user_dv_setting(struct ahc_softc *ahc); | ||
526 | static void ahc_linux_device_queue_depth(struct ahc_softc *ahc, | 450 | static void ahc_linux_device_queue_depth(struct ahc_softc *ahc, |
527 | struct ahc_linux_device *dev); | 451 | struct ahc_linux_device *dev); |
528 | static struct ahc_linux_target* ahc_linux_alloc_target(struct ahc_softc*, | 452 | static struct ahc_linux_target* ahc_linux_alloc_target(struct ahc_softc*, |
@@ -538,7 +462,6 @@ static void ahc_linux_run_device_queue(struct ahc_softc*, | |||
538 | struct ahc_linux_device*); | 462 | struct ahc_linux_device*); |
539 | static void ahc_linux_setup_tag_info_global(char *p); | 463 | static void ahc_linux_setup_tag_info_global(char *p); |
540 | static aic_option_callback_t ahc_linux_setup_tag_info; | 464 | static aic_option_callback_t ahc_linux_setup_tag_info; |
541 | static aic_option_callback_t ahc_linux_setup_dv; | ||
542 | static int aic7xxx_setup(char *s); | 465 | static int aic7xxx_setup(char *s); |
543 | static int ahc_linux_next_unit(void); | 466 | static int ahc_linux_next_unit(void); |
544 | static void ahc_runq_tasklet(unsigned long data); | 467 | static void ahc_runq_tasklet(unsigned long data); |
@@ -667,8 +590,7 @@ ahc_linux_next_device_to_run(struct ahc_softc *ahc) | |||
667 | { | 590 | { |
668 | 591 | ||
669 | if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0 | 592 | if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0 |
670 | || (ahc->platform_data->qfrozen != 0 | 593 | || (ahc->platform_data->qfrozen != 0)) |
671 | && AHC_DV_SIMQ_FROZEN(ahc) == 0)) | ||
672 | return (NULL); | 594 | return (NULL); |
673 | return (TAILQ_FIRST(&ahc->platform_data->device_runq)); | 595 | return (TAILQ_FIRST(&ahc->platform_data->device_runq)); |
674 | } | 596 | } |
@@ -966,8 +888,7 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) | |||
966 | * DV commands through so long as we are only frozen to | 888 | * DV commands through so long as we are only frozen to |
967 | * perform DV. | 889 | * perform DV. |
968 | */ | 890 | */ |
969 | if (ahc->platform_data->qfrozen != 0 | 891 | if (ahc->platform_data->qfrozen != 0) { |
970 | && AHC_DV_CMD(cmd) == 0) { | ||
971 | 892 | ||
972 | ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); | 893 | ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); |
973 | ahc_linux_queue_cmd_complete(ahc, cmd); | 894 | ahc_linux_queue_cmd_complete(ahc, cmd); |
@@ -1034,6 +955,11 @@ ahc_linux_slave_configure(Scsi_Device *device) | |||
1034 | ahc_linux_device_queue_depth(ahc, dev); | 955 | ahc_linux_device_queue_depth(ahc, dev); |
1035 | } | 956 | } |
1036 | ahc_midlayer_entrypoint_unlock(ahc, &flags); | 957 | ahc_midlayer_entrypoint_unlock(ahc, &flags); |
958 | |||
959 | /* Initial Domain Validation */ | ||
960 | if (!spi_initial_dv(device->sdev_target)) | ||
961 | spi_dv_device(device); | ||
962 | |||
1037 | return (0); | 963 | return (0); |
1038 | } | 964 | } |
1039 | 965 | ||
@@ -1549,18 +1475,6 @@ ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) | |||
1549 | } | 1475 | } |
1550 | } | 1476 | } |
1551 | 1477 | ||
1552 | static void | ||
1553 | ahc_linux_setup_dv(u_long arg, int instance, int targ, int32_t value) | ||
1554 | { | ||
1555 | |||
1556 | if ((instance >= 0) | ||
1557 | && (instance < NUM_ELEMENTS(aic7xxx_dv_settings))) { | ||
1558 | aic7xxx_dv_settings[instance] = value; | ||
1559 | if (bootverbose) | ||
1560 | printf("dv[%d] = %d\n", instance, value); | ||
1561 | } | ||
1562 | } | ||
1563 | |||
1564 | /* | 1478 | /* |
1565 | * Handle Linux boot parameters. This routine allows for assigning a value | 1479 | * Handle Linux boot parameters. This routine allows for assigning a value |
1566 | * to a parameter with a ':' between the parameter and the value. | 1480 | * to a parameter with a ':' between the parameter and the value. |
@@ -1620,9 +1534,6 @@ aic7xxx_setup(char *s) | |||
1620 | } else if (strncmp(p, "tag_info", n) == 0) { | 1534 | } else if (strncmp(p, "tag_info", n) == 0) { |
1621 | s = aic_parse_brace_option("tag_info", p + n, end, | 1535 | s = aic_parse_brace_option("tag_info", p + n, end, |
1622 | 2, ahc_linux_setup_tag_info, 0); | 1536 | 2, ahc_linux_setup_tag_info, 0); |
1623 | } else if (strncmp(p, "dv", n) == 0) { | ||
1624 | s = aic_parse_brace_option("dv", p + n, end, 1, | ||
1625 | ahc_linux_setup_dv, 0); | ||
1626 | } else if (p[n] == ':') { | 1537 | } else if (p[n] == ':') { |
1627 | *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); | 1538 | *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); |
1628 | } else if (strncmp(p, "verbose", n) == 0) { | 1539 | } else if (strncmp(p, "verbose", n) == 0) { |
@@ -1645,7 +1556,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template) | |||
1645 | struct Scsi_Host *host; | 1556 | struct Scsi_Host *host; |
1646 | char *new_name; | 1557 | char *new_name; |
1647 | u_long s; | 1558 | u_long s; |
1648 | u_int targ_offset; | ||
1649 | 1559 | ||
1650 | template->name = ahc->description; | 1560 | template->name = ahc->description; |
1651 | host = scsi_host_alloc(template, sizeof(struct ahc_softc *)); | 1561 | host = scsi_host_alloc(template, sizeof(struct ahc_softc *)); |
@@ -1681,55 +1591,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template) | |||
1681 | scsi_set_pci_device(host, ahc->dev_softc); | 1591 | scsi_set_pci_device(host, ahc->dev_softc); |
1682 | #endif | 1592 | #endif |
1683 | ahc_linux_initialize_scsi_bus(ahc); | 1593 | ahc_linux_initialize_scsi_bus(ahc); |
1684 | ahc_unlock(ahc, &s); | ||
1685 | ahc->platform_data->dv_pid = kernel_thread(ahc_linux_dv_thread, ahc, 0); | ||
1686 | ahc_lock(ahc, &s); | ||
1687 | if (ahc->platform_data->dv_pid < 0) { | ||
1688 | printf("%s: Failed to create DV thread, error= %d\n", | ||
1689 | ahc_name(ahc), ahc->platform_data->dv_pid); | ||
1690 | return (-ahc->platform_data->dv_pid); | ||
1691 | } | ||
1692 | /* | ||
1693 | * Initially allocate *all* of our linux target objects | ||
1694 | * so that the DV thread will scan them all in parallel | ||
1695 | * just after driver initialization. Any device that | ||
1696 | * does not exist will have its target object destroyed | ||
1697 | * by the selection timeout handler. In the case of a | ||
1698 | * device that appears after the initial DV scan, async | ||
1699 | * negotiation will occur for the first command, and DV | ||
1700 | * will comence should that first command be successful. | ||
1701 | */ | ||
1702 | for (targ_offset = 0; | ||
1703 | targ_offset < host->max_id * (host->max_channel + 1); | ||
1704 | targ_offset++) { | ||
1705 | u_int channel; | ||
1706 | u_int target; | ||
1707 | |||
1708 | channel = 0; | ||
1709 | target = targ_offset; | ||
1710 | if (target > 7 | ||
1711 | && (ahc->features & AHC_TWIN) != 0) { | ||
1712 | channel = 1; | ||
1713 | target &= 0x7; | ||
1714 | } | ||
1715 | /* | ||
1716 | * Skip our own ID. Some Compaq/HP storage devices | ||
1717 | * have enclosure management devices that respond to | ||
1718 | * single bit selection (i.e. selecting ourselves). | ||
1719 | * It is expected that either an external application | ||
1720 | * or a modified kernel will be used to probe this | ||
1721 | * ID if it is appropriate. To accommodate these | ||
1722 | * installations, ahc_linux_alloc_target() will allocate | ||
1723 | * for our ID if asked to do so. | ||
1724 | */ | ||
1725 | if ((channel == 0 && target == ahc->our_id) | ||
1726 | || (channel == 1 && target == ahc->our_id_b)) | ||
1727 | continue; | ||
1728 | |||
1729 | ahc_linux_alloc_target(ahc, channel, target); | ||
1730 | } | ||
1731 | ahc_intr_enable(ahc, TRUE); | 1594 | ahc_intr_enable(ahc, TRUE); |
1732 | ahc_linux_start_dv(ahc); | ||
1733 | ahc_unlock(ahc, &s); | 1595 | ahc_unlock(ahc, &s); |
1734 | 1596 | ||
1735 | host->transportt = ahc_linux_transport_template; | 1597 | host->transportt = ahc_linux_transport_template; |
@@ -1866,8 +1728,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) | |||
1866 | ahc->platform_data->completeq_timer.function = | 1728 | ahc->platform_data->completeq_timer.function = |
1867 | (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue; | 1729 | (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue; |
1868 | init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); | 1730 | init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); |
1869 | init_MUTEX_LOCKED(&ahc->platform_data->dv_sem); | ||
1870 | init_MUTEX_LOCKED(&ahc->platform_data->dv_cmd_sem); | ||
1871 | tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet, | 1731 | tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet, |
1872 | (unsigned long)ahc); | 1732 | (unsigned long)ahc); |
1873 | ahc->seltime = (aic7xxx_seltime & 0x3) << 4; | 1733 | ahc->seltime = (aic7xxx_seltime & 0x3) << 4; |
@@ -1887,7 +1747,6 @@ ahc_platform_free(struct ahc_softc *ahc) | |||
1887 | 1747 | ||
1888 | if (ahc->platform_data != NULL) { | 1748 | if (ahc->platform_data != NULL) { |
1889 | del_timer_sync(&ahc->platform_data->completeq_timer); | 1749 | del_timer_sync(&ahc->platform_data->completeq_timer); |
1890 | ahc_linux_kill_dv_thread(ahc); | ||
1891 | tasklet_kill(&ahc->platform_data->runq_tasklet); | 1750 | tasklet_kill(&ahc->platform_data->runq_tasklet); |
1892 | if (ahc->platform_data->host != NULL) { | 1751 | if (ahc->platform_data->host != NULL) { |
1893 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 1752 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) |
@@ -2126,1331 +1985,6 @@ ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc) | |||
2126 | ahc_unlock(ahc, &flags); | 1985 | ahc_unlock(ahc, &flags); |
2127 | } | 1986 | } |
2128 | 1987 | ||
2129 | static void | ||
2130 | ahc_linux_start_dv(struct ahc_softc *ahc) | ||
2131 | { | ||
2132 | |||
2133 | /* | ||
2134 | * Freeze the simq and signal ahc_linux_queue to not let any | ||
2135 | * more commands through. | ||
2136 | */ | ||
2137 | if ((ahc->platform_data->flags & AHC_DV_ACTIVE) == 0) { | ||
2138 | #ifdef AHC_DEBUG | ||
2139 | if (ahc_debug & AHC_SHOW_DV) | ||
2140 | printf("%s: Waking DV thread\n", ahc_name(ahc)); | ||
2141 | #endif | ||
2142 | |||
2143 | ahc->platform_data->flags |= AHC_DV_ACTIVE; | ||
2144 | ahc_linux_freeze_simq(ahc); | ||
2145 | |||
2146 | /* Wake up the DV kthread */ | ||
2147 | up(&ahc->platform_data->dv_sem); | ||
2148 | } | ||
2149 | } | ||
2150 | |||
2151 | static void | ||
2152 | ahc_linux_kill_dv_thread(struct ahc_softc *ahc) | ||
2153 | { | ||
2154 | u_long s; | ||
2155 | |||
2156 | ahc_lock(ahc, &s); | ||
2157 | if (ahc->platform_data->dv_pid != 0) { | ||
2158 | ahc->platform_data->flags |= AHC_DV_SHUTDOWN; | ||
2159 | ahc_unlock(ahc, &s); | ||
2160 | up(&ahc->platform_data->dv_sem); | ||
2161 | |||
2162 | /* | ||
2163 | * Use the eh_sem as an indicator that the | ||
2164 | * dv thread is exiting. Note that the dv | ||
2165 | * thread must still return after performing | ||
2166 | * the up on our semaphore before it has | ||
2167 | * completely exited this module. Unfortunately, | ||
2168 | * there seems to be no easy way to wait for the | ||
2169 | * exit of a thread for which you are not the | ||
2170 | * parent (dv threads are parented by init). | ||
2171 | * Cross your fingers... | ||
2172 | */ | ||
2173 | down(&ahc->platform_data->eh_sem); | ||
2174 | |||
2175 | /* | ||
2176 | * Mark the dv thread as already dead. This | ||
2177 | * avoids attempting to kill it a second time. | ||
2178 | * This is necessary because we must kill the | ||
2179 | * DV thread before calling ahc_free() in the | ||
2180 | * module shutdown case to avoid bogus locking | ||
2181 | * in the SCSI mid-layer, but we ahc_free() is | ||
2182 | * called without killing the DV thread in the | ||
2183 | * instance detach case, so ahc_platform_free() | ||
2184 | * calls us again to verify that the DV thread | ||
2185 | * is dead. | ||
2186 | */ | ||
2187 | ahc->platform_data->dv_pid = 0; | ||
2188 | } else { | ||
2189 | ahc_unlock(ahc, &s); | ||
2190 | } | ||
2191 | } | ||
2192 | |||
2193 | static int | ||
2194 | ahc_linux_dv_thread(void *data) | ||
2195 | { | ||
2196 | struct ahc_softc *ahc; | ||
2197 | int target; | ||
2198 | u_long s; | ||
2199 | |||
2200 | ahc = (struct ahc_softc *)data; | ||
2201 | |||
2202 | #ifdef AHC_DEBUG | ||
2203 | if (ahc_debug & AHC_SHOW_DV) | ||
2204 | printf("Launching DV Thread\n"); | ||
2205 | #endif | ||
2206 | |||
2207 | /* | ||
2208 | * Complete thread creation. | ||
2209 | */ | ||
2210 | lock_kernel(); | ||
2211 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
2212 | /* | ||
2213 | * Don't care about any signals. | ||
2214 | */ | ||
2215 | siginitsetinv(¤t->blocked, 0); | ||
2216 | |||
2217 | daemonize(); | ||
2218 | sprintf(current->comm, "ahc_dv_%d", ahc->unit); | ||
2219 | #else | ||
2220 | daemonize("ahc_dv_%d", ahc->unit); | ||
2221 | current->flags |= PF_FREEZE; | ||
2222 | #endif | ||
2223 | unlock_kernel(); | ||
2224 | |||
2225 | while (1) { | ||
2226 | /* | ||
2227 | * Use down_interruptible() rather than down() to | ||
2228 | * avoid inclusion in the load average. | ||
2229 | */ | ||
2230 | down_interruptible(&ahc->platform_data->dv_sem); | ||
2231 | |||
2232 | /* Check to see if we've been signaled to exit */ | ||
2233 | ahc_lock(ahc, &s); | ||
2234 | if ((ahc->platform_data->flags & AHC_DV_SHUTDOWN) != 0) { | ||
2235 | ahc_unlock(ahc, &s); | ||
2236 | break; | ||
2237 | } | ||
2238 | ahc_unlock(ahc, &s); | ||
2239 | |||
2240 | #ifdef AHC_DEBUG | ||
2241 | if (ahc_debug & AHC_SHOW_DV) | ||
2242 | printf("%s: Beginning Domain Validation\n", | ||
2243 | ahc_name(ahc)); | ||
2244 | #endif | ||
2245 | |||
2246 | /* | ||
2247 | * Wait for any pending commands to drain before proceeding. | ||
2248 | */ | ||
2249 | ahc_lock(ahc, &s); | ||
2250 | while (LIST_FIRST(&ahc->pending_scbs) != NULL) { | ||
2251 | ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_EMPTY; | ||
2252 | ahc_unlock(ahc, &s); | ||
2253 | down_interruptible(&ahc->platform_data->dv_sem); | ||
2254 | ahc_lock(ahc, &s); | ||
2255 | } | ||
2256 | |||
2257 | /* | ||
2258 | * Wait for the SIMQ to be released so that DV is the | ||
2259 | * only reason the queue is frozen. | ||
2260 | */ | ||
2261 | while (AHC_DV_SIMQ_FROZEN(ahc) == 0) { | ||
2262 | ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE; | ||
2263 | ahc_unlock(ahc, &s); | ||
2264 | down_interruptible(&ahc->platform_data->dv_sem); | ||
2265 | ahc_lock(ahc, &s); | ||
2266 | } | ||
2267 | ahc_unlock(ahc, &s); | ||
2268 | |||
2269 | for (target = 0; target < AHC_NUM_TARGETS; target++) | ||
2270 | ahc_linux_dv_target(ahc, target); | ||
2271 | |||
2272 | ahc_lock(ahc, &s); | ||
2273 | ahc->platform_data->flags &= ~AHC_DV_ACTIVE; | ||
2274 | ahc_unlock(ahc, &s); | ||
2275 | |||
2276 | /* | ||
2277 | * Release the SIMQ so that normal commands are | ||
2278 | * allowed to continue on the bus. | ||
2279 | */ | ||
2280 | ahc_linux_release_simq((u_long)ahc); | ||
2281 | } | ||
2282 | up(&ahc->platform_data->eh_sem); | ||
2283 | return (0); | ||
2284 | } | ||
2285 | |||
2286 | #define AHC_LINUX_DV_INQ_SHORT_LEN 36 | ||
2287 | #define AHC_LINUX_DV_INQ_LEN 256 | ||
2288 | #define AHC_LINUX_DV_TIMEOUT (HZ / 4) | ||
2289 | |||
2290 | #define AHC_SET_DV_STATE(ahc, targ, newstate) \ | ||
2291 | ahc_set_dv_state(ahc, targ, newstate, __LINE__) | ||
2292 | |||
2293 | static __inline void | ||
2294 | ahc_set_dv_state(struct ahc_softc *ahc, struct ahc_linux_target *targ, | ||
2295 | ahc_dv_state newstate, u_int line) | ||
2296 | { | ||
2297 | ahc_dv_state oldstate; | ||
2298 | |||
2299 | oldstate = targ->dv_state; | ||
2300 | #ifdef AHC_DEBUG | ||
2301 | if (ahc_debug & AHC_SHOW_DV) | ||
2302 | printf("%s:%d: Going from state %d to state %d\n", | ||
2303 | ahc_name(ahc), line, oldstate, newstate); | ||
2304 | #endif | ||
2305 | |||
2306 | if (oldstate == newstate) | ||
2307 | targ->dv_state_retry++; | ||
2308 | else | ||
2309 | targ->dv_state_retry = 0; | ||
2310 | targ->dv_state = newstate; | ||
2311 | } | ||
2312 | |||
2313 | static void | ||
2314 | ahc_linux_dv_target(struct ahc_softc *ahc, u_int target_offset) | ||
2315 | { | ||
2316 | struct ahc_devinfo devinfo; | ||
2317 | struct ahc_linux_target *targ; | ||
2318 | struct scsi_cmnd *cmd; | ||
2319 | struct scsi_device *scsi_dev; | ||
2320 | struct scsi_sense_data *sense; | ||
2321 | uint8_t *buffer; | ||
2322 | u_long s; | ||
2323 | u_int timeout; | ||
2324 | int echo_size; | ||
2325 | |||
2326 | sense = NULL; | ||
2327 | buffer = NULL; | ||
2328 | echo_size = 0; | ||
2329 | ahc_lock(ahc, &s); | ||
2330 | targ = ahc->platform_data->targets[target_offset]; | ||
2331 | if (targ == NULL || (targ->flags & AHC_DV_REQUIRED) == 0) { | ||
2332 | ahc_unlock(ahc, &s); | ||
2333 | return; | ||
2334 | } | ||
2335 | ahc_compile_devinfo(&devinfo, | ||
2336 | targ->channel == 0 ? ahc->our_id : ahc->our_id_b, | ||
2337 | targ->target, /*lun*/0, targ->channel + 'A', | ||
2338 | ROLE_INITIATOR); | ||
2339 | #ifdef AHC_DEBUG | ||
2340 | if (ahc_debug & AHC_SHOW_DV) { | ||
2341 | ahc_print_devinfo(ahc, &devinfo); | ||
2342 | printf("Performing DV\n"); | ||
2343 | } | ||
2344 | #endif | ||
2345 | |||
2346 | ahc_unlock(ahc, &s); | ||
2347 | |||
2348 | cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK); | ||
2349 | scsi_dev = malloc(sizeof(struct scsi_device), M_DEVBUF, M_WAITOK); | ||
2350 | scsi_dev->host = ahc->platform_data->host; | ||
2351 | scsi_dev->id = devinfo.target; | ||
2352 | scsi_dev->lun = devinfo.lun; | ||
2353 | scsi_dev->channel = devinfo.channel - 'A'; | ||
2354 | ahc->platform_data->dv_scsi_dev = scsi_dev; | ||
2355 | |||
2356 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_SHORT_ASYNC); | ||
2357 | |||
2358 | while (targ->dv_state != AHC_DV_STATE_EXIT) { | ||
2359 | timeout = AHC_LINUX_DV_TIMEOUT; | ||
2360 | switch (targ->dv_state) { | ||
2361 | case AHC_DV_STATE_INQ_SHORT_ASYNC: | ||
2362 | case AHC_DV_STATE_INQ_ASYNC: | ||
2363 | case AHC_DV_STATE_INQ_ASYNC_VERIFY: | ||
2364 | /* | ||
2365 | * Set things to async narrow to reduce the | ||
2366 | * chance that the INQ will fail. | ||
2367 | */ | ||
2368 | ahc_lock(ahc, &s); | ||
2369 | ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0, | ||
2370 | AHC_TRANS_GOAL, /*paused*/FALSE); | ||
2371 | ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, | ||
2372 | AHC_TRANS_GOAL, /*paused*/FALSE); | ||
2373 | ahc_unlock(ahc, &s); | ||
2374 | timeout = 10 * HZ; | ||
2375 | targ->flags &= ~AHC_INQ_VALID; | ||
2376 | /* FALLTHROUGH */ | ||
2377 | case AHC_DV_STATE_INQ_VERIFY: | ||
2378 | { | ||
2379 | u_int inq_len; | ||
2380 | |||
2381 | if (targ->dv_state == AHC_DV_STATE_INQ_SHORT_ASYNC) | ||
2382 | inq_len = AHC_LINUX_DV_INQ_SHORT_LEN; | ||
2383 | else | ||
2384 | inq_len = targ->inq_data->additional_length + 5; | ||
2385 | ahc_linux_dv_inq(ahc, cmd, &devinfo, targ, inq_len); | ||
2386 | break; | ||
2387 | } | ||
2388 | case AHC_DV_STATE_TUR: | ||
2389 | case AHC_DV_STATE_BUSY: | ||
2390 | timeout = 5 * HZ; | ||
2391 | ahc_linux_dv_tur(ahc, cmd, &devinfo); | ||
2392 | break; | ||
2393 | case AHC_DV_STATE_REBD: | ||
2394 | ahc_linux_dv_rebd(ahc, cmd, &devinfo, targ); | ||
2395 | break; | ||
2396 | case AHC_DV_STATE_WEB: | ||
2397 | ahc_linux_dv_web(ahc, cmd, &devinfo, targ); | ||
2398 | break; | ||
2399 | |||
2400 | case AHC_DV_STATE_REB: | ||
2401 | ahc_linux_dv_reb(ahc, cmd, &devinfo, targ); | ||
2402 | break; | ||
2403 | |||
2404 | case AHC_DV_STATE_SU: | ||
2405 | ahc_linux_dv_su(ahc, cmd, &devinfo, targ); | ||
2406 | timeout = 50 * HZ; | ||
2407 | break; | ||
2408 | |||
2409 | default: | ||
2410 | ahc_print_devinfo(ahc, &devinfo); | ||
2411 | printf("Unknown DV state %d\n", targ->dv_state); | ||
2412 | goto out; | ||
2413 | } | ||
2414 | |||
2415 | /* Queue the command and wait for it to complete */ | ||
2416 | /* Abuse eh_timeout in the scsi_cmnd struct for our purposes */ | ||
2417 | init_timer(&cmd->eh_timeout); | ||
2418 | #ifdef AHC_DEBUG | ||
2419 | if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) | ||
2420 | /* | ||
2421 | * All of the printfs during negotiation | ||
2422 | * really slow down the negotiation. | ||
2423 | * Add a bit of time just to be safe. | ||
2424 | */ | ||
2425 | timeout += HZ; | ||
2426 | #endif | ||
2427 | scsi_add_timer(cmd, timeout, ahc_linux_dv_timeout); | ||
2428 | /* | ||
2429 | * In 2.5.X, it is assumed that all calls from the | ||
2430 | * "midlayer" (which we are emulating) will have the | ||
2431 | * ahc host lock held. For other kernels, the | ||
2432 | * io_request_lock must be held. | ||
2433 | */ | ||
2434 | #if AHC_SCSI_HAS_HOST_LOCK != 0 | ||
2435 | ahc_lock(ahc, &s); | ||
2436 | #else | ||
2437 | spin_lock_irqsave(&io_request_lock, s); | ||
2438 | #endif | ||
2439 | ahc_linux_queue(cmd, ahc_linux_dv_complete); | ||
2440 | #if AHC_SCSI_HAS_HOST_LOCK != 0 | ||
2441 | ahc_unlock(ahc, &s); | ||
2442 | #else | ||
2443 | spin_unlock_irqrestore(&io_request_lock, s); | ||
2444 | #endif | ||
2445 | down_interruptible(&ahc->platform_data->dv_cmd_sem); | ||
2446 | /* | ||
2447 | * Wait for the SIMQ to be released so that DV is the | ||
2448 | * only reason the queue is frozen. | ||
2449 | */ | ||
2450 | ahc_lock(ahc, &s); | ||
2451 | while (AHC_DV_SIMQ_FROZEN(ahc) == 0) { | ||
2452 | ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE; | ||
2453 | ahc_unlock(ahc, &s); | ||
2454 | down_interruptible(&ahc->platform_data->dv_sem); | ||
2455 | ahc_lock(ahc, &s); | ||
2456 | } | ||
2457 | ahc_unlock(ahc, &s); | ||
2458 | |||
2459 | ahc_linux_dv_transition(ahc, cmd, &devinfo, targ); | ||
2460 | } | ||
2461 | |||
2462 | out: | ||
2463 | if ((targ->flags & AHC_INQ_VALID) != 0 | ||
2464 | && ahc_linux_get_device(ahc, devinfo.channel - 'A', | ||
2465 | devinfo.target, devinfo.lun, | ||
2466 | /*alloc*/FALSE) == NULL) { | ||
2467 | /* | ||
2468 | * The DV state machine failed to configure this device. | ||
2469 | * This is normal if DV is disabled. Since we have inquiry | ||
2470 | * data, filter it and use the "optimistic" negotiation | ||
2471 | * parameters found in the inquiry string. | ||
2472 | */ | ||
2473 | ahc_linux_filter_inquiry(ahc, &devinfo); | ||
2474 | if ((targ->flags & (AHC_BASIC_DV|AHC_ENHANCED_DV)) != 0) { | ||
2475 | ahc_print_devinfo(ahc, &devinfo); | ||
2476 | printf("DV failed to configure device. " | ||
2477 | "Please file a bug report against " | ||
2478 | "this driver.\n"); | ||
2479 | } | ||
2480 | } | ||
2481 | |||
2482 | if (cmd != NULL) | ||
2483 | free(cmd, M_DEVBUF); | ||
2484 | |||
2485 | if (ahc->platform_data->dv_scsi_dev != NULL) { | ||
2486 | free(ahc->platform_data->dv_scsi_dev, M_DEVBUF); | ||
2487 | ahc->platform_data->dv_scsi_dev = NULL; | ||
2488 | } | ||
2489 | |||
2490 | ahc_lock(ahc, &s); | ||
2491 | if (targ->dv_buffer != NULL) { | ||
2492 | free(targ->dv_buffer, M_DEVBUF); | ||
2493 | targ->dv_buffer = NULL; | ||
2494 | } | ||
2495 | if (targ->dv_buffer1 != NULL) { | ||
2496 | free(targ->dv_buffer1, M_DEVBUF); | ||
2497 | targ->dv_buffer1 = NULL; | ||
2498 | } | ||
2499 | targ->flags &= ~AHC_DV_REQUIRED; | ||
2500 | if (targ->refcount == 0) | ||
2501 | ahc_linux_free_target(ahc, targ); | ||
2502 | ahc_unlock(ahc, &s); | ||
2503 | } | ||
2504 | |||
2505 | static void | ||
2506 | ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd, | ||
2507 | struct ahc_devinfo *devinfo, | ||
2508 | struct ahc_linux_target *targ) | ||
2509 | { | ||
2510 | u_int32_t status; | ||
2511 | |||
2512 | status = aic_error_action(cmd, targ->inq_data, | ||
2513 | ahc_cmd_get_transaction_status(cmd), | ||
2514 | ahc_cmd_get_scsi_status(cmd)); | ||
2515 | |||
2516 | #ifdef AHC_DEBUG | ||
2517 | if (ahc_debug & AHC_SHOW_DV) { | ||
2518 | ahc_print_devinfo(ahc, devinfo); | ||
2519 | printf("Entering ahc_linux_dv_transition, state= %d, " | ||
2520 | "status= 0x%x, cmd->result= 0x%x\n", targ->dv_state, | ||
2521 | status, cmd->result); | ||
2522 | } | ||
2523 | #endif | ||
2524 | |||
2525 | switch (targ->dv_state) { | ||
2526 | case AHC_DV_STATE_INQ_SHORT_ASYNC: | ||
2527 | case AHC_DV_STATE_INQ_ASYNC: | ||
2528 | switch (status & SS_MASK) { | ||
2529 | case SS_NOP: | ||
2530 | { | ||
2531 | AHC_SET_DV_STATE(ahc, targ, targ->dv_state+1); | ||
2532 | break; | ||
2533 | } | ||
2534 | case SS_INQ_REFRESH: | ||
2535 | AHC_SET_DV_STATE(ahc, targ, | ||
2536 | AHC_DV_STATE_INQ_SHORT_ASYNC); | ||
2537 | break; | ||
2538 | case SS_TUR: | ||
2539 | case SS_RETRY: | ||
2540 | AHC_SET_DV_STATE(ahc, targ, targ->dv_state); | ||
2541 | if (ahc_cmd_get_transaction_status(cmd) | ||
2542 | == CAM_REQUEUE_REQ) | ||
2543 | targ->dv_state_retry--; | ||
2544 | if ((status & SS_ERRMASK) == EBUSY) | ||
2545 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY); | ||
2546 | if (targ->dv_state_retry < 10) | ||
2547 | break; | ||
2548 | /* FALLTHROUGH */ | ||
2549 | default: | ||
2550 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2551 | #ifdef AHC_DEBUG | ||
2552 | if (ahc_debug & AHC_SHOW_DV) { | ||
2553 | ahc_print_devinfo(ahc, devinfo); | ||
2554 | printf("Failed DV inquiry, skipping\n"); | ||
2555 | } | ||
2556 | #endif | ||
2557 | break; | ||
2558 | } | ||
2559 | break; | ||
2560 | case AHC_DV_STATE_INQ_ASYNC_VERIFY: | ||
2561 | switch (status & SS_MASK) { | ||
2562 | case SS_NOP: | ||
2563 | { | ||
2564 | u_int xportflags; | ||
2565 | u_int spi3data; | ||
2566 | |||
2567 | if (memcmp(targ->inq_data, targ->dv_buffer, | ||
2568 | AHC_LINUX_DV_INQ_LEN) != 0) { | ||
2569 | /* | ||
2570 | * Inquiry data must have changed. | ||
2571 | * Try from the top again. | ||
2572 | */ | ||
2573 | AHC_SET_DV_STATE(ahc, targ, | ||
2574 | AHC_DV_STATE_INQ_SHORT_ASYNC); | ||
2575 | break; | ||
2576 | } | ||
2577 | |||
2578 | AHC_SET_DV_STATE(ahc, targ, targ->dv_state+1); | ||
2579 | targ->flags |= AHC_INQ_VALID; | ||
2580 | if (ahc_linux_user_dv_setting(ahc) == 0) | ||
2581 | break; | ||
2582 | |||
2583 | xportflags = targ->inq_data->flags; | ||
2584 | if ((xportflags & (SID_Sync|SID_WBus16)) == 0) | ||
2585 | break; | ||
2586 | |||
2587 | spi3data = targ->inq_data->spi3data; | ||
2588 | switch (spi3data & SID_SPI_CLOCK_DT_ST) { | ||
2589 | default: | ||
2590 | case SID_SPI_CLOCK_ST: | ||
2591 | /* Assume only basic DV is supported. */ | ||
2592 | targ->flags |= AHC_BASIC_DV; | ||
2593 | break; | ||
2594 | case SID_SPI_CLOCK_DT: | ||
2595 | case SID_SPI_CLOCK_DT_ST: | ||
2596 | targ->flags |= AHC_ENHANCED_DV; | ||
2597 | break; | ||
2598 | } | ||
2599 | break; | ||
2600 | } | ||
2601 | case SS_INQ_REFRESH: | ||
2602 | AHC_SET_DV_STATE(ahc, targ, | ||
2603 | AHC_DV_STATE_INQ_SHORT_ASYNC); | ||
2604 | break; | ||
2605 | case SS_TUR: | ||
2606 | case SS_RETRY: | ||
2607 | AHC_SET_DV_STATE(ahc, targ, targ->dv_state); | ||
2608 | if (ahc_cmd_get_transaction_status(cmd) | ||
2609 | == CAM_REQUEUE_REQ) | ||
2610 | targ->dv_state_retry--; | ||
2611 | |||
2612 | if ((status & SS_ERRMASK) == EBUSY) | ||
2613 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY); | ||
2614 | if (targ->dv_state_retry < 10) | ||
2615 | break; | ||
2616 | /* FALLTHROUGH */ | ||
2617 | default: | ||
2618 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2619 | #ifdef AHC_DEBUG | ||
2620 | if (ahc_debug & AHC_SHOW_DV) { | ||
2621 | ahc_print_devinfo(ahc, devinfo); | ||
2622 | printf("Failed DV inquiry, skipping\n"); | ||
2623 | } | ||
2624 | #endif | ||
2625 | break; | ||
2626 | } | ||
2627 | break; | ||
2628 | case AHC_DV_STATE_INQ_VERIFY: | ||
2629 | switch (status & SS_MASK) { | ||
2630 | case SS_NOP: | ||
2631 | { | ||
2632 | |||
2633 | if (memcmp(targ->inq_data, targ->dv_buffer, | ||
2634 | AHC_LINUX_DV_INQ_LEN) == 0) { | ||
2635 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2636 | break; | ||
2637 | } | ||
2638 | #ifdef AHC_DEBUG | ||
2639 | if (ahc_debug & AHC_SHOW_DV) { | ||
2640 | int i; | ||
2641 | |||
2642 | ahc_print_devinfo(ahc, devinfo); | ||
2643 | printf("Inquiry buffer mismatch:"); | ||
2644 | for (i = 0; i < AHC_LINUX_DV_INQ_LEN; i++) { | ||
2645 | if ((i & 0xF) == 0) | ||
2646 | printf("\n "); | ||
2647 | printf("0x%x:0x0%x ", | ||
2648 | ((uint8_t *)targ->inq_data)[i], | ||
2649 | targ->dv_buffer[i]); | ||
2650 | } | ||
2651 | printf("\n"); | ||
2652 | } | ||
2653 | #endif | ||
2654 | |||
2655 | if (ahc_linux_fallback(ahc, devinfo) != 0) { | ||
2656 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2657 | break; | ||
2658 | } | ||
2659 | /* | ||
2660 | * Do not count "falling back" | ||
2661 | * against our retries. | ||
2662 | */ | ||
2663 | targ->dv_state_retry = 0; | ||
2664 | AHC_SET_DV_STATE(ahc, targ, targ->dv_state); | ||
2665 | break; | ||
2666 | } | ||
2667 | case SS_INQ_REFRESH: | ||
2668 | AHC_SET_DV_STATE(ahc, targ, | ||
2669 | AHC_DV_STATE_INQ_SHORT_ASYNC); | ||
2670 | break; | ||
2671 | case SS_TUR: | ||
2672 | case SS_RETRY: | ||
2673 | AHC_SET_DV_STATE(ahc, targ, targ->dv_state); | ||
2674 | if (ahc_cmd_get_transaction_status(cmd) | ||
2675 | == CAM_REQUEUE_REQ) { | ||
2676 | targ->dv_state_retry--; | ||
2677 | } else if ((status & SSQ_FALLBACK) != 0) { | ||
2678 | if (ahc_linux_fallback(ahc, devinfo) != 0) { | ||
2679 | AHC_SET_DV_STATE(ahc, targ, | ||
2680 | AHC_DV_STATE_EXIT); | ||
2681 | break; | ||
2682 | } | ||
2683 | /* | ||
2684 | * Do not count "falling back" | ||
2685 | * against our retries. | ||
2686 | */ | ||
2687 | targ->dv_state_retry = 0; | ||
2688 | } else if ((status & SS_ERRMASK) == EBUSY) | ||
2689 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY); | ||
2690 | if (targ->dv_state_retry < 10) | ||
2691 | break; | ||
2692 | /* FALLTHROUGH */ | ||
2693 | default: | ||
2694 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2695 | #ifdef AHC_DEBUG | ||
2696 | if (ahc_debug & AHC_SHOW_DV) { | ||
2697 | ahc_print_devinfo(ahc, devinfo); | ||
2698 | printf("Failed DV inquiry, skipping\n"); | ||
2699 | } | ||
2700 | #endif | ||
2701 | break; | ||
2702 | } | ||
2703 | break; | ||
2704 | |||
2705 | case AHC_DV_STATE_TUR: | ||
2706 | switch (status & SS_MASK) { | ||
2707 | case SS_NOP: | ||
2708 | if ((targ->flags & AHC_BASIC_DV) != 0) { | ||
2709 | ahc_linux_filter_inquiry(ahc, devinfo); | ||
2710 | AHC_SET_DV_STATE(ahc, targ, | ||
2711 | AHC_DV_STATE_INQ_VERIFY); | ||
2712 | } else if ((targ->flags & AHC_ENHANCED_DV) != 0) { | ||
2713 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REBD); | ||
2714 | } else { | ||
2715 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2716 | } | ||
2717 | break; | ||
2718 | case SS_RETRY: | ||
2719 | case SS_TUR: | ||
2720 | if ((status & SS_ERRMASK) == EBUSY) { | ||
2721 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY); | ||
2722 | break; | ||
2723 | } | ||
2724 | AHC_SET_DV_STATE(ahc, targ, targ->dv_state); | ||
2725 | if (ahc_cmd_get_transaction_status(cmd) | ||
2726 | == CAM_REQUEUE_REQ) { | ||
2727 | targ->dv_state_retry--; | ||
2728 | } else if ((status & SSQ_FALLBACK) != 0) { | ||
2729 | if (ahc_linux_fallback(ahc, devinfo) != 0) { | ||
2730 | AHC_SET_DV_STATE(ahc, targ, | ||
2731 | AHC_DV_STATE_EXIT); | ||
2732 | break; | ||
2733 | } | ||
2734 | /* | ||
2735 | * Do not count "falling back" | ||
2736 | * against our retries. | ||
2737 | */ | ||
2738 | targ->dv_state_retry = 0; | ||
2739 | } | ||
2740 | if (targ->dv_state_retry >= 10) { | ||
2741 | #ifdef AHC_DEBUG | ||
2742 | if (ahc_debug & AHC_SHOW_DV) { | ||
2743 | ahc_print_devinfo(ahc, devinfo); | ||
2744 | printf("DV TUR reties exhausted\n"); | ||
2745 | } | ||
2746 | #endif | ||
2747 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2748 | break; | ||
2749 | } | ||
2750 | if (status & SSQ_DELAY) | ||
2751 | ssleep(1); | ||
2752 | |||
2753 | break; | ||
2754 | case SS_START: | ||
2755 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_SU); | ||
2756 | break; | ||
2757 | case SS_INQ_REFRESH: | ||
2758 | AHC_SET_DV_STATE(ahc, targ, | ||
2759 | AHC_DV_STATE_INQ_SHORT_ASYNC); | ||
2760 | break; | ||
2761 | default: | ||
2762 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2763 | break; | ||
2764 | } | ||
2765 | break; | ||
2766 | |||
2767 | case AHC_DV_STATE_REBD: | ||
2768 | switch (status & SS_MASK) { | ||
2769 | case SS_NOP: | ||
2770 | { | ||
2771 | uint32_t echo_size; | ||
2772 | |||
2773 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_WEB); | ||
2774 | echo_size = scsi_3btoul(&targ->dv_buffer[1]); | ||
2775 | echo_size &= 0x1FFF; | ||
2776 | #ifdef AHC_DEBUG | ||
2777 | if (ahc_debug & AHC_SHOW_DV) { | ||
2778 | ahc_print_devinfo(ahc, devinfo); | ||
2779 | printf("Echo buffer size= %d\n", echo_size); | ||
2780 | } | ||
2781 | #endif | ||
2782 | if (echo_size == 0) { | ||
2783 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2784 | break; | ||
2785 | } | ||
2786 | |||
2787 | /* Generate the buffer pattern */ | ||
2788 | targ->dv_echo_size = echo_size; | ||
2789 | ahc_linux_generate_dv_pattern(targ); | ||
2790 | /* | ||
2791 | * Setup initial negotiation values. | ||
2792 | */ | ||
2793 | ahc_linux_filter_inquiry(ahc, devinfo); | ||
2794 | break; | ||
2795 | } | ||
2796 | case SS_INQ_REFRESH: | ||
2797 | AHC_SET_DV_STATE(ahc, targ, | ||
2798 | AHC_DV_STATE_INQ_SHORT_ASYNC); | ||
2799 | break; | ||
2800 | case SS_RETRY: | ||
2801 | AHC_SET_DV_STATE(ahc, targ, targ->dv_state); | ||
2802 | if (ahc_cmd_get_transaction_status(cmd) | ||
2803 | == CAM_REQUEUE_REQ) | ||
2804 | targ->dv_state_retry--; | ||
2805 | if (targ->dv_state_retry <= 10) | ||
2806 | break; | ||
2807 | #ifdef AHC_DEBUG | ||
2808 | if (ahc_debug & AHC_SHOW_DV) { | ||
2809 | ahc_print_devinfo(ahc, devinfo); | ||
2810 | printf("DV REBD reties exhausted\n"); | ||
2811 | } | ||
2812 | #endif | ||
2813 | /* FALLTHROUGH */ | ||
2814 | case SS_FATAL: | ||
2815 | default: | ||
2816 | /* | ||
2817 | * Setup initial negotiation values | ||
2818 | * and try level 1 DV. | ||
2819 | */ | ||
2820 | ahc_linux_filter_inquiry(ahc, devinfo); | ||
2821 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_VERIFY); | ||
2822 | targ->dv_echo_size = 0; | ||
2823 | break; | ||
2824 | } | ||
2825 | break; | ||
2826 | |||
2827 | case AHC_DV_STATE_WEB: | ||
2828 | switch (status & SS_MASK) { | ||
2829 | case SS_NOP: | ||
2830 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REB); | ||
2831 | break; | ||
2832 | case SS_INQ_REFRESH: | ||
2833 | AHC_SET_DV_STATE(ahc, targ, | ||
2834 | AHC_DV_STATE_INQ_SHORT_ASYNC); | ||
2835 | break; | ||
2836 | case SS_RETRY: | ||
2837 | AHC_SET_DV_STATE(ahc, targ, targ->dv_state); | ||
2838 | if (ahc_cmd_get_transaction_status(cmd) | ||
2839 | == CAM_REQUEUE_REQ) { | ||
2840 | targ->dv_state_retry--; | ||
2841 | } else if ((status & SSQ_FALLBACK) != 0) { | ||
2842 | if (ahc_linux_fallback(ahc, devinfo) != 0) { | ||
2843 | AHC_SET_DV_STATE(ahc, targ, | ||
2844 | AHC_DV_STATE_EXIT); | ||
2845 | break; | ||
2846 | } | ||
2847 | /* | ||
2848 | * Do not count "falling back" | ||
2849 | * against our retries. | ||
2850 | */ | ||
2851 | targ->dv_state_retry = 0; | ||
2852 | } | ||
2853 | if (targ->dv_state_retry <= 10) | ||
2854 | break; | ||
2855 | /* FALLTHROUGH */ | ||
2856 | #ifdef AHC_DEBUG | ||
2857 | if (ahc_debug & AHC_SHOW_DV) { | ||
2858 | ahc_print_devinfo(ahc, devinfo); | ||
2859 | printf("DV WEB reties exhausted\n"); | ||
2860 | } | ||
2861 | #endif | ||
2862 | default: | ||
2863 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2864 | break; | ||
2865 | } | ||
2866 | break; | ||
2867 | |||
2868 | case AHC_DV_STATE_REB: | ||
2869 | switch (status & SS_MASK) { | ||
2870 | case SS_NOP: | ||
2871 | if (memcmp(targ->dv_buffer, targ->dv_buffer1, | ||
2872 | targ->dv_echo_size) != 0) { | ||
2873 | if (ahc_linux_fallback(ahc, devinfo) != 0) | ||
2874 | AHC_SET_DV_STATE(ahc, targ, | ||
2875 | AHC_DV_STATE_EXIT); | ||
2876 | else | ||
2877 | AHC_SET_DV_STATE(ahc, targ, | ||
2878 | AHC_DV_STATE_WEB); | ||
2879 | break; | ||
2880 | } | ||
2881 | |||
2882 | if (targ->dv_buffer != NULL) { | ||
2883 | free(targ->dv_buffer, M_DEVBUF); | ||
2884 | targ->dv_buffer = NULL; | ||
2885 | } | ||
2886 | if (targ->dv_buffer1 != NULL) { | ||
2887 | free(targ->dv_buffer1, M_DEVBUF); | ||
2888 | targ->dv_buffer1 = NULL; | ||
2889 | } | ||
2890 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2891 | break; | ||
2892 | case SS_INQ_REFRESH: | ||
2893 | AHC_SET_DV_STATE(ahc, targ, | ||
2894 | AHC_DV_STATE_INQ_SHORT_ASYNC); | ||
2895 | break; | ||
2896 | case SS_RETRY: | ||
2897 | AHC_SET_DV_STATE(ahc, targ, targ->dv_state); | ||
2898 | if (ahc_cmd_get_transaction_status(cmd) | ||
2899 | == CAM_REQUEUE_REQ) { | ||
2900 | targ->dv_state_retry--; | ||
2901 | } else if ((status & SSQ_FALLBACK) != 0) { | ||
2902 | if (ahc_linux_fallback(ahc, devinfo) != 0) { | ||
2903 | AHC_SET_DV_STATE(ahc, targ, | ||
2904 | AHC_DV_STATE_EXIT); | ||
2905 | break; | ||
2906 | } | ||
2907 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_WEB); | ||
2908 | } | ||
2909 | if (targ->dv_state_retry <= 10) { | ||
2910 | if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0) | ||
2911 | msleep(ahc->our_id*1000/10); | ||
2912 | break; | ||
2913 | } | ||
2914 | #ifdef AHC_DEBUG | ||
2915 | if (ahc_debug & AHC_SHOW_DV) { | ||
2916 | ahc_print_devinfo(ahc, devinfo); | ||
2917 | printf("DV REB reties exhausted\n"); | ||
2918 | } | ||
2919 | #endif | ||
2920 | /* FALLTHROUGH */ | ||
2921 | default: | ||
2922 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2923 | break; | ||
2924 | } | ||
2925 | break; | ||
2926 | |||
2927 | case AHC_DV_STATE_SU: | ||
2928 | switch (status & SS_MASK) { | ||
2929 | case SS_NOP: | ||
2930 | case SS_INQ_REFRESH: | ||
2931 | AHC_SET_DV_STATE(ahc, targ, | ||
2932 | AHC_DV_STATE_INQ_SHORT_ASYNC); | ||
2933 | break; | ||
2934 | default: | ||
2935 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2936 | break; | ||
2937 | } | ||
2938 | break; | ||
2939 | |||
2940 | case AHC_DV_STATE_BUSY: | ||
2941 | switch (status & SS_MASK) { | ||
2942 | case SS_NOP: | ||
2943 | case SS_INQ_REFRESH: | ||
2944 | AHC_SET_DV_STATE(ahc, targ, | ||
2945 | AHC_DV_STATE_INQ_SHORT_ASYNC); | ||
2946 | break; | ||
2947 | case SS_TUR: | ||
2948 | case SS_RETRY: | ||
2949 | AHC_SET_DV_STATE(ahc, targ, targ->dv_state); | ||
2950 | if (ahc_cmd_get_transaction_status(cmd) | ||
2951 | == CAM_REQUEUE_REQ) { | ||
2952 | targ->dv_state_retry--; | ||
2953 | } else if (targ->dv_state_retry < 60) { | ||
2954 | if ((status & SSQ_DELAY) != 0) | ||
2955 | ssleep(1); | ||
2956 | } else { | ||
2957 | #ifdef AHC_DEBUG | ||
2958 | if (ahc_debug & AHC_SHOW_DV) { | ||
2959 | ahc_print_devinfo(ahc, devinfo); | ||
2960 | printf("DV BUSY reties exhausted\n"); | ||
2961 | } | ||
2962 | #endif | ||
2963 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2964 | } | ||
2965 | break; | ||
2966 | default: | ||
2967 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2968 | break; | ||
2969 | } | ||
2970 | break; | ||
2971 | |||
2972 | default: | ||
2973 | printf("%s: Invalid DV completion state %d\n", ahc_name(ahc), | ||
2974 | targ->dv_state); | ||
2975 | AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); | ||
2976 | break; | ||
2977 | } | ||
2978 | } | ||
2979 | |||
2980 | static void | ||
2981 | ahc_linux_dv_fill_cmd(struct ahc_softc *ahc, struct scsi_cmnd *cmd, | ||
2982 | struct ahc_devinfo *devinfo) | ||
2983 | { | ||
2984 | memset(cmd, 0, sizeof(struct scsi_cmnd)); | ||
2985 | cmd->device = ahc->platform_data->dv_scsi_dev; | ||
2986 | cmd->scsi_done = ahc_linux_dv_complete; | ||
2987 | } | ||
2988 | |||
2989 | /* | ||
2990 | * Synthesize an inquiry command. On the return trip, it'll be | ||
2991 | * sniffed and the device transfer settings set for us. | ||
2992 | */ | ||
2993 | static void | ||
2994 | ahc_linux_dv_inq(struct ahc_softc *ahc, struct scsi_cmnd *cmd, | ||
2995 | struct ahc_devinfo *devinfo, struct ahc_linux_target *targ, | ||
2996 | u_int request_length) | ||
2997 | { | ||
2998 | |||
2999 | #ifdef AHC_DEBUG | ||
3000 | if (ahc_debug & AHC_SHOW_DV) { | ||
3001 | ahc_print_devinfo(ahc, devinfo); | ||
3002 | printf("Sending INQ\n"); | ||
3003 | } | ||
3004 | #endif | ||
3005 | if (targ->inq_data == NULL) | ||
3006 | targ->inq_data = malloc(AHC_LINUX_DV_INQ_LEN, | ||
3007 | M_DEVBUF, M_WAITOK); | ||
3008 | if (targ->dv_state > AHC_DV_STATE_INQ_ASYNC) { | ||
3009 | if (targ->dv_buffer != NULL) | ||
3010 | free(targ->dv_buffer, M_DEVBUF); | ||
3011 | targ->dv_buffer = malloc(AHC_LINUX_DV_INQ_LEN, | ||
3012 | M_DEVBUF, M_WAITOK); | ||
3013 | } | ||
3014 | |||
3015 | ahc_linux_dv_fill_cmd(ahc, cmd, devinfo); | ||
3016 | cmd->sc_data_direction = DMA_FROM_DEVICE; | ||
3017 | cmd->cmd_len = 6; | ||
3018 | cmd->cmnd[0] = INQUIRY; | ||
3019 | cmd->cmnd[4] = request_length; | ||
3020 | cmd->request_bufflen = request_length; | ||
3021 | if (targ->dv_state > AHC_DV_STATE_INQ_ASYNC) | ||
3022 | cmd->request_buffer = targ->dv_buffer; | ||
3023 | else | ||
3024 | cmd->request_buffer = targ->inq_data; | ||
3025 | memset(cmd->request_buffer, 0, AHC_LINUX_DV_INQ_LEN); | ||
3026 | } | ||
3027 | |||
3028 | static void | ||
3029 | ahc_linux_dv_tur(struct ahc_softc *ahc, struct scsi_cmnd *cmd, | ||
3030 | struct ahc_devinfo *devinfo) | ||
3031 | { | ||
3032 | |||
3033 | #ifdef AHC_DEBUG | ||
3034 | if (ahc_debug & AHC_SHOW_DV) { | ||
3035 | ahc_print_devinfo(ahc, devinfo); | ||
3036 | printf("Sending TUR\n"); | ||
3037 | } | ||
3038 | #endif | ||
3039 | /* Do a TUR to clear out any non-fatal transitional state */ | ||
3040 | ahc_linux_dv_fill_cmd(ahc, cmd, devinfo); | ||
3041 | cmd->sc_data_direction = DMA_NONE; | ||
3042 | cmd->cmd_len = 6; | ||
3043 | cmd->cmnd[0] = TEST_UNIT_READY; | ||
3044 | } | ||
3045 | |||
3046 | #define AHC_REBD_LEN 4 | ||
3047 | |||
3048 | static void | ||
3049 | ahc_linux_dv_rebd(struct ahc_softc *ahc, struct scsi_cmnd *cmd, | ||
3050 | struct ahc_devinfo *devinfo, struct ahc_linux_target *targ) | ||
3051 | { | ||
3052 | |||
3053 | #ifdef AHC_DEBUG | ||
3054 | if (ahc_debug & AHC_SHOW_DV) { | ||
3055 | ahc_print_devinfo(ahc, devinfo); | ||
3056 | printf("Sending REBD\n"); | ||
3057 | } | ||
3058 | #endif | ||
3059 | if (targ->dv_buffer != NULL) | ||
3060 | free(targ->dv_buffer, M_DEVBUF); | ||
3061 | targ->dv_buffer = malloc(AHC_REBD_LEN, M_DEVBUF, M_WAITOK); | ||
3062 | ahc_linux_dv_fill_cmd(ahc, cmd, devinfo); | ||
3063 | cmd->sc_data_direction = DMA_FROM_DEVICE; | ||
3064 | cmd->cmd_len = 10; | ||
3065 | cmd->cmnd[0] = READ_BUFFER; | ||
3066 | cmd->cmnd[1] = 0x0b; | ||
3067 | scsi_ulto3b(AHC_REBD_LEN, &cmd->cmnd[6]); | ||
3068 | cmd->request_bufflen = AHC_REBD_LEN; | ||
3069 | cmd->underflow = cmd->request_bufflen; | ||
3070 | cmd->request_buffer = targ->dv_buffer; | ||
3071 | } | ||
3072 | |||
3073 | static void | ||
3074 | ahc_linux_dv_web(struct ahc_softc *ahc, struct scsi_cmnd *cmd, | ||
3075 | struct ahc_devinfo *devinfo, struct ahc_linux_target *targ) | ||
3076 | { | ||
3077 | |||
3078 | #ifdef AHC_DEBUG | ||
3079 | if (ahc_debug & AHC_SHOW_DV) { | ||
3080 | ahc_print_devinfo(ahc, devinfo); | ||
3081 | printf("Sending WEB\n"); | ||
3082 | } | ||
3083 | #endif | ||
3084 | ahc_linux_dv_fill_cmd(ahc, cmd, devinfo); | ||
3085 | cmd->sc_data_direction = DMA_TO_DEVICE; | ||
3086 | cmd->cmd_len = 10; | ||
3087 | cmd->cmnd[0] = WRITE_BUFFER; | ||
3088 | cmd->cmnd[1] = 0x0a; | ||
3089 | scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]); | ||
3090 | cmd->request_bufflen = targ->dv_echo_size; | ||
3091 | cmd->underflow = cmd->request_bufflen; | ||
3092 | cmd->request_buffer = targ->dv_buffer; | ||
3093 | } | ||
3094 | |||
3095 | static void | ||
3096 | ahc_linux_dv_reb(struct ahc_softc *ahc, struct scsi_cmnd *cmd, | ||
3097 | struct ahc_devinfo *devinfo, struct ahc_linux_target *targ) | ||
3098 | { | ||
3099 | |||
3100 | #ifdef AHC_DEBUG | ||
3101 | if (ahc_debug & AHC_SHOW_DV) { | ||
3102 | ahc_print_devinfo(ahc, devinfo); | ||
3103 | printf("Sending REB\n"); | ||
3104 | } | ||
3105 | #endif | ||
3106 | ahc_linux_dv_fill_cmd(ahc, cmd, devinfo); | ||
3107 | cmd->sc_data_direction = DMA_FROM_DEVICE; | ||
3108 | cmd->cmd_len = 10; | ||
3109 | cmd->cmnd[0] = READ_BUFFER; | ||
3110 | cmd->cmnd[1] = 0x0a; | ||
3111 | scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]); | ||
3112 | cmd->request_bufflen = targ->dv_echo_size; | ||
3113 | cmd->underflow = cmd->request_bufflen; | ||
3114 | cmd->request_buffer = targ->dv_buffer1; | ||
3115 | } | ||
3116 | |||
3117 | static void | ||
3118 | ahc_linux_dv_su(struct ahc_softc *ahc, struct scsi_cmnd *cmd, | ||
3119 | struct ahc_devinfo *devinfo, | ||
3120 | struct ahc_linux_target *targ) | ||
3121 | { | ||
3122 | u_int le; | ||
3123 | |||
3124 | le = SID_IS_REMOVABLE(targ->inq_data) ? SSS_LOEJ : 0; | ||
3125 | |||
3126 | #ifdef AHC_DEBUG | ||
3127 | if (ahc_debug & AHC_SHOW_DV) { | ||
3128 | ahc_print_devinfo(ahc, devinfo); | ||
3129 | printf("Sending SU\n"); | ||
3130 | } | ||
3131 | #endif | ||
3132 | ahc_linux_dv_fill_cmd(ahc, cmd, devinfo); | ||
3133 | cmd->sc_data_direction = DMA_NONE; | ||
3134 | cmd->cmd_len = 6; | ||
3135 | cmd->cmnd[0] = START_STOP_UNIT; | ||
3136 | cmd->cmnd[4] = le | SSS_START; | ||
3137 | } | ||
3138 | |||
3139 | static int | ||
3140 | ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) | ||
3141 | { | ||
3142 | struct ahc_linux_target *targ; | ||
3143 | struct ahc_initiator_tinfo *tinfo; | ||
3144 | struct ahc_transinfo *goal; | ||
3145 | struct ahc_tmode_tstate *tstate; | ||
3146 | struct ahc_syncrate *syncrate; | ||
3147 | u_long s; | ||
3148 | u_int width; | ||
3149 | u_int period; | ||
3150 | u_int offset; | ||
3151 | u_int ppr_options; | ||
3152 | u_int cur_speed; | ||
3153 | u_int wide_speed; | ||
3154 | u_int narrow_speed; | ||
3155 | u_int fallback_speed; | ||
3156 | |||
3157 | #ifdef AHC_DEBUG | ||
3158 | if (ahc_debug & AHC_SHOW_DV) { | ||
3159 | ahc_print_devinfo(ahc, devinfo); | ||
3160 | printf("Trying to fallback\n"); | ||
3161 | } | ||
3162 | #endif | ||
3163 | ahc_lock(ahc, &s); | ||
3164 | targ = ahc->platform_data->targets[devinfo->target_offset]; | ||
3165 | tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, | ||
3166 | devinfo->our_scsiid, | ||
3167 | devinfo->target, &tstate); | ||
3168 | goal = &tinfo->goal; | ||
3169 | width = goal->width; | ||
3170 | period = goal->period; | ||
3171 | offset = goal->offset; | ||
3172 | ppr_options = goal->ppr_options; | ||
3173 | if (offset == 0) | ||
3174 | period = AHC_ASYNC_XFER_PERIOD; | ||
3175 | if (targ->dv_next_narrow_period == 0) | ||
3176 | targ->dv_next_narrow_period = MAX(period, AHC_SYNCRATE_ULTRA2); | ||
3177 | if (targ->dv_next_wide_period == 0) | ||
3178 | targ->dv_next_wide_period = period; | ||
3179 | if (targ->dv_max_width == 0) | ||
3180 | targ->dv_max_width = width; | ||
3181 | if (targ->dv_max_ppr_options == 0) | ||
3182 | targ->dv_max_ppr_options = ppr_options; | ||
3183 | if (targ->dv_last_ppr_options == 0) | ||
3184 | targ->dv_last_ppr_options = ppr_options; | ||
3185 | |||
3186 | cur_speed = aic_calc_speed(width, period, offset, AHC_SYNCRATE_MIN); | ||
3187 | wide_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_16_BIT, | ||
3188 | targ->dv_next_wide_period, | ||
3189 | MAX_OFFSET, | ||
3190 | AHC_SYNCRATE_MIN); | ||
3191 | narrow_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_8_BIT, | ||
3192 | targ->dv_next_narrow_period, | ||
3193 | MAX_OFFSET, | ||
3194 | AHC_SYNCRATE_MIN); | ||
3195 | fallback_speed = aic_calc_speed(width, period+1, offset, | ||
3196 | AHC_SYNCRATE_MIN); | ||
3197 | #ifdef AHC_DEBUG | ||
3198 | if (ahc_debug & AHC_SHOW_DV) { | ||
3199 | printf("cur_speed= %d, wide_speed= %d, narrow_speed= %d, " | ||
3200 | "fallback_speed= %d\n", cur_speed, wide_speed, | ||
3201 | narrow_speed, fallback_speed); | ||
3202 | } | ||
3203 | #endif | ||
3204 | |||
3205 | if (cur_speed > 160000) { | ||
3206 | /* | ||
3207 | * Paced/DT/IU_REQ only transfer speeds. All we | ||
3208 | * can do is fallback in terms of syncrate. | ||
3209 | */ | ||
3210 | period++; | ||
3211 | } else if (cur_speed > 80000) { | ||
3212 | if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { | ||
3213 | /* | ||
3214 | * Try without IU_REQ as it may be confusing | ||
3215 | * an expander. | ||
3216 | */ | ||
3217 | ppr_options &= ~MSG_EXT_PPR_IU_REQ; | ||
3218 | } else { | ||
3219 | /* | ||
3220 | * Paced/DT only transfer speeds. All we | ||
3221 | * can do is fallback in terms of syncrate. | ||
3222 | */ | ||
3223 | period++; | ||
3224 | ppr_options = targ->dv_max_ppr_options; | ||
3225 | } | ||
3226 | } else if (cur_speed > 3300) { | ||
3227 | |||
3228 | /* | ||
3229 | * In this range we the following | ||
3230 | * options ordered from highest to | ||
3231 | * lowest desireability: | ||
3232 | * | ||
3233 | * o Wide/DT | ||
3234 | * o Wide/non-DT | ||
3235 | * o Narrow at a potentally higher sync rate. | ||
3236 | * | ||
3237 | * All modes are tested with and without IU_REQ | ||
3238 | * set since using IUs may confuse an expander. | ||
3239 | */ | ||
3240 | if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { | ||
3241 | |||
3242 | ppr_options &= ~MSG_EXT_PPR_IU_REQ; | ||
3243 | } else if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) { | ||
3244 | /* | ||
3245 | * Try going non-DT. | ||
3246 | */ | ||
3247 | ppr_options = targ->dv_max_ppr_options; | ||
3248 | ppr_options &= ~MSG_EXT_PPR_DT_REQ; | ||
3249 | } else if (targ->dv_last_ppr_options != 0) { | ||
3250 | /* | ||
3251 | * Try without QAS or any other PPR options. | ||
3252 | * We may need a non-PPR message to work with | ||
3253 | * an expander. We look at the "last PPR options" | ||
3254 | * so we will perform this fallback even if the | ||
3255 | * target responded to our PPR negotiation with | ||
3256 | * no option bits set. | ||
3257 | */ | ||
3258 | ppr_options = 0; | ||
3259 | } else if (width == MSG_EXT_WDTR_BUS_16_BIT) { | ||
3260 | /* | ||
3261 | * If the next narrow speed is greater than | ||
3262 | * the next wide speed, fallback to narrow. | ||
3263 | * Otherwise fallback to the next DT/Wide setting. | ||
3264 | * The narrow async speed will always be smaller | ||
3265 | * than the wide async speed, so handle this case | ||
3266 | * specifically. | ||
3267 | */ | ||
3268 | ppr_options = targ->dv_max_ppr_options; | ||
3269 | if (narrow_speed > fallback_speed | ||
3270 | || period >= AHC_ASYNC_XFER_PERIOD) { | ||
3271 | targ->dv_next_wide_period = period+1; | ||
3272 | width = MSG_EXT_WDTR_BUS_8_BIT; | ||
3273 | period = targ->dv_next_narrow_period; | ||
3274 | } else { | ||
3275 | period++; | ||
3276 | } | ||
3277 | } else if ((ahc->features & AHC_WIDE) != 0 | ||
3278 | && targ->dv_max_width != 0 | ||
3279 | && wide_speed >= fallback_speed | ||
3280 | && (targ->dv_next_wide_period <= AHC_ASYNC_XFER_PERIOD | ||
3281 | || period >= AHC_ASYNC_XFER_PERIOD)) { | ||
3282 | |||
3283 | /* | ||
3284 | * We are narrow. Try falling back | ||
3285 | * to the next wide speed with | ||
3286 | * all supported ppr options set. | ||
3287 | */ | ||
3288 | targ->dv_next_narrow_period = period+1; | ||
3289 | width = MSG_EXT_WDTR_BUS_16_BIT; | ||
3290 | period = targ->dv_next_wide_period; | ||
3291 | ppr_options = targ->dv_max_ppr_options; | ||
3292 | } else { | ||
3293 | /* Only narrow fallback is allowed. */ | ||
3294 | period++; | ||
3295 | ppr_options = targ->dv_max_ppr_options; | ||
3296 | } | ||
3297 | } else { | ||
3298 | ahc_unlock(ahc, &s); | ||
3299 | return (-1); | ||
3300 | } | ||
3301 | offset = MAX_OFFSET; | ||
3302 | syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, | ||
3303 | AHC_SYNCRATE_DT); | ||
3304 | ahc_set_width(ahc, devinfo, width, AHC_TRANS_GOAL, FALSE); | ||
3305 | if (period == 0) { | ||
3306 | period = 0; | ||
3307 | offset = 0; | ||
3308 | ppr_options = 0; | ||
3309 | if (width == MSG_EXT_WDTR_BUS_8_BIT) | ||
3310 | targ->dv_next_narrow_period = AHC_ASYNC_XFER_PERIOD; | ||
3311 | else | ||
3312 | targ->dv_next_wide_period = AHC_ASYNC_XFER_PERIOD; | ||
3313 | } | ||
3314 | ahc_set_syncrate(ahc, devinfo, syncrate, period, offset, | ||
3315 | ppr_options, AHC_TRANS_GOAL, FALSE); | ||
3316 | targ->dv_last_ppr_options = ppr_options; | ||
3317 | ahc_unlock(ahc, &s); | ||
3318 | return (0); | ||
3319 | } | ||
3320 | |||
3321 | static void | ||
3322 | ahc_linux_dv_timeout(struct scsi_cmnd *cmd) | ||
3323 | { | ||
3324 | struct ahc_softc *ahc; | ||
3325 | struct scb *scb; | ||
3326 | u_long flags; | ||
3327 | |||
3328 | ahc = *((struct ahc_softc **)cmd->device->host->hostdata); | ||
3329 | ahc_lock(ahc, &flags); | ||
3330 | |||
3331 | #ifdef AHC_DEBUG | ||
3332 | if (ahc_debug & AHC_SHOW_DV) { | ||
3333 | printf("%s: Timeout while doing DV command %x.\n", | ||
3334 | ahc_name(ahc), cmd->cmnd[0]); | ||
3335 | ahc_dump_card_state(ahc); | ||
3336 | } | ||
3337 | #endif | ||
3338 | |||
3339 | /* | ||
3340 | * Guard against "done race". No action is | ||
3341 | * required if we just completed. | ||
3342 | */ | ||
3343 | if ((scb = (struct scb *)cmd->host_scribble) == NULL) { | ||
3344 | ahc_unlock(ahc, &flags); | ||
3345 | return; | ||
3346 | } | ||
3347 | |||
3348 | /* | ||
3349 | * Command has not completed. Mark this | ||
3350 | * SCB as having failing status prior to | ||
3351 | * resetting the bus, so we get the correct | ||
3352 | * error code. | ||
3353 | */ | ||
3354 | if ((scb->flags & SCB_SENSE) != 0) | ||
3355 | ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); | ||
3356 | else | ||
3357 | ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); | ||
3358 | ahc_reset_channel(ahc, cmd->device->channel + 'A', /*initiate*/TRUE); | ||
3359 | |||
3360 | /* | ||
3361 | * Add a minimal bus settle delay for devices that are slow to | ||
3362 | * respond after bus resets. | ||
3363 | */ | ||
3364 | ahc_linux_freeze_simq(ahc); | ||
3365 | init_timer(&ahc->platform_data->reset_timer); | ||
3366 | ahc->platform_data->reset_timer.data = (u_long)ahc; | ||
3367 | ahc->platform_data->reset_timer.expires = jiffies + HZ / 2; | ||
3368 | ahc->platform_data->reset_timer.function = | ||
3369 | (ahc_linux_callback_t *)ahc_linux_release_simq; | ||
3370 | add_timer(&ahc->platform_data->reset_timer); | ||
3371 | if (ahc_linux_next_device_to_run(ahc) != NULL) | ||
3372 | ahc_schedule_runq(ahc); | ||
3373 | ahc_linux_run_complete_queue(ahc); | ||
3374 | ahc_unlock(ahc, &flags); | ||
3375 | } | ||
3376 | |||
3377 | static void | ||
3378 | ahc_linux_dv_complete(struct scsi_cmnd *cmd) | ||
3379 | { | ||
3380 | struct ahc_softc *ahc; | ||
3381 | |||
3382 | ahc = *((struct ahc_softc **)cmd->device->host->hostdata); | ||
3383 | |||
3384 | /* Delete the DV timer before it goes off! */ | ||
3385 | scsi_delete_timer(cmd); | ||
3386 | |||
3387 | #ifdef AHC_DEBUG | ||
3388 | if (ahc_debug & AHC_SHOW_DV) | ||
3389 | printf("%s:%d:%d: Command completed, status= 0x%x\n", | ||
3390 | ahc_name(ahc), cmd->device->channel, | ||
3391 | cmd->device->id, cmd->result); | ||
3392 | #endif | ||
3393 | |||
3394 | /* Wake up the state machine */ | ||
3395 | up(&ahc->platform_data->dv_cmd_sem); | ||
3396 | } | ||
3397 | |||
3398 | static void | ||
3399 | ahc_linux_generate_dv_pattern(struct ahc_linux_target *targ) | ||
3400 | { | ||
3401 | uint16_t b; | ||
3402 | u_int i; | ||
3403 | u_int j; | ||
3404 | |||
3405 | if (targ->dv_buffer != NULL) | ||
3406 | free(targ->dv_buffer, M_DEVBUF); | ||
3407 | targ->dv_buffer = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK); | ||
3408 | if (targ->dv_buffer1 != NULL) | ||
3409 | free(targ->dv_buffer1, M_DEVBUF); | ||
3410 | targ->dv_buffer1 = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK); | ||
3411 | |||
3412 | i = 0; | ||
3413 | b = 0x0001; | ||
3414 | for (j = 0 ; i < targ->dv_echo_size; j++) { | ||
3415 | if (j < 32) { | ||
3416 | /* | ||
3417 | * 32bytes of sequential numbers. | ||
3418 | */ | ||
3419 | targ->dv_buffer[i++] = j & 0xff; | ||
3420 | } else if (j < 48) { | ||
3421 | /* | ||
3422 | * 32bytes of repeating 0x0000, 0xffff. | ||
3423 | */ | ||
3424 | targ->dv_buffer[i++] = (j & 0x02) ? 0xff : 0x00; | ||
3425 | } else if (j < 64) { | ||
3426 | /* | ||
3427 | * 32bytes of repeating 0x5555, 0xaaaa. | ||
3428 | */ | ||
3429 | targ->dv_buffer[i++] = (j & 0x02) ? 0xaa : 0x55; | ||
3430 | } else { | ||
3431 | /* | ||
3432 | * Remaining buffer is filled with a repeating | ||
3433 | * patter of: | ||
3434 | * | ||
3435 | * 0xffff | ||
3436 | * ~0x0001 << shifted once in each loop. | ||
3437 | */ | ||
3438 | if (j & 0x02) { | ||
3439 | if (j & 0x01) { | ||
3440 | targ->dv_buffer[i++] = ~(b >> 8) & 0xff; | ||
3441 | b <<= 1; | ||
3442 | if (b == 0x0000) | ||
3443 | b = 0x0001; | ||
3444 | } else { | ||
3445 | targ->dv_buffer[i++] = (~b & 0xff); | ||
3446 | } | ||
3447 | } else { | ||
3448 | targ->dv_buffer[i++] = 0xff; | ||
3449 | } | ||
3450 | } | ||
3451 | } | ||
3452 | } | ||
3453 | |||
3454 | static u_int | 1988 | static u_int |
3455 | ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) | 1989 | ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) |
3456 | { | 1990 | { |
@@ -3482,48 +2016,6 @@ ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) | |||
3482 | return (tags); | 2016 | return (tags); |
3483 | } | 2017 | } |
3484 | 2018 | ||
3485 | static u_int | ||
3486 | ahc_linux_user_dv_setting(struct ahc_softc *ahc) | ||
3487 | { | ||
3488 | static int warned_user; | ||
3489 | int dv; | ||
3490 | |||
3491 | if (ahc->unit >= NUM_ELEMENTS(aic7xxx_dv_settings)) { | ||
3492 | if (warned_user == 0) { | ||
3493 | |||
3494 | printf(KERN_WARNING | ||
3495 | "aic7xxx: WARNING: Insufficient dv settings instances\n" | ||
3496 | "aic7xxx: for installed controllers. Using defaults\n" | ||
3497 | "aic7xxx: Please update the aic7xxx_dv_settings array\n" | ||
3498 | "aic7xxx: in the aic7xxx_osm.c source file.\n"); | ||
3499 | warned_user++; | ||
3500 | } | ||
3501 | dv = -1; | ||
3502 | } else { | ||
3503 | |||
3504 | dv = aic7xxx_dv_settings[ahc->unit]; | ||
3505 | } | ||
3506 | |||
3507 | if (dv < 0) { | ||
3508 | u_long s; | ||
3509 | |||
3510 | /* | ||
3511 | * Apply the default. | ||
3512 | */ | ||
3513 | /* | ||
3514 | * XXX - Enable DV on non-U160 controllers once it | ||
3515 | * has been tested there. | ||
3516 | */ | ||
3517 | ahc_lock(ahc, &s); | ||
3518 | dv = (ahc->features & AHC_DT); | ||
3519 | if (ahc->seep_config != 0 | ||
3520 | && ahc->seep_config->signature >= CFSIGNATURE2) | ||
3521 | dv = (ahc->seep_config->adapter_control & CFENABLEDV); | ||
3522 | ahc_unlock(ahc, &s); | ||
3523 | } | ||
3524 | return (dv); | ||
3525 | } | ||
3526 | |||
3527 | /* | 2019 | /* |
3528 | * Determines the queue depth for a given device. | 2020 | * Determines the queue depth for a given device. |
3529 | */ | 2021 | */ |
@@ -3574,8 +2066,7 @@ ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev) | |||
3574 | * Schedule us to run later. The only reason we are not | 2066 | * Schedule us to run later. The only reason we are not |
3575 | * running is because the whole controller Q is frozen. | 2067 | * running is because the whole controller Q is frozen. |
3576 | */ | 2068 | */ |
3577 | if (ahc->platform_data->qfrozen != 0 | 2069 | if (ahc->platform_data->qfrozen != 0) { |
3578 | && AHC_DV_SIMQ_FROZEN(ahc) == 0) { | ||
3579 | TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, | 2070 | TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, |
3580 | dev, links); | 2071 | dev, links); |
3581 | dev->flags |= AHC_DEV_ON_RUN_LIST; | 2072 | dev->flags |= AHC_DEV_ON_RUN_LIST; |
@@ -3616,9 +2107,6 @@ ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev) | |||
3616 | if ((ahc->user_discenable & mask) != 0) | 2107 | if ((ahc->user_discenable & mask) != 0) |
3617 | hscb->control |= DISCENB; | 2108 | hscb->control |= DISCENB; |
3618 | 2109 | ||
3619 | if (AHC_DV_CMD(cmd) != 0) | ||
3620 | scb->flags |= SCB_SILENT; | ||
3621 | |||
3622 | if ((tstate->auto_negotiate & mask) != 0) { | 2110 | if ((tstate->auto_negotiate & mask) != 0) { |
3623 | scb->flags |= SCB_AUTO_NEGOTIATE; | 2111 | scb->flags |= SCB_AUTO_NEGOTIATE; |
3624 | scb->hscb->control |= MK_MESSAGE; | 2112 | scb->hscb->control |= MK_MESSAGE; |
@@ -3811,7 +2299,6 @@ ahc_linux_alloc_target(struct ahc_softc *ahc, u_int channel, u_int target) | |||
3811 | targ->channel = channel; | 2299 | targ->channel = channel; |
3812 | targ->target = target; | 2300 | targ->target = target; |
3813 | targ->ahc = ahc; | 2301 | targ->ahc = ahc; |
3814 | targ->flags = AHC_DV_REQUIRED; | ||
3815 | ahc->platform_data->targets[target_offset] = targ; | 2302 | ahc->platform_data->targets[target_offset] = targ; |
3816 | return (targ); | 2303 | return (targ); |
3817 | } | 2304 | } |
@@ -3850,10 +2337,6 @@ ahc_linux_free_target(struct ahc_softc *ahc, struct ahc_linux_target *targ) | |||
3850 | ahc->platform_data->targets[target_offset] = NULL; | 2337 | ahc->platform_data->targets[target_offset] = NULL; |
3851 | if (targ->inq_data != NULL) | 2338 | if (targ->inq_data != NULL) |
3852 | free(targ->inq_data, M_DEVBUF); | 2339 | free(targ->inq_data, M_DEVBUF); |
3853 | if (targ->dv_buffer != NULL) | ||
3854 | free(targ->dv_buffer, M_DEVBUF); | ||
3855 | if (targ->dv_buffer1 != NULL) | ||
3856 | free(targ->dv_buffer1, M_DEVBUF); | ||
3857 | free(targ, M_DEVBUF); | 2340 | free(targ, M_DEVBUF); |
3858 | } | 2341 | } |
3859 | 2342 | ||
@@ -3900,8 +2383,7 @@ __ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) | |||
3900 | targ->devices[dev->lun] = NULL; | 2383 | targ->devices[dev->lun] = NULL; |
3901 | free(dev, M_DEVBUF); | 2384 | free(dev, M_DEVBUF); |
3902 | targ->refcount--; | 2385 | targ->refcount--; |
3903 | if (targ->refcount == 0 | 2386 | if (targ->refcount == 0) |
3904 | && (targ->flags & AHC_DV_REQUIRED) == 0) | ||
3905 | ahc_linux_free_target(ahc, targ); | 2387 | ahc_linux_free_target(ahc, targ); |
3906 | } | 2388 | } |
3907 | 2389 | ||
@@ -4105,16 +2587,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) | |||
4105 | ahc_linux_handle_scsi_status(ahc, dev, scb); | 2587 | ahc_linux_handle_scsi_status(ahc, dev, scb); |
4106 | } else if (ahc_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { | 2588 | } else if (ahc_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { |
4107 | dev->flags |= AHC_DEV_UNCONFIGURED; | 2589 | dev->flags |= AHC_DEV_UNCONFIGURED; |
4108 | if (AHC_DV_CMD(cmd) == FALSE) | ||
4109 | dev->target->flags &= ~AHC_DV_REQUIRED; | ||
4110 | } | 2590 | } |
4111 | /* | ||
4112 | * Start DV for devices that require it assuming the first command | ||
4113 | * sent does not result in a selection timeout. | ||
4114 | */ | ||
4115 | if (ahc_get_transaction_status(scb) != CAM_SEL_TIMEOUT | ||
4116 | && (dev->target->flags & AHC_DV_REQUIRED) != 0) | ||
4117 | ahc_linux_start_dv(ahc); | ||
4118 | 2591 | ||
4119 | if (dev->openings == 1 | 2592 | if (dev->openings == 1 |
4120 | && ahc_get_transaction_status(scb) == CAM_REQ_CMP | 2593 | && ahc_get_transaction_status(scb) == CAM_REQ_CMP |
@@ -4158,13 +2631,6 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) | |||
4158 | 2631 | ||
4159 | ahc_free_scb(ahc, scb); | 2632 | ahc_free_scb(ahc, scb); |
4160 | ahc_linux_queue_cmd_complete(ahc, cmd); | 2633 | ahc_linux_queue_cmd_complete(ahc, cmd); |
4161 | |||
4162 | if ((ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_EMPTY) != 0 | ||
4163 | && LIST_FIRST(&ahc->pending_scbs) == NULL) { | ||
4164 | ahc->platform_data->flags &= ~AHC_DV_WAIT_SIMQ_EMPTY; | ||
4165 | up(&ahc->platform_data->dv_sem); | ||
4166 | } | ||
4167 | |||
4168 | } | 2634 | } |
4169 | 2635 | ||
4170 | static void | 2636 | static void |
@@ -4341,7 +2807,7 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd) | |||
4341 | * full error information available when making | 2807 | * full error information available when making |
4342 | * state change decisions. | 2808 | * state change decisions. |
4343 | */ | 2809 | */ |
4344 | if (AHC_DV_CMD(cmd) == FALSE) { | 2810 | { |
4345 | u_int new_status; | 2811 | u_int new_status; |
4346 | 2812 | ||
4347 | switch (ahc_cmd_get_transaction_status(cmd)) { | 2813 | switch (ahc_cmd_get_transaction_status(cmd)) { |
@@ -4432,115 +2898,6 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd) | |||
4432 | } | 2898 | } |
4433 | 2899 | ||
4434 | static void | 2900 | static void |
4435 | ahc_linux_filter_inquiry(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) | ||
4436 | { | ||
4437 | struct scsi_inquiry_data *sid; | ||
4438 | struct ahc_initiator_tinfo *tinfo; | ||
4439 | struct ahc_transinfo *user; | ||
4440 | struct ahc_transinfo *goal; | ||
4441 | struct ahc_transinfo *curr; | ||
4442 | struct ahc_tmode_tstate *tstate; | ||
4443 | struct ahc_syncrate *syncrate; | ||
4444 | struct ahc_linux_device *dev; | ||
4445 | u_int maxsync; | ||
4446 | u_int width; | ||
4447 | u_int period; | ||
4448 | u_int offset; | ||
4449 | u_int ppr_options; | ||
4450 | u_int trans_version; | ||
4451 | u_int prot_version; | ||
4452 | |||
4453 | /* | ||
4454 | * Determine if this lun actually exists. If so, | ||
4455 | * hold on to its corresponding device structure. | ||
4456 | * If not, make sure we release the device and | ||
4457 | * don't bother processing the rest of this inquiry | ||
4458 | * command. | ||
4459 | */ | ||
4460 | dev = ahc_linux_get_device(ahc, devinfo->channel - 'A', | ||
4461 | devinfo->target, devinfo->lun, | ||
4462 | /*alloc*/TRUE); | ||
4463 | |||
4464 | sid = (struct scsi_inquiry_data *)dev->target->inq_data; | ||
4465 | if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) { | ||
4466 | |||
4467 | dev->flags &= ~AHC_DEV_UNCONFIGURED; | ||
4468 | } else { | ||
4469 | dev->flags |= AHC_DEV_UNCONFIGURED; | ||
4470 | return; | ||
4471 | } | ||
4472 | |||
4473 | /* | ||
4474 | * Update our notion of this device's transfer | ||
4475 | * negotiation capabilities. | ||
4476 | */ | ||
4477 | tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, | ||
4478 | devinfo->our_scsiid, | ||
4479 | devinfo->target, &tstate); | ||
4480 | user = &tinfo->user; | ||
4481 | goal = &tinfo->goal; | ||
4482 | curr = &tinfo->curr; | ||
4483 | width = user->width; | ||
4484 | period = user->period; | ||
4485 | offset = user->offset; | ||
4486 | ppr_options = user->ppr_options; | ||
4487 | trans_version = user->transport_version; | ||
4488 | prot_version = MIN(user->protocol_version, SID_ANSI_REV(sid)); | ||
4489 | |||
4490 | /* | ||
4491 | * Only attempt SPI3/4 once we've verified that | ||
4492 | * the device claims to support SPI3/4 features. | ||
4493 | */ | ||
4494 | if (prot_version < SCSI_REV_2) | ||
4495 | trans_version = SID_ANSI_REV(sid); | ||
4496 | else | ||
4497 | trans_version = SCSI_REV_2; | ||
4498 | |||
4499 | if ((sid->flags & SID_WBus16) == 0) | ||
4500 | width = MSG_EXT_WDTR_BUS_8_BIT; | ||
4501 | if ((sid->flags & SID_Sync) == 0) { | ||
4502 | period = 0; | ||
4503 | offset = 0; | ||
4504 | ppr_options = 0; | ||
4505 | } | ||
4506 | if ((sid->spi3data & SID_SPI_QAS) == 0) | ||
4507 | ppr_options &= ~MSG_EXT_PPR_QAS_REQ; | ||
4508 | if ((sid->spi3data & SID_SPI_CLOCK_DT) == 0) | ||
4509 | ppr_options &= MSG_EXT_PPR_QAS_REQ; | ||
4510 | if ((sid->spi3data & SID_SPI_IUS) == 0) | ||
4511 | ppr_options &= (MSG_EXT_PPR_DT_REQ | ||
4512 | | MSG_EXT_PPR_QAS_REQ); | ||
4513 | |||
4514 | if (prot_version > SCSI_REV_2 | ||
4515 | && ppr_options != 0) | ||
4516 | trans_version = user->transport_version; | ||
4517 | |||
4518 | ahc_validate_width(ahc, /*tinfo limit*/NULL, &width, ROLE_UNKNOWN); | ||
4519 | if ((ahc->features & AHC_ULTRA2) != 0) | ||
4520 | maxsync = AHC_SYNCRATE_DT; | ||
4521 | else if ((ahc->features & AHC_ULTRA) != 0) | ||
4522 | maxsync = AHC_SYNCRATE_ULTRA; | ||
4523 | else | ||
4524 | maxsync = AHC_SYNCRATE_FAST; | ||
4525 | |||
4526 | syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, maxsync); | ||
4527 | ahc_validate_offset(ahc, /*tinfo limit*/NULL, syncrate, | ||
4528 | &offset, width, ROLE_UNKNOWN); | ||
4529 | if (offset == 0 || period == 0) { | ||
4530 | period = 0; | ||
4531 | offset = 0; | ||
4532 | ppr_options = 0; | ||
4533 | } | ||
4534 | /* Apply our filtered user settings. */ | ||
4535 | curr->transport_version = trans_version; | ||
4536 | curr->protocol_version = prot_version; | ||
4537 | ahc_set_width(ahc, devinfo, width, AHC_TRANS_GOAL, /*paused*/FALSE); | ||
4538 | ahc_set_syncrate(ahc, devinfo, syncrate, period, | ||
4539 | offset, ppr_options, AHC_TRANS_GOAL, | ||
4540 | /*paused*/FALSE); | ||
4541 | } | ||
4542 | |||
4543 | static void | ||
4544 | ahc_linux_sem_timeout(u_long arg) | 2901 | ahc_linux_sem_timeout(u_long arg) |
4545 | { | 2902 | { |
4546 | struct ahc_softc *ahc; | 2903 | struct ahc_softc *ahc; |
@@ -4585,11 +2942,6 @@ ahc_linux_release_simq(u_long arg) | |||
4585 | ahc->platform_data->qfrozen--; | 2942 | ahc->platform_data->qfrozen--; |
4586 | if (ahc->platform_data->qfrozen == 0) | 2943 | if (ahc->platform_data->qfrozen == 0) |
4587 | unblock_reqs = 1; | 2944 | unblock_reqs = 1; |
4588 | if (AHC_DV_SIMQ_FROZEN(ahc) | ||
4589 | && ((ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_RELEASE) != 0)) { | ||
4590 | ahc->platform_data->flags &= ~AHC_DV_WAIT_SIMQ_RELEASE; | ||
4591 | up(&ahc->platform_data->dv_sem); | ||
4592 | } | ||
4593 | ahc_schedule_runq(ahc); | 2945 | ahc_schedule_runq(ahc); |
4594 | ahc_unlock(ahc, &s); | 2946 | ahc_unlock(ahc, &s); |
4595 | /* | 2947 | /* |
@@ -5274,19 +3626,6 @@ ahc_linux_init(void) | |||
5274 | static void | 3626 | static void |
5275 | ahc_linux_exit(void) | 3627 | ahc_linux_exit(void) |
5276 | { | 3628 | { |
5277 | struct ahc_softc *ahc; | ||
5278 | |||
5279 | /* | ||
5280 | * Shutdown DV threads before going into the SCSI mid-layer. | ||
5281 | * This avoids situations where the mid-layer locks the entire | ||
5282 | * kernel so that waiting for our DV threads to exit leads | ||
5283 | * to deadlock. | ||
5284 | */ | ||
5285 | TAILQ_FOREACH(ahc, &ahc_tailq, links) { | ||
5286 | |||
5287 | ahc_linux_kill_dv_thread(ahc); | ||
5288 | } | ||
5289 | |||
5290 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 3629 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) |
5291 | /* | 3630 | /* |
5292 | * In 2.4 we have to unregister from the PCI core _after_ | 3631 | * In 2.4 we have to unregister from the PCI core _after_ |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index db3bd6321dd4..c401537067b6 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h | |||
@@ -424,27 +424,9 @@ struct ahc_linux_device { | |||
424 | }; | 424 | }; |
425 | 425 | ||
426 | typedef enum { | 426 | typedef enum { |
427 | AHC_DV_REQUIRED = 0x01, | ||
428 | AHC_INQ_VALID = 0x02, | 427 | AHC_INQ_VALID = 0x02, |
429 | AHC_BASIC_DV = 0x04, | ||
430 | AHC_ENHANCED_DV = 0x08 | ||
431 | } ahc_linux_targ_flags; | 428 | } ahc_linux_targ_flags; |
432 | 429 | ||
433 | /* DV States */ | ||
434 | typedef enum { | ||
435 | AHC_DV_STATE_EXIT = 0, | ||
436 | AHC_DV_STATE_INQ_SHORT_ASYNC, | ||
437 | AHC_DV_STATE_INQ_ASYNC, | ||
438 | AHC_DV_STATE_INQ_ASYNC_VERIFY, | ||
439 | AHC_DV_STATE_TUR, | ||
440 | AHC_DV_STATE_REBD, | ||
441 | AHC_DV_STATE_INQ_VERIFY, | ||
442 | AHC_DV_STATE_WEB, | ||
443 | AHC_DV_STATE_REB, | ||
444 | AHC_DV_STATE_SU, | ||
445 | AHC_DV_STATE_BUSY | ||
446 | } ahc_dv_state; | ||
447 | |||
448 | struct ahc_linux_target { | 430 | struct ahc_linux_target { |
449 | struct ahc_linux_device *devices[AHC_NUM_LUNS]; | 431 | struct ahc_linux_device *devices[AHC_NUM_LUNS]; |
450 | int channel; | 432 | int channel; |
@@ -454,19 +436,6 @@ struct ahc_linux_target { | |||
454 | struct ahc_softc *ahc; | 436 | struct ahc_softc *ahc; |
455 | ahc_linux_targ_flags flags; | 437 | ahc_linux_targ_flags flags; |
456 | struct scsi_inquiry_data *inq_data; | 438 | struct scsi_inquiry_data *inq_data; |
457 | /* | ||
458 | * The next "fallback" period to use for narrow/wide transfers. | ||
459 | */ | ||
460 | uint8_t dv_next_narrow_period; | ||
461 | uint8_t dv_next_wide_period; | ||
462 | uint8_t dv_max_width; | ||
463 | uint8_t dv_max_ppr_options; | ||
464 | uint8_t dv_last_ppr_options; | ||
465 | u_int dv_echo_size; | ||
466 | ahc_dv_state dv_state; | ||
467 | u_int dv_state_retry; | ||
468 | char *dv_buffer; | ||
469 | char *dv_buffer1; | ||
470 | }; | 439 | }; |
471 | 440 | ||
472 | /********************* Definitions Required by the Core ***********************/ | 441 | /********************* Definitions Required by the Core ***********************/ |
@@ -511,10 +480,6 @@ struct scb_platform_data { | |||
511 | * this driver. | 480 | * this driver. |
512 | */ | 481 | */ |
513 | typedef enum { | 482 | typedef enum { |
514 | AHC_DV_WAIT_SIMQ_EMPTY = 0x01, | ||
515 | AHC_DV_WAIT_SIMQ_RELEASE = 0x02, | ||
516 | AHC_DV_ACTIVE = 0x04, | ||
517 | AHC_DV_SHUTDOWN = 0x08, | ||
518 | AHC_RUN_CMPLT_Q_TIMER = 0x10 | 483 | AHC_RUN_CMPLT_Q_TIMER = 0x10 |
519 | } ahc_linux_softc_flags; | 484 | } ahc_linux_softc_flags; |
520 | 485 | ||
@@ -937,11 +902,6 @@ int ahc_linux_proc_info(struct Scsi_Host *, char *, char **, | |||
937 | #endif | 902 | #endif |
938 | 903 | ||
939 | /*************************** Domain Validation ********************************/ | 904 | /*************************** Domain Validation ********************************/ |
940 | #define AHC_DV_CMD(cmd) ((cmd)->scsi_done == ahc_linux_dv_complete) | ||
941 | #define AHC_DV_SIMQ_FROZEN(ahc) \ | ||
942 | ((((ahc)->platform_data->flags & AHC_DV_ACTIVE) != 0) \ | ||
943 | && (ahc)->platform_data->qfrozen == 1) | ||
944 | |||
945 | /*********************** Transaction Access Wrappers *************************/ | 905 | /*********************** Transaction Access Wrappers *************************/ |
946 | static __inline void ahc_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); | 906 | static __inline void ahc_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); |
947 | static __inline void ahc_set_transaction_status(struct scb *, uint32_t); | 907 | static __inline void ahc_set_transaction_status(struct scb *, uint32_t); |