aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic7xxx
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2006-01-30 10:10:31 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2006-01-31 15:39:50 -0500
commiteb221849540b7f4165c58b6c79d98b97ac902fdb (patch)
tree606f04871288b2b062f52fe2804e9320aa924644 /drivers/scsi/aic7xxx
parentd60256b1b3ceb79cb06a5dd5e259b23bd27d4c61 (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.aic79xx4
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c5
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c26
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h8
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
37config AIC79XX_RESET_DELAY_MS 37config 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
48config AIC79XX_BUILD_FIRMWARE 48config 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)
2050void 2049void
2051ahd_freeze_simq(struct ahd_softc *ahd) 2050ahd_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
2062void 2065void
@@ -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;
228typedef void ahd_linux_callback_t (u_long); 228typedef void ahd_linux_callback_t (u_long);
229static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec, 229static __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);
231static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);
232 231
233static __inline void 232static __inline void
234ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg) 233ahd_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
246static __inline void
247ahd_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)