aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic7xxx/aic79xx_osm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx_osm.c')
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 2567e29960bd..7254ea535a16 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -314,6 +314,21 @@ static uint32_t aic79xx_seltime;
314 */ 314 */
315uint32_t aic79xx_periodic_otag; 315uint32_t aic79xx_periodic_otag;
316 316
317/* Some storage boxes are using an LSI chip which has a bug making it
318 * impossible to use aic79xx Rev B chip in 320 speeds. The following
319 * storage boxes have been reported to be buggy:
320 * EonStor 3U 16-Bay: U16U-G3A3
321 * EonStor 2U 12-Bay: U12U-G3A3
322 * SentinelRAID: 2500F R5 / R6
323 * SentinelRAID: 2500F R1
324 * SentinelRAID: 2500F/1500F
325 * SentinelRAID: 150F
326 *
327 * To get around this LSI bug, you can set your board to 160 mode
328 * or you can enable the SLOWCRC bit.
329 */
330uint32_t aic79xx_slowcrc;
331
317/* 332/*
318 * Module information and settable options. 333 * Module information and settable options.
319 */ 334 */
@@ -343,6 +358,7 @@ MODULE_PARM_DESC(aic79xx,
343" amplitude:<int> Set the signal amplitude (0-7).\n" 358" amplitude:<int> Set the signal amplitude (0-7).\n"
344" seltime:<int> Selection Timeout:\n" 359" seltime:<int> Selection Timeout:\n"
345" (0/256ms,1/128ms,2/64ms,3/32ms)\n" 360" (0/256ms,1/128ms,2/64ms,3/32ms)\n"
361" slowcrc Turn on the SLOWCRC bit (Rev B only)\n"
346"\n" 362"\n"
347" Sample /etc/modprobe.conf line:\n" 363" Sample /etc/modprobe.conf line:\n"
348" Enable verbose logging\n" 364" Enable verbose logging\n"
@@ -1003,6 +1019,7 @@ aic79xx_setup(char *s)
1003 { "slewrate", NULL }, 1019 { "slewrate", NULL },
1004 { "precomp", NULL }, 1020 { "precomp", NULL },
1005 { "amplitude", NULL }, 1021 { "amplitude", NULL },
1022 { "slowcrc", &aic79xx_slowcrc },
1006 }; 1023 };
1007 1024
1008 end = strchr(s, '\0'); 1025 end = strchr(s, '\0');
@@ -1072,7 +1089,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
1072 return (ENOMEM); 1089 return (ENOMEM);
1073 1090
1074 *((struct ahd_softc **)host->hostdata) = ahd; 1091 *((struct ahd_softc **)host->hostdata) = ahd;
1075 ahd_lock(ahd, &s);
1076 ahd->platform_data->host = host; 1092 ahd->platform_data->host = host;
1077 host->can_queue = AHD_MAX_QUEUE; 1093 host->can_queue = AHD_MAX_QUEUE;
1078 host->cmd_per_lun = 2; 1094 host->cmd_per_lun = 2;
@@ -1083,7 +1099,9 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
1083 host->max_lun = AHD_NUM_LUNS; 1099 host->max_lun = AHD_NUM_LUNS;
1084 host->max_channel = 0; 1100 host->max_channel = 0;
1085 host->sg_tablesize = AHD_NSEG; 1101 host->sg_tablesize = AHD_NSEG;
1102 ahd_lock(ahd, &s);
1086 ahd_set_unit(ahd, ahd_linux_unit++); 1103 ahd_set_unit(ahd, ahd_linux_unit++);
1104 ahd_unlock(ahd, &s);
1087 sprintf(buf, "scsi%d", host->host_no); 1105 sprintf(buf, "scsi%d", host->host_no);
1088 new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); 1106 new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
1089 if (new_name != NULL) { 1107 if (new_name != NULL) {
@@ -1093,7 +1111,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
1093 host->unique_id = ahd->unit; 1111 host->unique_id = ahd->unit;
1094 ahd_linux_initialize_scsi_bus(ahd); 1112 ahd_linux_initialize_scsi_bus(ahd);
1095 ahd_intr_enable(ahd, TRUE); 1113 ahd_intr_enable(ahd, TRUE);
1096 ahd_unlock(ahd, &s);
1097 1114
1098 host->transportt = ahd_linux_transport_template; 1115 host->transportt = ahd_linux_transport_template;
1099 1116
@@ -1127,6 +1144,7 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
1127{ 1144{
1128 u_int target_id; 1145 u_int target_id;
1129 u_int numtarg; 1146 u_int numtarg;
1147 unsigned long s;
1130 1148
1131 target_id = 0; 1149 target_id = 0;
1132 numtarg = 0; 1150 numtarg = 0;
@@ -1139,6 +1157,8 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
1139 else 1157 else
1140 numtarg = (ahd->features & AHD_WIDE) ? 16 : 8; 1158 numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
1141 1159
1160 ahd_lock(ahd, &s);
1161
1142 /* 1162 /*
1143 * Force negotiation to async for all targets that 1163 * Force negotiation to async for all targets that
1144 * will not see an initial bus reset. 1164 * will not see an initial bus reset.
@@ -1155,16 +1175,12 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
1155 ahd_update_neg_request(ahd, &devinfo, tstate, 1175 ahd_update_neg_request(ahd, &devinfo, tstate,
1156 tinfo, AHD_NEG_ALWAYS); 1176 tinfo, AHD_NEG_ALWAYS);
1157 } 1177 }
1178 ahd_unlock(ahd, &s);
1158 /* Give the bus some time to recover */ 1179 /* Give the bus some time to recover */
1159 if ((ahd->flags & AHD_RESET_BUS_A) != 0) { 1180 if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
1160 ahd_freeze_simq(ahd); 1181 ahd_freeze_simq(ahd);
1161 init_timer(&ahd->platform_data->reset_timer); 1182 msleep(AIC79XX_RESET_DELAY);
1162 ahd->platform_data->reset_timer.data = (u_long)ahd; 1183 ahd_release_simq(ahd);
1163 ahd->platform_data->reset_timer.expires =
1164 jiffies + (AIC79XX_RESET_DELAY * HZ)/1000;
1165 ahd->platform_data->reset_timer.function =
1166 (ahd_linux_callback_t *)ahd_release_simq;
1167 add_timer(&ahd->platform_data->reset_timer);
1168 } 1184 }
1169} 1185}
1170 1186
@@ -2033,6 +2049,9 @@ ahd_linux_sem_timeout(u_long arg)
2033void 2049void
2034ahd_freeze_simq(struct ahd_softc *ahd) 2050ahd_freeze_simq(struct ahd_softc *ahd)
2035{ 2051{
2052 unsigned long s;
2053
2054 ahd_lock(ahd, &s);
2036 ahd->platform_data->qfrozen++; 2055 ahd->platform_data->qfrozen++;
2037 if (ahd->platform_data->qfrozen == 1) { 2056 if (ahd->platform_data->qfrozen == 1) {
2038 scsi_block_requests(ahd->platform_data->host); 2057 scsi_block_requests(ahd->platform_data->host);
@@ -2040,6 +2059,7 @@ ahd_freeze_simq(struct ahd_softc *ahd)
2040 CAM_LUN_WILDCARD, SCB_LIST_NULL, 2059 CAM_LUN_WILDCARD, SCB_LIST_NULL,
2041 ROLE_INITIATOR, CAM_REQUEUE_REQ); 2060 ROLE_INITIATOR, CAM_REQUEUE_REQ);
2042 } 2061 }
2062 ahd_unlock(ahd, &s);
2043} 2063}
2044 2064
2045void 2065void
@@ -2344,8 +2364,9 @@ done:
2344 ahd_name(ahd), dev->active); 2364 ahd_name(ahd), dev->active);
2345 retval = FAILED; 2365 retval = FAILED;
2346 } 2366 }
2347 } 2367 } else
2348 ahd_unlock(ahd, &flags); 2368 ahd_unlock(ahd, &flags);
2369
2349 return (retval); 2370 return (retval);
2350} 2371}
2351 2372