diff options
author | Hannes Reinecke <hare@suse.de> | 2006-01-30 10:10:31 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2006-01-31 15:39:50 -0500 |
commit | eb221849540b7f4165c58b6c79d98b97ac902fdb (patch) | |
tree | 606f04871288b2b062f52fe2804e9320aa924644 /drivers/scsi/aic7xxx | |
parent | d60256b1b3ceb79cb06a5dd5e259b23bd27d4c61 (diff) |
[SCSI] aic79xx: Fix timer handling
Fix the timer handling in aic79xx to use the SCSI-ML provided handling
instead of implementing our own.
It also fixes a deadlock in the command recovery code.
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aic7xxx')
-rw-r--r-- | drivers/scsi/aic7xxx/Kconfig.aic79xx | 4 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_core.c | 5 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm.c | 26 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm.h | 8 |
4 files changed, 17 insertions, 26 deletions
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx index 69ed77fcb71f..7955ebe8e1e8 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic79xx +++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx | |||
@@ -37,13 +37,13 @@ config AIC79XX_CMDS_PER_DEVICE | |||
37 | config AIC79XX_RESET_DELAY_MS | 37 | config AIC79XX_RESET_DELAY_MS |
38 | int "Initial bus reset delay in milli-seconds" | 38 | int "Initial bus reset delay in milli-seconds" |
39 | depends on SCSI_AIC79XX | 39 | depends on SCSI_AIC79XX |
40 | default "15000" | 40 | default "5000" |
41 | ---help--- | 41 | ---help--- |
42 | The number of milliseconds to delay after an initial bus reset. | 42 | The number of milliseconds to delay after an initial bus reset. |
43 | The bus settle delay following all error recovery actions is | 43 | The bus settle delay following all error recovery actions is |
44 | dictated by the SCSI layer and is not affected by this value. | 44 | dictated by the SCSI layer and is not affected by this value. |
45 | 45 | ||
46 | Default: 15000 (15 seconds) | 46 | Default: 5000 (5 seconds) |
47 | 47 | ||
48 | config AIC79XX_BUILD_FIRMWARE | 48 | config AIC79XX_BUILD_FIRMWARE |
49 | bool "Build Adapter Firmware with Kernel Build" | 49 | bool "Build Adapter Firmware with Kernel Build" |
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 6114b3e72caa..342f77966a5b 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c | |||
@@ -8273,11 +8273,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) | |||
8273 | ahd_setup_data_scb(ahd, scb); | 8273 | ahd_setup_data_scb(ahd, scb); |
8274 | scb->flags |= SCB_SENSE; | 8274 | scb->flags |= SCB_SENSE; |
8275 | ahd_queue_scb(ahd, scb); | 8275 | ahd_queue_scb(ahd, scb); |
8276 | /* | ||
8277 | * Ensure we have enough time to actually | ||
8278 | * retrieve the sense. | ||
8279 | */ | ||
8280 | ahd_scb_timer_reset(scb, 5 * 1000000); | ||
8281 | break; | 8276 | break; |
8282 | } | 8277 | } |
8283 | case SCSI_STATUS_OK: | 8278 | case SCSI_STATUS_OK: |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 815c06312c88..7254ea535a16 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
@@ -1089,7 +1089,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa | |||
1089 | return (ENOMEM); | 1089 | return (ENOMEM); |
1090 | 1090 | ||
1091 | *((struct ahd_softc **)host->hostdata) = ahd; | 1091 | *((struct ahd_softc **)host->hostdata) = ahd; |
1092 | ahd_lock(ahd, &s); | ||
1093 | ahd->platform_data->host = host; | 1092 | ahd->platform_data->host = host; |
1094 | host->can_queue = AHD_MAX_QUEUE; | 1093 | host->can_queue = AHD_MAX_QUEUE; |
1095 | host->cmd_per_lun = 2; | 1094 | host->cmd_per_lun = 2; |
@@ -1100,7 +1099,9 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa | |||
1100 | host->max_lun = AHD_NUM_LUNS; | 1099 | host->max_lun = AHD_NUM_LUNS; |
1101 | host->max_channel = 0; | 1100 | host->max_channel = 0; |
1102 | host->sg_tablesize = AHD_NSEG; | 1101 | host->sg_tablesize = AHD_NSEG; |
1102 | ahd_lock(ahd, &s); | ||
1103 | ahd_set_unit(ahd, ahd_linux_unit++); | 1103 | ahd_set_unit(ahd, ahd_linux_unit++); |
1104 | ahd_unlock(ahd, &s); | ||
1104 | sprintf(buf, "scsi%d", host->host_no); | 1105 | sprintf(buf, "scsi%d", host->host_no); |
1105 | new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); | 1106 | new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); |
1106 | if (new_name != NULL) { | 1107 | if (new_name != NULL) { |
@@ -1110,7 +1111,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa | |||
1110 | host->unique_id = ahd->unit; | 1111 | host->unique_id = ahd->unit; |
1111 | ahd_linux_initialize_scsi_bus(ahd); | 1112 | ahd_linux_initialize_scsi_bus(ahd); |
1112 | ahd_intr_enable(ahd, TRUE); | 1113 | ahd_intr_enable(ahd, TRUE); |
1113 | ahd_unlock(ahd, &s); | ||
1114 | 1114 | ||
1115 | host->transportt = ahd_linux_transport_template; | 1115 | host->transportt = ahd_linux_transport_template; |
1116 | 1116 | ||
@@ -1144,6 +1144,7 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd) | |||
1144 | { | 1144 | { |
1145 | u_int target_id; | 1145 | u_int target_id; |
1146 | u_int numtarg; | 1146 | u_int numtarg; |
1147 | unsigned long s; | ||
1147 | 1148 | ||
1148 | target_id = 0; | 1149 | target_id = 0; |
1149 | numtarg = 0; | 1150 | numtarg = 0; |
@@ -1156,6 +1157,8 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd) | |||
1156 | else | 1157 | else |
1157 | numtarg = (ahd->features & AHD_WIDE) ? 16 : 8; | 1158 | numtarg = (ahd->features & AHD_WIDE) ? 16 : 8; |
1158 | 1159 | ||
1160 | ahd_lock(ahd, &s); | ||
1161 | |||
1159 | /* | 1162 | /* |
1160 | * Force negotiation to async for all targets that | 1163 | * Force negotiation to async for all targets that |
1161 | * will not see an initial bus reset. | 1164 | * will not see an initial bus reset. |
@@ -1172,16 +1175,12 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd) | |||
1172 | ahd_update_neg_request(ahd, &devinfo, tstate, | 1175 | ahd_update_neg_request(ahd, &devinfo, tstate, |
1173 | tinfo, AHD_NEG_ALWAYS); | 1176 | tinfo, AHD_NEG_ALWAYS); |
1174 | } | 1177 | } |
1178 | ahd_unlock(ahd, &s); | ||
1175 | /* Give the bus some time to recover */ | 1179 | /* Give the bus some time to recover */ |
1176 | if ((ahd->flags & AHD_RESET_BUS_A) != 0) { | 1180 | if ((ahd->flags & AHD_RESET_BUS_A) != 0) { |
1177 | ahd_freeze_simq(ahd); | 1181 | ahd_freeze_simq(ahd); |
1178 | init_timer(&ahd->platform_data->reset_timer); | 1182 | msleep(AIC79XX_RESET_DELAY); |
1179 | ahd->platform_data->reset_timer.data = (u_long)ahd; | 1183 | ahd_release_simq(ahd); |
1180 | ahd->platform_data->reset_timer.expires = | ||
1181 | jiffies + (AIC79XX_RESET_DELAY * HZ)/1000; | ||
1182 | ahd->platform_data->reset_timer.function = | ||
1183 | (ahd_linux_callback_t *)ahd_release_simq; | ||
1184 | add_timer(&ahd->platform_data->reset_timer); | ||
1185 | } | 1184 | } |
1186 | } | 1185 | } |
1187 | 1186 | ||
@@ -2050,6 +2049,9 @@ ahd_linux_sem_timeout(u_long arg) | |||
2050 | void | 2049 | void |
2051 | ahd_freeze_simq(struct ahd_softc *ahd) | 2050 | ahd_freeze_simq(struct ahd_softc *ahd) |
2052 | { | 2051 | { |
2052 | unsigned long s; | ||
2053 | |||
2054 | ahd_lock(ahd, &s); | ||
2053 | ahd->platform_data->qfrozen++; | 2055 | ahd->platform_data->qfrozen++; |
2054 | if (ahd->platform_data->qfrozen == 1) { | 2056 | if (ahd->platform_data->qfrozen == 1) { |
2055 | scsi_block_requests(ahd->platform_data->host); | 2057 | scsi_block_requests(ahd->platform_data->host); |
@@ -2057,6 +2059,7 @@ ahd_freeze_simq(struct ahd_softc *ahd) | |||
2057 | CAM_LUN_WILDCARD, SCB_LIST_NULL, | 2059 | CAM_LUN_WILDCARD, SCB_LIST_NULL, |
2058 | ROLE_INITIATOR, CAM_REQUEUE_REQ); | 2060 | ROLE_INITIATOR, CAM_REQUEUE_REQ); |
2059 | } | 2061 | } |
2062 | ahd_unlock(ahd, &s); | ||
2060 | } | 2063 | } |
2061 | 2064 | ||
2062 | void | 2065 | void |
@@ -2361,8 +2364,9 @@ done: | |||
2361 | ahd_name(ahd), dev->active); | 2364 | ahd_name(ahd), dev->active); |
2362 | retval = FAILED; | 2365 | retval = FAILED; |
2363 | } | 2366 | } |
2364 | } | 2367 | } else |
2365 | ahd_unlock(ahd, &flags); | 2368 | ahd_unlock(ahd, &flags); |
2369 | |||
2366 | return (retval); | 2370 | return (retval); |
2367 | } | 2371 | } |
2368 | 2372 | ||
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index 854fc57c304c..9cb101345107 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h | |||
@@ -228,7 +228,6 @@ typedef struct timer_list ahd_timer_t; | |||
228 | typedef void ahd_linux_callback_t (u_long); | 228 | typedef void ahd_linux_callback_t (u_long); |
229 | static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec, | 229 | static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec, |
230 | ahd_callback_t *func, void *arg); | 230 | ahd_callback_t *func, void *arg); |
231 | static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec); | ||
232 | 231 | ||
233 | static __inline void | 232 | static __inline void |
234 | ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg) | 233 | ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg) |
@@ -243,12 +242,6 @@ ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg) | |||
243 | add_timer(timer); | 242 | add_timer(timer); |
244 | } | 243 | } |
245 | 244 | ||
246 | static __inline void | ||
247 | ahd_scb_timer_reset(struct scb *scb, u_int usec) | ||
248 | { | ||
249 | mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000); | ||
250 | } | ||
251 | |||
252 | /***************************** SMP support ************************************/ | 245 | /***************************** SMP support ************************************/ |
253 | #include <linux/spinlock.h> | 246 | #include <linux/spinlock.h> |
254 | 247 | ||
@@ -389,7 +382,6 @@ struct ahd_platform_data { | |||
389 | 382 | ||
390 | spinlock_t spin_lock; | 383 | spinlock_t spin_lock; |
391 | u_int qfrozen; | 384 | u_int qfrozen; |
392 | struct timer_list reset_timer; | ||
393 | struct semaphore eh_sem; | 385 | struct semaphore eh_sem; |
394 | struct Scsi_Host *host; /* pointer to scsi host */ | 386 | struct Scsi_Host *host; /* pointer to scsi host */ |
395 | #define AHD_LINUX_NOIRQ ((uint32_t)~0) | 387 | #define AHD_LINUX_NOIRQ ((uint32_t)~0) |