diff options
Diffstat (limited to 'drivers/scsi/aic7xxx')
-rw-r--r-- | drivers/scsi/aic7xxx/Kconfig.aic7xxx | 2 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx.h | 4 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_core.c | 166 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm.c | 4 |
4 files changed, 69 insertions, 107 deletions
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx index 6c2c395554ff..5517da5855f0 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx +++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx | |||
@@ -86,7 +86,7 @@ config AIC7XXX_DEBUG_MASK | |||
86 | default "0" | 86 | default "0" |
87 | help | 87 | help |
88 | Bit mask of debug options that is only valid if the | 88 | Bit mask of debug options that is only valid if the |
89 | CONFIG_AIC7XXX_DEBUG_ENBLE option is enabled. The bits in this mask | 89 | CONFIG_AIC7XXX_DEBUG_ENABLE option is enabled. The bits in this mask |
90 | are defined in the drivers/scsi/aic7xxx/aic7xxx.h - search for the | 90 | are defined in the drivers/scsi/aic7xxx/aic7xxx.h - search for the |
91 | variable ahc_debug in that file to find them. | 91 | variable ahc_debug in that file to find them. |
92 | 92 | ||
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 1d11f7e77564..bb5166da4358 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h | |||
@@ -372,7 +372,7 @@ typedef enum { | |||
372 | AHD_CURRENT_SENSING = 0x40000, | 372 | AHD_CURRENT_SENSING = 0x40000, |
373 | AHD_SCB_CONFIG_USED = 0x80000,/* No SEEPROM but SCB had info. */ | 373 | AHD_SCB_CONFIG_USED = 0x80000,/* No SEEPROM but SCB had info. */ |
374 | AHD_HP_BOARD = 0x100000, | 374 | AHD_HP_BOARD = 0x100000, |
375 | AHD_RESET_POLL_ACTIVE = 0x200000, | 375 | AHD_BUS_RESET_ACTIVE = 0x200000, |
376 | AHD_UPDATE_PEND_CMDS = 0x400000, | 376 | AHD_UPDATE_PEND_CMDS = 0x400000, |
377 | AHD_RUNNING_QOUTFIFO = 0x800000, | 377 | AHD_RUNNING_QOUTFIFO = 0x800000, |
378 | AHD_HAD_FIRST_SEL = 0x1000000 | 378 | AHD_HAD_FIRST_SEL = 0x1000000 |
@@ -589,7 +589,7 @@ typedef enum { | |||
589 | SCB_PACKETIZED = 0x00800, | 589 | SCB_PACKETIZED = 0x00800, |
590 | SCB_EXPECT_PPR_BUSFREE = 0x01000, | 590 | SCB_EXPECT_PPR_BUSFREE = 0x01000, |
591 | SCB_PKT_SENSE = 0x02000, | 591 | SCB_PKT_SENSE = 0x02000, |
592 | SCB_CMDPHASE_ABORT = 0x04000, | 592 | SCB_EXTERNAL_RESET = 0x04000,/* Device was reset externally */ |
593 | SCB_ON_COL_LIST = 0x08000, | 593 | SCB_ON_COL_LIST = 0x08000, |
594 | SCB_SILENT = 0x10000 /* | 594 | SCB_SILENT = 0x10000 /* |
595 | * Be quiet about transmission type | 595 | * Be quiet about transmission type |
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 326a62226235..08771f6f6859 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c | |||
@@ -207,7 +207,6 @@ static void ahd_add_scb_to_free_list(struct ahd_softc *ahd, | |||
207 | static u_int ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid, | 207 | static u_int ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid, |
208 | u_int prev, u_int next, u_int tid); | 208 | u_int prev, u_int next, u_int tid); |
209 | static void ahd_reset_current_bus(struct ahd_softc *ahd); | 209 | static void ahd_reset_current_bus(struct ahd_softc *ahd); |
210 | static ahd_callback_t ahd_reset_poll; | ||
211 | static ahd_callback_t ahd_stat_timer; | 210 | static ahd_callback_t ahd_stat_timer; |
212 | #ifdef AHD_DUMP_SEQ | 211 | #ifdef AHD_DUMP_SEQ |
213 | static void ahd_dumpseq(struct ahd_softc *ahd); | 212 | static void ahd_dumpseq(struct ahd_softc *ahd); |
@@ -1054,12 +1053,10 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) | |||
1054 | * If a target takes us into the command phase | 1053 | * If a target takes us into the command phase |
1055 | * assume that it has been externally reset and | 1054 | * assume that it has been externally reset and |
1056 | * has thus lost our previous packetized negotiation | 1055 | * has thus lost our previous packetized negotiation |
1057 | * agreement. Since we have not sent an identify | 1056 | * agreement. |
1058 | * message and may not have fully qualified the | 1057 | * Revert to async/narrow transfers until we |
1059 | * connection, we change our command to TUR, assert | 1058 | * can renegotiate with the device and notify |
1060 | * ATN and ABORT the task when we go to message in | 1059 | * the OSM about the reset. |
1061 | * phase. The OSM will see the REQUEUE_REQUEST | ||
1062 | * status and retry the command. | ||
1063 | */ | 1060 | */ |
1064 | scbid = ahd_get_scbptr(ahd); | 1061 | scbid = ahd_get_scbptr(ahd); |
1065 | scb = ahd_lookup_scb(ahd, scbid); | 1062 | scb = ahd_lookup_scb(ahd, scbid); |
@@ -1086,31 +1083,15 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) | |||
1086 | ahd_set_syncrate(ahd, &devinfo, /*period*/0, | 1083 | ahd_set_syncrate(ahd, &devinfo, /*period*/0, |
1087 | /*offset*/0, /*ppr_options*/0, | 1084 | /*offset*/0, /*ppr_options*/0, |
1088 | AHD_TRANS_ACTIVE, /*paused*/TRUE); | 1085 | AHD_TRANS_ACTIVE, /*paused*/TRUE); |
1089 | ahd_outb(ahd, SCB_CDB_STORE, 0); | 1086 | scb->flags |= SCB_EXTERNAL_RESET; |
1090 | ahd_outb(ahd, SCB_CDB_STORE+1, 0); | ||
1091 | ahd_outb(ahd, SCB_CDB_STORE+2, 0); | ||
1092 | ahd_outb(ahd, SCB_CDB_STORE+3, 0); | ||
1093 | ahd_outb(ahd, SCB_CDB_STORE+4, 0); | ||
1094 | ahd_outb(ahd, SCB_CDB_STORE+5, 0); | ||
1095 | ahd_outb(ahd, SCB_CDB_LEN, 6); | ||
1096 | scb->hscb->control &= ~(TAG_ENB|SCB_TAG_TYPE); | ||
1097 | scb->hscb->control |= MK_MESSAGE; | ||
1098 | ahd_outb(ahd, SCB_CONTROL, scb->hscb->control); | ||
1099 | ahd_outb(ahd, MSG_OUT, HOST_MSG); | ||
1100 | ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid); | ||
1101 | /* | ||
1102 | * The lun is 0, regardless of the SCB's lun | ||
1103 | * as we have not sent an identify message. | ||
1104 | */ | ||
1105 | ahd_outb(ahd, SAVED_LUN, 0); | ||
1106 | ahd_outb(ahd, SEQ_FLAGS, 0); | ||
1107 | ahd_assert_atn(ahd); | ||
1108 | scb->flags &= ~SCB_PACKETIZED; | ||
1109 | scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT; | ||
1110 | ahd_freeze_devq(ahd, scb); | 1087 | ahd_freeze_devq(ahd, scb); |
1111 | ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); | 1088 | ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); |
1112 | ahd_freeze_scb(scb); | 1089 | ahd_freeze_scb(scb); |
1113 | 1090 | ||
1091 | /* Notify XPT */ | ||
1092 | ahd_send_async(ahd, devinfo.channel, devinfo.target, | ||
1093 | CAM_LUN_WILDCARD, AC_SENT_BDR, NULL); | ||
1094 | |||
1114 | /* | 1095 | /* |
1115 | * Allow the sequencer to continue with | 1096 | * Allow the sequencer to continue with |
1116 | * non-pack processing. | 1097 | * non-pack processing. |
@@ -1534,6 +1515,18 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) | |||
1534 | lqistat1 = ahd_inb(ahd, LQISTAT1); | 1515 | lqistat1 = ahd_inb(ahd, LQISTAT1); |
1535 | lqostat0 = ahd_inb(ahd, LQOSTAT0); | 1516 | lqostat0 = ahd_inb(ahd, LQOSTAT0); |
1536 | busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME; | 1517 | busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME; |
1518 | |||
1519 | /* | ||
1520 | * Ignore external resets after a bus reset. | ||
1521 | */ | ||
1522 | if (((status & SCSIRSTI) != 0) && (ahd->flags & AHD_BUS_RESET_ACTIVE)) | ||
1523 | return; | ||
1524 | |||
1525 | /* | ||
1526 | * Clear bus reset flag | ||
1527 | */ | ||
1528 | ahd->flags &= ~AHD_BUS_RESET_ACTIVE; | ||
1529 | |||
1537 | if ((status0 & (SELDI|SELDO)) != 0) { | 1530 | if ((status0 & (SELDI|SELDO)) != 0) { |
1538 | u_int simode0; | 1531 | u_int simode0; |
1539 | 1532 | ||
@@ -2207,22 +2200,6 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) | |||
2207 | if (sent_msg == MSG_ABORT_TAG) | 2200 | if (sent_msg == MSG_ABORT_TAG) |
2208 | tag = SCB_GET_TAG(scb); | 2201 | tag = SCB_GET_TAG(scb); |
2209 | 2202 | ||
2210 | if ((scb->flags & SCB_CMDPHASE_ABORT) != 0) { | ||
2211 | /* | ||
2212 | * This abort is in response to an | ||
2213 | * unexpected switch to command phase | ||
2214 | * for a packetized connection. Since | ||
2215 | * the identify message was never sent, | ||
2216 | * "saved lun" is 0. We really want to | ||
2217 | * abort only the SCB that encountered | ||
2218 | * this error, which could have a different | ||
2219 | * lun. The SCB will be retried so the OS | ||
2220 | * will see the UA after renegotiating to | ||
2221 | * packetized. | ||
2222 | */ | ||
2223 | tag = SCB_GET_TAG(scb); | ||
2224 | saved_lun = scb->hscb->lun; | ||
2225 | } | ||
2226 | found = ahd_abort_scbs(ahd, target, 'A', saved_lun, | 2203 | found = ahd_abort_scbs(ahd, target, 'A', saved_lun, |
2227 | tag, ROLE_INITIATOR, | 2204 | tag, ROLE_INITIATOR, |
2228 | CAM_REQ_ABORTED); | 2205 | CAM_REQ_ABORTED); |
@@ -7847,6 +7824,17 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) | |||
7847 | int found; | 7824 | int found; |
7848 | u_int fifo; | 7825 | u_int fifo; |
7849 | u_int next_fifo; | 7826 | u_int next_fifo; |
7827 | uint8_t scsiseq; | ||
7828 | |||
7829 | /* | ||
7830 | * Check if the last bus reset is cleared | ||
7831 | */ | ||
7832 | if (ahd->flags & AHD_BUS_RESET_ACTIVE) { | ||
7833 | printf("%s: bus reset still active\n", | ||
7834 | ahd_name(ahd)); | ||
7835 | return 0; | ||
7836 | } | ||
7837 | ahd->flags |= AHD_BUS_RESET_ACTIVE; | ||
7850 | 7838 | ||
7851 | ahd->pending_device = NULL; | 7839 | ahd->pending_device = NULL; |
7852 | 7840 | ||
@@ -7860,6 +7848,12 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) | |||
7860 | /* Make sure the sequencer is in a safe location. */ | 7848 | /* Make sure the sequencer is in a safe location. */ |
7861 | ahd_clear_critical_section(ahd); | 7849 | ahd_clear_critical_section(ahd); |
7862 | 7850 | ||
7851 | /* | ||
7852 | * Run our command complete fifos to ensure that we perform | ||
7853 | * completion processing on any commands that 'completed' | ||
7854 | * before the reset occurred. | ||
7855 | */ | ||
7856 | ahd_run_qoutfifo(ahd); | ||
7863 | #ifdef AHD_TARGET_MODE | 7857 | #ifdef AHD_TARGET_MODE |
7864 | if ((ahd->flags & AHD_TARGETROLE) != 0) { | 7858 | if ((ahd->flags & AHD_TARGETROLE) != 0) { |
7865 | ahd_run_tqinfifo(ahd, /*paused*/TRUE); | 7859 | ahd_run_tqinfifo(ahd, /*paused*/TRUE); |
@@ -7924,30 +7918,14 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) | |||
7924 | ahd_clear_fifo(ahd, 1); | 7918 | ahd_clear_fifo(ahd, 1); |
7925 | 7919 | ||
7926 | /* | 7920 | /* |
7927 | * Revert to async/narrow transfers until we renegotiate. | 7921 | * Reenable selections |
7928 | */ | 7922 | */ |
7929 | max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7; | 7923 | ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST); |
7930 | for (target = 0; target <= max_scsiid; target++) { | 7924 | scsiseq = ahd_inb(ahd, SCSISEQ_TEMPLATE); |
7931 | 7925 | ahd_outb(ahd, SCSISEQ1, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP)); | |
7932 | if (ahd->enabled_targets[target] == NULL) | ||
7933 | continue; | ||
7934 | for (initiator = 0; initiator <= max_scsiid; initiator++) { | ||
7935 | struct ahd_devinfo devinfo; | ||
7936 | |||
7937 | ahd_compile_devinfo(&devinfo, target, initiator, | ||
7938 | CAM_LUN_WILDCARD, | ||
7939 | 'A', ROLE_UNKNOWN); | ||
7940 | ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, | ||
7941 | AHD_TRANS_CUR, /*paused*/TRUE); | ||
7942 | ahd_set_syncrate(ahd, &devinfo, /*period*/0, | ||
7943 | /*offset*/0, /*ppr_options*/0, | ||
7944 | AHD_TRANS_CUR, /*paused*/TRUE); | ||
7945 | } | ||
7946 | } | ||
7947 | 7926 | ||
7948 | #ifdef AHD_TARGET_MODE | ||
7949 | max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7; | 7927 | max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7; |
7950 | 7928 | #ifdef AHD_TARGET_MODE | |
7951 | /* | 7929 | /* |
7952 | * Send an immediate notify ccb to all target more peripheral | 7930 | * Send an immediate notify ccb to all target more peripheral |
7953 | * drivers affected by this action. | 7931 | * drivers affected by this action. |
@@ -7975,51 +7953,31 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) | |||
7975 | /* Notify the XPT that a bus reset occurred */ | 7953 | /* Notify the XPT that a bus reset occurred */ |
7976 | ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD, | 7954 | ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD, |
7977 | CAM_LUN_WILDCARD, AC_BUS_RESET, NULL); | 7955 | CAM_LUN_WILDCARD, AC_BUS_RESET, NULL); |
7978 | ahd_restart(ahd); | 7956 | |
7979 | /* | 7957 | /* |
7980 | * Freeze the SIMQ until our poller can determine that | 7958 | * Revert to async/narrow transfers until we renegotiate. |
7981 | * the bus reset has really gone away. We set the initial | ||
7982 | * timer to 0 to have the check performed as soon as possible | ||
7983 | * from the timer context. | ||
7984 | */ | 7959 | */ |
7985 | if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) { | 7960 | for (target = 0; target <= max_scsiid; target++) { |
7986 | ahd->flags |= AHD_RESET_POLL_ACTIVE; | ||
7987 | ahd_freeze_simq(ahd); | ||
7988 | ahd_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd); | ||
7989 | } | ||
7990 | return (found); | ||
7991 | } | ||
7992 | 7961 | ||
7962 | if (ahd->enabled_targets[target] == NULL) | ||
7963 | continue; | ||
7964 | for (initiator = 0; initiator <= max_scsiid; initiator++) { | ||
7965 | struct ahd_devinfo devinfo; | ||
7993 | 7966 | ||
7994 | #define AHD_RESET_POLL_US 1000 | 7967 | ahd_compile_devinfo(&devinfo, target, initiator, |
7995 | static void | 7968 | CAM_LUN_WILDCARD, |
7996 | ahd_reset_poll(void *arg) | 7969 | 'A', ROLE_UNKNOWN); |
7997 | { | 7970 | ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, |
7998 | struct ahd_softc *ahd = arg; | 7971 | AHD_TRANS_CUR, /*paused*/TRUE); |
7999 | u_int scsiseq1; | 7972 | ahd_set_syncrate(ahd, &devinfo, /*period*/0, |
8000 | u_long s; | 7973 | /*offset*/0, /*ppr_options*/0, |
8001 | 7974 | AHD_TRANS_CUR, /*paused*/TRUE); | |
8002 | ahd_lock(ahd, &s); | 7975 | } |
8003 | ahd_pause(ahd); | ||
8004 | ahd_update_modes(ahd); | ||
8005 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | ||
8006 | ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); | ||
8007 | if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) { | ||
8008 | ahd_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US, | ||
8009 | ahd_reset_poll, ahd); | ||
8010 | ahd_unpause(ahd); | ||
8011 | ahd_unlock(ahd, &s); | ||
8012 | return; | ||
8013 | } | 7976 | } |
8014 | 7977 | ||
8015 | /* Reset is now low. Complete chip reinitialization. */ | 7978 | ahd_restart(ahd); |
8016 | ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST); | 7979 | |
8017 | scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE); | 7980 | return (found); |
8018 | ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP)); | ||
8019 | ahd_unpause(ahd); | ||
8020 | ahd->flags &= ~AHD_RESET_POLL_ACTIVE; | ||
8021 | ahd_unlock(ahd, &s); | ||
8022 | ahd_release_simq(ahd); | ||
8023 | } | 7981 | } |
8024 | 7982 | ||
8025 | /**************************** Statistics Processing ***************************/ | 7983 | /**************************** Statistics Processing ***************************/ |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index bcced0a417e6..66e4a47bb9ee 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
@@ -782,6 +782,7 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd) | |||
782 | { | 782 | { |
783 | struct ahd_softc *ahd; | 783 | struct ahd_softc *ahd; |
784 | int found; | 784 | int found; |
785 | unsigned long flags; | ||
785 | 786 | ||
786 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; | 787 | ahd = *(struct ahd_softc **)cmd->device->host->hostdata; |
787 | #ifdef AHD_DEBUG | 788 | #ifdef AHD_DEBUG |
@@ -789,8 +790,11 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd) | |||
789 | printf("%s: Bus reset called for cmd %p\n", | 790 | printf("%s: Bus reset called for cmd %p\n", |
790 | ahd_name(ahd), cmd); | 791 | ahd_name(ahd), cmd); |
791 | #endif | 792 | #endif |
793 | ahd_lock(ahd, &flags); | ||
794 | |||
792 | found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A', | 795 | found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A', |
793 | /*initiate reset*/TRUE); | 796 | /*initiate reset*/TRUE); |
797 | ahd_unlock(ahd, &flags); | ||
794 | 798 | ||
795 | if (bootverbose) | 799 | if (bootverbose) |
796 | printf("%s: SCSI bus reset delivered. " | 800 | printf("%s: SCSI bus reset delivered. " |