diff options
author | Hannes Reinecke <hare@suse.de> | 2006-03-08 06:58:16 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-03-12 10:05:18 -0500 |
commit | 6902f41610d631f74cfca7c61eac7b0950dd8990 (patch) | |
tree | ee084da4fdd3fff54982e79034ee2a284c57cc3c | |
parent | 1ede5f9fe59ea245ad0ba859cfb08ac5814f6269 (diff) |
[SCSI] aic79xx: Update error recovery
This patch updates the error recovery. Routines for TARGET RESET
and ABORT COMMAND are split up as the logic is quite dissimilar.
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm.c | 325 |
1 files changed, 201 insertions, 124 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index cb5f7af606ed..00d48a0fb7e1 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
@@ -373,7 +373,7 @@ static void ahd_linux_handle_scsi_status(struct ahd_softc *, | |||
373 | struct scb *); | 373 | struct scb *); |
374 | static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, | 374 | static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, |
375 | struct scsi_cmnd *cmd); | 375 | struct scsi_cmnd *cmd); |
376 | static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); | 376 | static int ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd); |
377 | static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); | 377 | static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); |
378 | static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, | 378 | static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, |
379 | struct ahd_devinfo *devinfo); | 379 | struct ahd_devinfo *devinfo); |
@@ -648,10 +648,9 @@ static int | |||
648 | ahd_linux_abort(struct scsi_cmnd *cmd) | 648 | ahd_linux_abort(struct scsi_cmnd *cmd) |
649 | { | 649 | { |
650 | int error; | 650 | int error; |
651 | |||
652 | error = ahd_linux_queue_abort_cmd(cmd); | ||
651 | 653 | ||
652 | error = ahd_linux_queue_recovery_cmd(cmd, SCB_ABORT); | ||
653 | if (error != 0) | ||
654 | printf("aic79xx_abort returns 0x%x\n", error); | ||
655 | return error; | 654 | return error; |
656 | } | 655 | } |
657 | 656 | ||
@@ -661,12 +660,97 @@ ahd_linux_abort(struct scsi_cmnd *cmd) | |||
661 | static int | 660 | static int |
662 | ahd_linux_dev_reset(struct scsi_cmnd *cmd) | 661 | ahd_linux_dev_reset(struct scsi_cmnd *cmd) |
663 | { | 662 | { |
664 | int error; | 663 | struct ahd_softc *ahd; |
664 | struct ahd_linux_device *dev; | ||
665 | struct scb *reset_scb; | ||
666 | u_int cdb_byte; | ||
667 | int retval = SUCCESS; | ||
668 | int paused; | ||
669 | int wait; | ||
670 | struct ahd_initiator_tinfo *tinfo; | ||
671 | struct ahd_tmode_tstate *tstate; | ||
672 | unsigned long flags; | ||
673 | DECLARE_COMPLETION(done); | ||
665 | 674 | ||
666 | error = ahd_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET); | 675 | reset_scb = NULL; |
667 | if (error != 0) | 676 | paused = FALSE; |
668 | printf("aic79xx_dev_reset returns 0x%x\n", error); | 677 | wait = FALSE; |
669 | return error; | 678 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; |
679 | |||
680 | scmd_printk(KERN_INFO, cmd, | ||
681 | "Attempting to queue a TARGET RESET message:"); | ||
682 | |||
683 | printf("CDB:"); | ||
684 | for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) | ||
685 | printf(" 0x%x", cmd->cmnd[cdb_byte]); | ||
686 | printf("\n"); | ||
687 | |||
688 | /* | ||
689 | * Determine if we currently own this command. | ||
690 | */ | ||
691 | dev = scsi_transport_device_data(cmd->device); | ||
692 | |||
693 | if (dev == NULL) { | ||
694 | /* | ||
695 | * No target device for this command exists, | ||
696 | * so we must not still own the command. | ||
697 | */ | ||
698 | scmd_printk(KERN_INFO, cmd, "Is not an active device\n"); | ||
699 | return SUCCESS; | ||
700 | } | ||
701 | |||
702 | /* | ||
703 | * Generate us a new SCB | ||
704 | */ | ||
705 | reset_scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX); | ||
706 | if (!reset_scb) { | ||
707 | scmd_printk(KERN_INFO, cmd, "No SCB available\n"); | ||
708 | return FAILED; | ||
709 | } | ||
710 | |||
711 | tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, | ||
712 | cmd->device->id, &tstate); | ||
713 | reset_scb->io_ctx = cmd; | ||
714 | reset_scb->platform_data->dev = dev; | ||
715 | reset_scb->sg_count = 0; | ||
716 | ahd_set_residual(reset_scb, 0); | ||
717 | ahd_set_sense_residual(reset_scb, 0); | ||
718 | reset_scb->platform_data->xfer_len = 0; | ||
719 | reset_scb->hscb->control = 0; | ||
720 | reset_scb->hscb->scsiid = BUILD_SCSIID(ahd,cmd); | ||
721 | reset_scb->hscb->lun = cmd->device->lun; | ||
722 | reset_scb->hscb->cdb_len = 0; | ||
723 | reset_scb->hscb->task_management = SIU_TASKMGMT_LUN_RESET; | ||
724 | reset_scb->flags |= SCB_DEVICE_RESET|SCB_RECOVERY_SCB|SCB_ACTIVE; | ||
725 | if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { | ||
726 | reset_scb->flags |= SCB_PACKETIZED; | ||
727 | } else { | ||
728 | reset_scb->hscb->control |= MK_MESSAGE; | ||
729 | } | ||
730 | dev->openings--; | ||
731 | dev->active++; | ||
732 | dev->commands_issued++; | ||
733 | |||
734 | ahd_lock(ahd, &flags); | ||
735 | |||
736 | LIST_INSERT_HEAD(&ahd->pending_scbs, reset_scb, pending_links); | ||
737 | ahd_queue_scb(ahd, reset_scb); | ||
738 | |||
739 | ahd->platform_data->eh_done = &done; | ||
740 | ahd_unlock(ahd, &flags); | ||
741 | |||
742 | printf("%s: Device reset code sleeping\n", ahd_name(ahd)); | ||
743 | if (!wait_for_completion_timeout(&done, 5 * HZ)) { | ||
744 | ahd_lock(ahd, &flags); | ||
745 | ahd->platform_data->eh_done = NULL; | ||
746 | ahd_unlock(ahd, &flags); | ||
747 | printf("%s: Device reset timer expired (active %d)\n", | ||
748 | ahd_name(ahd), dev->active); | ||
749 | retval = FAILED; | ||
750 | } | ||
751 | printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval); | ||
752 | |||
753 | return (retval); | ||
670 | } | 754 | } |
671 | 755 | ||
672 | /* | 756 | /* |
@@ -1891,72 +1975,108 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, | |||
1891 | static void | 1975 | static void |
1892 | ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) | 1976 | ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) |
1893 | { | 1977 | { |
1978 | int status; | ||
1979 | int new_status = DID_OK; | ||
1980 | int do_fallback = 0; | ||
1981 | int scsi_status; | ||
1982 | |||
1894 | /* | 1983 | /* |
1895 | * Map CAM error codes into Linux Error codes. We | 1984 | * Map CAM error codes into Linux Error codes. We |
1896 | * avoid the conversion so that the DV code has the | 1985 | * avoid the conversion so that the DV code has the |
1897 | * full error information available when making | 1986 | * full error information available when making |
1898 | * state change decisions. | 1987 | * state change decisions. |
1899 | */ | 1988 | */ |
1900 | { | 1989 | |
1901 | uint32_t status; | 1990 | status = ahd_cmd_get_transaction_status(cmd); |
1902 | u_int new_status; | 1991 | switch (status) { |
1903 | 1992 | case CAM_REQ_INPROG: | |
1904 | status = ahd_cmd_get_transaction_status(cmd); | 1993 | case CAM_REQ_CMP: |
1905 | switch (status) { | 1994 | new_status = DID_OK; |
1906 | case CAM_REQ_INPROG: | 1995 | break; |
1907 | case CAM_REQ_CMP: | 1996 | case CAM_AUTOSENSE_FAIL: |
1908 | case CAM_SCSI_STATUS_ERROR: | 1997 | new_status = DID_ERROR; |
1909 | new_status = DID_OK; | 1998 | /* Fallthrough */ |
1910 | break; | 1999 | case CAM_SCSI_STATUS_ERROR: |
1911 | case CAM_REQ_ABORTED: | 2000 | scsi_status = ahd_cmd_get_scsi_status(cmd); |
1912 | new_status = DID_ABORT; | 2001 | |
1913 | break; | 2002 | switch(scsi_status) { |
1914 | case CAM_BUSY: | 2003 | case SCSI_STATUS_CMD_TERMINATED: |
1915 | new_status = DID_BUS_BUSY; | 2004 | case SCSI_STATUS_CHECK_COND: |
1916 | break; | 2005 | if ((cmd->result >> 24) != DRIVER_SENSE) { |
1917 | case CAM_REQ_INVALID: | 2006 | do_fallback = 1; |
1918 | case CAM_PATH_INVALID: | 2007 | } else { |
1919 | new_status = DID_BAD_TARGET; | 2008 | struct scsi_sense_data *sense; |
1920 | break; | 2009 | |
1921 | case CAM_SEL_TIMEOUT: | 2010 | sense = (struct scsi_sense_data *) |
1922 | new_status = DID_NO_CONNECT; | 2011 | &cmd->sense_buffer; |
1923 | break; | 2012 | if (sense->extra_len >= 5 && |
1924 | case CAM_SCSI_BUS_RESET: | 2013 | (sense->add_sense_code == 0x47 |
1925 | case CAM_BDR_SENT: | 2014 | || sense->add_sense_code == 0x48)) |
1926 | new_status = DID_RESET; | 2015 | do_fallback = 1; |
1927 | break; | 2016 | } |
1928 | case CAM_UNCOR_PARITY: | ||
1929 | new_status = DID_PARITY; | ||
1930 | break; | ||
1931 | case CAM_CMD_TIMEOUT: | ||
1932 | new_status = DID_TIME_OUT; | ||
1933 | break; | ||
1934 | case CAM_UA_ABORT: | ||
1935 | case CAM_REQ_CMP_ERR: | ||
1936 | case CAM_AUTOSENSE_FAIL: | ||
1937 | case CAM_NO_HBA: | ||
1938 | case CAM_DATA_RUN_ERR: | ||
1939 | case CAM_UNEXP_BUSFREE: | ||
1940 | case CAM_SEQUENCE_FAIL: | ||
1941 | case CAM_CCB_LEN_ERR: | ||
1942 | case CAM_PROVIDE_FAIL: | ||
1943 | case CAM_REQ_TERMIO: | ||
1944 | case CAM_UNREC_HBA_ERROR: | ||
1945 | case CAM_REQ_TOO_BIG: | ||
1946 | new_status = DID_ERROR; | ||
1947 | break; | ||
1948 | case CAM_REQUEUE_REQ: | ||
1949 | new_status = DID_REQUEUE; | ||
1950 | break; | 2017 | break; |
1951 | default: | 2018 | default: |
1952 | /* We should never get here */ | ||
1953 | new_status = DID_ERROR; | ||
1954 | break; | 2019 | break; |
1955 | } | 2020 | } |
2021 | break; | ||
2022 | case CAM_REQ_ABORTED: | ||
2023 | new_status = DID_ABORT; | ||
2024 | break; | ||
2025 | case CAM_BUSY: | ||
2026 | new_status = DID_BUS_BUSY; | ||
2027 | break; | ||
2028 | case CAM_REQ_INVALID: | ||
2029 | case CAM_PATH_INVALID: | ||
2030 | new_status = DID_BAD_TARGET; | ||
2031 | break; | ||
2032 | case CAM_SEL_TIMEOUT: | ||
2033 | new_status = DID_NO_CONNECT; | ||
2034 | break; | ||
2035 | case CAM_SCSI_BUS_RESET: | ||
2036 | case CAM_BDR_SENT: | ||
2037 | new_status = DID_RESET; | ||
2038 | break; | ||
2039 | case CAM_UNCOR_PARITY: | ||
2040 | new_status = DID_PARITY; | ||
2041 | do_fallback = 1; | ||
2042 | break; | ||
2043 | case CAM_CMD_TIMEOUT: | ||
2044 | new_status = DID_TIME_OUT; | ||
2045 | do_fallback = 1; | ||
2046 | break; | ||
2047 | case CAM_REQ_CMP_ERR: | ||
2048 | case CAM_UNEXP_BUSFREE: | ||
2049 | case CAM_DATA_RUN_ERR: | ||
2050 | new_status = DID_ERROR; | ||
2051 | do_fallback = 1; | ||
2052 | break; | ||
2053 | case CAM_UA_ABORT: | ||
2054 | case CAM_NO_HBA: | ||
2055 | case CAM_SEQUENCE_FAIL: | ||
2056 | case CAM_CCB_LEN_ERR: | ||
2057 | case CAM_PROVIDE_FAIL: | ||
2058 | case CAM_REQ_TERMIO: | ||
2059 | case CAM_UNREC_HBA_ERROR: | ||
2060 | case CAM_REQ_TOO_BIG: | ||
2061 | new_status = DID_ERROR; | ||
2062 | break; | ||
2063 | case CAM_REQUEUE_REQ: | ||
2064 | new_status = DID_REQUEUE; | ||
2065 | break; | ||
2066 | default: | ||
2067 | /* We should never get here */ | ||
2068 | new_status = DID_ERROR; | ||
2069 | break; | ||
2070 | } | ||
1956 | 2071 | ||
1957 | ahd_cmd_set_transaction_status(cmd, new_status); | 2072 | if (do_fallback) { |
2073 | printf("%s: device overrun (status %x) on %d:%d:%d\n", | ||
2074 | ahd_name(ahd), status, cmd->device->channel, | ||
2075 | cmd->device->id, cmd->device->lun); | ||
1958 | } | 2076 | } |
1959 | 2077 | ||
2078 | ahd_cmd_set_transaction_status(cmd, new_status); | ||
2079 | |||
1960 | cmd->scsi_done(cmd); | 2080 | cmd->scsi_done(cmd); |
1961 | } | 2081 | } |
1962 | 2082 | ||
@@ -1973,7 +2093,7 @@ ahd_release_simq(struct ahd_softc *ahd) | |||
1973 | } | 2093 | } |
1974 | 2094 | ||
1975 | static int | 2095 | static int |
1976 | ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) | 2096 | ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) |
1977 | { | 2097 | { |
1978 | struct ahd_softc *ahd; | 2098 | struct ahd_softc *ahd; |
1979 | struct ahd_linux_device *dev; | 2099 | struct ahd_linux_device *dev; |
@@ -1988,7 +2108,6 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) | |||
1988 | int paused; | 2108 | int paused; |
1989 | int wait; | 2109 | int wait; |
1990 | int disconnected; | 2110 | int disconnected; |
1991 | int found; | ||
1992 | ahd_mode_state saved_modes; | 2111 | ahd_mode_state saved_modes; |
1993 | unsigned long flags; | 2112 | unsigned long flags; |
1994 | 2113 | ||
@@ -1998,8 +2117,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) | |||
1998 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; | 2117 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; |
1999 | 2118 | ||
2000 | scmd_printk(KERN_INFO, cmd, | 2119 | scmd_printk(KERN_INFO, cmd, |
2001 | "Attempting to queue a%s message:", | 2120 | "Attempting to queue an ABORT message:"); |
2002 | flag == SCB_ABORT ? "n ABORT" : " TARGET RESET"); | ||
2003 | 2121 | ||
2004 | printf("CDB:"); | 2122 | printf("CDB:"); |
2005 | for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) | 2123 | for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) |
@@ -2035,19 +2153,6 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) | |||
2035 | break; | 2153 | break; |
2036 | } | 2154 | } |
2037 | 2155 | ||
2038 | if (pending_scb == NULL && flag == SCB_DEVICE_RESET) { | ||
2039 | |||
2040 | /* Any SCB for this device will do for a target reset */ | ||
2041 | LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { | ||
2042 | if (ahd_match_scb(ahd, pending_scb, | ||
2043 | scmd_id(cmd), | ||
2044 | scmd_channel(cmd) + 'A', | ||
2045 | CAM_LUN_WILDCARD, | ||
2046 | SCB_LIST_NULL, ROLE_INITIATOR)) | ||
2047 | break; | ||
2048 | } | ||
2049 | } | ||
2050 | |||
2051 | if (pending_scb == NULL) { | 2156 | if (pending_scb == NULL) { |
2052 | scmd_printk(KERN_INFO, cmd, "Command not found\n"); | 2157 | scmd_printk(KERN_INFO, cmd, "Command not found\n"); |
2053 | goto no_cmd; | 2158 | goto no_cmd; |
@@ -2081,25 +2186,17 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) | |||
2081 | ahd_dump_card_state(ahd); | 2186 | ahd_dump_card_state(ahd); |
2082 | 2187 | ||
2083 | disconnected = TRUE; | 2188 | disconnected = TRUE; |
2084 | if (flag == SCB_ABORT) { | 2189 | if (ahd_search_qinfifo(ahd, cmd->device->id, |
2085 | if (ahd_search_qinfifo(ahd, cmd->device->id, | 2190 | cmd->device->channel + 'A', |
2086 | cmd->device->channel + 'A', | 2191 | cmd->device->lun, |
2087 | cmd->device->lun, | 2192 | pending_scb->hscb->tag, |
2088 | pending_scb->hscb->tag, | 2193 | ROLE_INITIATOR, CAM_REQ_ABORTED, |
2089 | ROLE_INITIATOR, CAM_REQ_ABORTED, | 2194 | SEARCH_COMPLETE) > 0) { |
2090 | SEARCH_COMPLETE) > 0) { | 2195 | printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", |
2091 | printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", | 2196 | ahd_name(ahd), cmd->device->channel, |
2092 | ahd_name(ahd), cmd->device->channel, | 2197 | cmd->device->id, cmd->device->lun); |
2093 | cmd->device->id, cmd->device->lun); | 2198 | retval = SUCCESS; |
2094 | retval = SUCCESS; | 2199 | goto done; |
2095 | goto done; | ||
2096 | } | ||
2097 | } else if (ahd_search_qinfifo(ahd, cmd->device->id, | ||
2098 | cmd->device->channel + 'A', | ||
2099 | cmd->device->lun, pending_scb->hscb->tag, | ||
2100 | ROLE_INITIATOR, /*status*/0, | ||
2101 | SEARCH_COUNT) > 0) { | ||
2102 | disconnected = FALSE; | ||
2103 | } | 2200 | } |
2104 | 2201 | ||
2105 | saved_modes = ahd_save_modes(ahd); | 2202 | saved_modes = ahd_save_modes(ahd); |
@@ -2107,17 +2204,12 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) | |||
2107 | last_phase = ahd_inb(ahd, LASTPHASE); | 2204 | last_phase = ahd_inb(ahd, LASTPHASE); |
2108 | saved_scbptr = ahd_get_scbptr(ahd); | 2205 | saved_scbptr = ahd_get_scbptr(ahd); |
2109 | active_scbptr = saved_scbptr; | 2206 | active_scbptr = saved_scbptr; |
2110 | if (disconnected && ((last_phase != P_BUSFREE) || | 2207 | if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) { |
2111 | (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)) { | ||
2112 | struct scb *bus_scb; | 2208 | struct scb *bus_scb; |
2113 | 2209 | ||
2114 | bus_scb = ahd_lookup_scb(ahd, active_scbptr); | 2210 | bus_scb = ahd_lookup_scb(ahd, active_scbptr); |
2115 | if (bus_scb == pending_scb) | 2211 | if (bus_scb == pending_scb) |
2116 | disconnected = FALSE; | 2212 | disconnected = FALSE; |
2117 | else if (flag != SCB_ABORT | ||
2118 | && ahd_inb(ahd, SAVED_SCSIID) == pending_scb->hscb->scsiid | ||
2119 | && ahd_inb(ahd, SAVED_LUN) == SCB_GET_LUN(pending_scb)) | ||
2120 | disconnected = FALSE; | ||
2121 | } | 2213 | } |
2122 | 2214 | ||
2123 | /* | 2215 | /* |
@@ -2126,41 +2218,26 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) | |||
2126 | * bus or is in the disconnected state. | 2218 | * bus or is in the disconnected state. |
2127 | */ | 2219 | */ |
2128 | saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); | 2220 | saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); |
2129 | if (SCB_GET_TAG(pending_scb) == active_scbptr | 2221 | if (last_phase != P_BUSFREE |
2130 | || (flag == SCB_DEVICE_RESET | 2222 | && SCB_GET_TAG(pending_scb) == active_scbptr) { |
2131 | && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd))) { | ||
2132 | 2223 | ||
2133 | /* | 2224 | /* |
2134 | * We're active on the bus, so assert ATN | 2225 | * We're active on the bus, so assert ATN |
2135 | * and hope that the target responds. | 2226 | * and hope that the target responds. |
2136 | */ | 2227 | */ |
2137 | pending_scb = ahd_lookup_scb(ahd, active_scbptr); | 2228 | pending_scb = ahd_lookup_scb(ahd, active_scbptr); |
2138 | pending_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET; | 2229 | pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; |
2139 | ahd_outb(ahd, MSG_OUT, HOST_MSG); | 2230 | ahd_outb(ahd, MSG_OUT, HOST_MSG); |
2140 | ahd_outb(ahd, SCSISIGO, last_phase|ATNO); | 2231 | ahd_outb(ahd, SCSISIGO, last_phase|ATNO); |
2141 | scmd_printk(KERN_INFO, cmd, "BDR message in message buffer\n"); | 2232 | scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n"); |
2142 | wait = TRUE; | 2233 | wait = TRUE; |
2143 | } else if (last_phase != P_BUSFREE | ||
2144 | && ahd_inb(ahd, SCSIPHASE) == 0) { | ||
2145 | /* | ||
2146 | * SCB is not identified, there | ||
2147 | * is no pending REQ, and the sequencer | ||
2148 | * has not seen a busfree. Looks like | ||
2149 | * a stuck connection waiting to | ||
2150 | * go busfree. Reset the bus. | ||
2151 | */ | ||
2152 | found = ahd_reset_channel(ahd, cmd->device->channel + 'A', | ||
2153 | /*Initiate Reset*/TRUE); | ||
2154 | printf("%s: Issued Channel %c Bus Reset. " | ||
2155 | "%d SCBs aborted\n", ahd_name(ahd), | ||
2156 | cmd->device->channel + 'A', found); | ||
2157 | } else if (disconnected) { | 2234 | } else if (disconnected) { |
2158 | 2235 | ||
2159 | /* | 2236 | /* |
2160 | * Actually re-queue this SCB in an attempt | 2237 | * Actually re-queue this SCB in an attempt |
2161 | * to select the device before it reconnects. | 2238 | * to select the device before it reconnects. |
2162 | */ | 2239 | */ |
2163 | pending_scb->flags |= SCB_RECOVERY_SCB|flag; | 2240 | pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; |
2164 | ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); | 2241 | ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); |
2165 | pending_scb->hscb->cdb_len = 0; | 2242 | pending_scb->hscb->cdb_len = 0; |
2166 | pending_scb->hscb->task_attribute = 0; | 2243 | pending_scb->hscb->task_attribute = 0; |