diff options
| -rw-r--r-- | drivers/scsi/aic7xxx/aic79xx.h | 2 | ||||
| -rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_core.c | 114 | ||||
| -rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm.c | 4 |
3 files changed, 58 insertions, 62 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 1d11f7e77564..933e5101edf6 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 |
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 326a62226235..880a10def1aa 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); |
| @@ -1534,6 +1533,18 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) | |||
| 1534 | lqistat1 = ahd_inb(ahd, LQISTAT1); | 1533 | lqistat1 = ahd_inb(ahd, LQISTAT1); |
| 1535 | lqostat0 = ahd_inb(ahd, LQOSTAT0); | 1534 | lqostat0 = ahd_inb(ahd, LQOSTAT0); |
| 1536 | busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME; | 1535 | busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME; |
| 1536 | |||
| 1537 | /* | ||
| 1538 | * Ignore external resets after a bus reset. | ||
| 1539 | */ | ||
| 1540 | if (((status & SCSIRSTI) != 0) && (ahd->flags & AHD_BUS_RESET_ACTIVE)) | ||
| 1541 | return; | ||
| 1542 | |||
| 1543 | /* | ||
| 1544 | * Clear bus reset flag | ||
| 1545 | */ | ||
| 1546 | ahd->flags &= ~AHD_BUS_RESET_ACTIVE; | ||
| 1547 | |||
| 1537 | if ((status0 & (SELDI|SELDO)) != 0) { | 1548 | if ((status0 & (SELDI|SELDO)) != 0) { |
| 1538 | u_int simode0; | 1549 | u_int simode0; |
| 1539 | 1550 | ||
| @@ -7847,6 +7858,17 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) | |||
| 7847 | int found; | 7858 | int found; |
| 7848 | u_int fifo; | 7859 | u_int fifo; |
| 7849 | u_int next_fifo; | 7860 | u_int next_fifo; |
| 7861 | uint8_t scsiseq; | ||
| 7862 | |||
| 7863 | /* | ||
| 7864 | * Check if the last bus reset is cleared | ||
| 7865 | */ | ||
| 7866 | if (ahd->flags & AHD_BUS_RESET_ACTIVE) { | ||
| 7867 | printf("%s: bus reset still active\n", | ||
| 7868 | ahd_name(ahd)); | ||
| 7869 | return 0; | ||
| 7870 | } | ||
| 7871 | ahd->flags |= AHD_BUS_RESET_ACTIVE; | ||
| 7850 | 7872 | ||
| 7851 | ahd->pending_device = NULL; | 7873 | ahd->pending_device = NULL; |
| 7852 | 7874 | ||
| @@ -7860,6 +7882,12 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) | |||
| 7860 | /* Make sure the sequencer is in a safe location. */ | 7882 | /* Make sure the sequencer is in a safe location. */ |
| 7861 | ahd_clear_critical_section(ahd); | 7883 | ahd_clear_critical_section(ahd); |
| 7862 | 7884 | ||
| 7885 | /* | ||
| 7886 | * Run our command complete fifos to ensure that we perform | ||
| 7887 | * completion processing on any commands that 'completed' | ||
| 7888 | * before the reset occurred. | ||
| 7889 | */ | ||
| 7890 | ahd_run_qoutfifo(ahd); | ||
| 7863 | #ifdef AHD_TARGET_MODE | 7891 | #ifdef AHD_TARGET_MODE |
| 7864 | if ((ahd->flags & AHD_TARGETROLE) != 0) { | 7892 | if ((ahd->flags & AHD_TARGETROLE) != 0) { |
| 7865 | ahd_run_tqinfifo(ahd, /*paused*/TRUE); | 7893 | ahd_run_tqinfifo(ahd, /*paused*/TRUE); |
| @@ -7924,30 +7952,14 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) | |||
| 7924 | ahd_clear_fifo(ahd, 1); | 7952 | ahd_clear_fifo(ahd, 1); |
| 7925 | 7953 | ||
| 7926 | /* | 7954 | /* |
| 7927 | * Revert to async/narrow transfers until we renegotiate. | 7955 | * Reenable selections |
| 7928 | */ | 7956 | */ |
| 7929 | max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7; | 7957 | ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST); |
| 7930 | for (target = 0; target <= max_scsiid; target++) { | 7958 | scsiseq = ahd_inb(ahd, SCSISEQ_TEMPLATE); |
| 7931 | 7959 | 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 | 7960 | ||
| 7948 | #ifdef AHD_TARGET_MODE | ||
| 7949 | max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7; | 7961 | max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7; |
| 7950 | 7962 | #ifdef AHD_TARGET_MODE | |
| 7951 | /* | 7963 | /* |
| 7952 | * Send an immediate notify ccb to all target more peripheral | 7964 | * Send an immediate notify ccb to all target more peripheral |
| 7953 | * drivers affected by this action. | 7965 | * drivers affected by this action. |
| @@ -7975,51 +7987,31 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) | |||
| 7975 | /* Notify the XPT that a bus reset occurred */ | 7987 | /* Notify the XPT that a bus reset occurred */ |
| 7976 | ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD, | 7988 | ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD, |
| 7977 | CAM_LUN_WILDCARD, AC_BUS_RESET, NULL); | 7989 | CAM_LUN_WILDCARD, AC_BUS_RESET, NULL); |
| 7978 | ahd_restart(ahd); | 7990 | |
| 7979 | /* | 7991 | /* |
| 7980 | * Freeze the SIMQ until our poller can determine that | 7992 | * 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 | */ | 7993 | */ |
| 7985 | if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) { | 7994 | 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 | 7995 | ||
| 7996 | if (ahd->enabled_targets[target] == NULL) | ||
| 7997 | continue; | ||
| 7998 | for (initiator = 0; initiator <= max_scsiid; initiator++) { | ||
| 7999 | struct ahd_devinfo devinfo; | ||
| 7993 | 8000 | ||
| 7994 | #define AHD_RESET_POLL_US 1000 | 8001 | ahd_compile_devinfo(&devinfo, target, initiator, |
| 7995 | static void | 8002 | CAM_LUN_WILDCARD, |
| 7996 | ahd_reset_poll(void *arg) | 8003 | 'A', ROLE_UNKNOWN); |
| 7997 | { | 8004 | ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, |
| 7998 | struct ahd_softc *ahd = arg; | 8005 | AHD_TRANS_CUR, /*paused*/TRUE); |
| 7999 | u_int scsiseq1; | 8006 | ahd_set_syncrate(ahd, &devinfo, /*period*/0, |
| 8000 | u_long s; | 8007 | /*offset*/0, /*ppr_options*/0, |
| 8001 | 8008 | AHD_TRANS_CUR, /*paused*/TRUE); | |
| 8002 | ahd_lock(ahd, &s); | 8009 | } |
| 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 | } | 8010 | } |
| 8014 | 8011 | ||
| 8015 | /* Reset is now low. Complete chip reinitialization. */ | 8012 | ahd_restart(ahd); |
| 8016 | ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST); | 8013 | |
| 8017 | scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE); | 8014 | 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 | } | 8015 | } |
| 8024 | 8016 | ||
| 8025 | /**************************** Statistics Processing ***************************/ | 8017 | /**************************** 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. " |
