aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_init.c
diff options
context:
space:
mode:
authorHarihara Kadayam <harihara.kadayam@qlogic.com>2008-04-03 16:13:26 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-07 13:19:15 -0400
commit4d4df1932b6b116aecc81039066fec27f2050762 (patch)
treeee02f449a0bb456e40fcdb5287609b98e8e8f62f /drivers/scsi/qla2xxx/qla_init.c
parentb93480e319654b8921364b49528532dff4822a45 (diff)
[SCSI] qla2xxx: Add ISP84XX support.
Signed-off-by: Ravi Anand <ravi.anand@qlogic.com> Additional cleanups and Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c119
1 files changed, 111 insertions, 8 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 10e6995b39a7..916462ef1966 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -37,6 +37,9 @@ static int qla2x00_restart_isp(scsi_qla_host_t *);
37 37
38static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev); 38static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev);
39 39
40static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
41static int qla84xx_init_chip(scsi_qla_host_t *);
42
40/****************************************************************************/ 43/****************************************************************************/
41/* QLogic ISP2x00 Hardware Support Functions. */ 44/* QLogic ISP2x00 Hardware Support Functions. */
42/****************************************************************************/ 45/****************************************************************************/
@@ -108,6 +111,14 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
108 return (rval); 111 return (rval);
109 qla2xxx_get_flash_info(ha); 112 qla2xxx_get_flash_info(ha);
110 } 113 }
114 if (IS_QLA84XX(ha)) {
115 ha->cs84xx = qla84xx_get_chip(ha);
116 if (!ha->cs84xx) {
117 qla_printk(KERN_ERR, ha,
118 "Unable to configure ISP84XX.\n");
119 return QLA_FUNCTION_FAILED;
120 }
121 }
111 rval = qla2x00_init_rings(ha); 122 rval = qla2x00_init_rings(ha);
112 123
113 return (rval); 124 return (rval);
@@ -1243,10 +1254,10 @@ static int
1243qla2x00_fw_ready(scsi_qla_host_t *ha) 1254qla2x00_fw_ready(scsi_qla_host_t *ha)
1244{ 1255{
1245 int rval; 1256 int rval;
1246 unsigned long wtime, mtime; 1257 unsigned long wtime, mtime, cs84xx_time;
1247 uint16_t min_wait; /* Minimum wait time if loop is down */ 1258 uint16_t min_wait; /* Minimum wait time if loop is down */
1248 uint16_t wait_time; /* Wait time if loop is coming ready */ 1259 uint16_t wait_time; /* Wait time if loop is coming ready */
1249 uint16_t fw_state; 1260 uint16_t state[3];
1250 1261
1251 rval = QLA_SUCCESS; 1262 rval = QLA_SUCCESS;
1252 1263
@@ -1275,12 +1286,34 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
1275 ha->host_no)); 1286 ha->host_no));
1276 1287
1277 do { 1288 do {
1278 rval = qla2x00_get_firmware_state(ha, &fw_state); 1289 rval = qla2x00_get_firmware_state(ha, state);
1279 if (rval == QLA_SUCCESS) { 1290 if (rval == QLA_SUCCESS) {
1280 if (fw_state < FSTATE_LOSS_OF_SYNC) { 1291 if (state[0] < FSTATE_LOSS_OF_SYNC) {
1281 ha->device_flags &= ~DFLG_NO_CABLE; 1292 ha->device_flags &= ~DFLG_NO_CABLE;
1282 } 1293 }
1283 if (fw_state == FSTATE_READY) { 1294 if (IS_QLA84XX(ha) && state[0] != FSTATE_READY) {
1295 DEBUG16(printk("scsi(%ld): fw_state=%x "
1296 "84xx=%x.\n", ha->host_no, state[0],
1297 state[2]));
1298 if ((state[2] & FSTATE_LOGGED_IN) &&
1299 (state[2] & FSTATE_WAITING_FOR_VERIFY)) {
1300 DEBUG16(printk("scsi(%ld): Sending "
1301 "verify iocb.\n", ha->host_no));
1302
1303 cs84xx_time = jiffies;
1304 rval = qla84xx_init_chip(ha);
1305 if (rval != QLA_SUCCESS)
1306 break;
1307
1308 /* Add time taken to initialize. */
1309 cs84xx_time = jiffies - cs84xx_time;
1310 wtime += cs84xx_time;
1311 mtime += cs84xx_time;
1312 DEBUG16(printk("scsi(%ld): Increasing "
1313 "wait time by %ld. New time %ld\n",
1314 ha->host_no, cs84xx_time, wtime));
1315 }
1316 } else if (state[0] == FSTATE_READY) {
1284 DEBUG(printk("scsi(%ld): F/W Ready - OK \n", 1317 DEBUG(printk("scsi(%ld): F/W Ready - OK \n",
1285 ha->host_no)); 1318 ha->host_no));
1286 1319
@@ -1294,7 +1327,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
1294 rval = QLA_FUNCTION_FAILED; 1327 rval = QLA_FUNCTION_FAILED;
1295 1328
1296 if (atomic_read(&ha->loop_down_timer) && 1329 if (atomic_read(&ha->loop_down_timer) &&
1297 fw_state != FSTATE_READY) { 1330 state[0] != FSTATE_READY) {
1298 /* Loop down. Timeout on min_wait for states 1331 /* Loop down. Timeout on min_wait for states
1299 * other than Wait for Login. 1332 * other than Wait for Login.
1300 */ 1333 */
@@ -1319,11 +1352,11 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
1319 msleep(500); 1352 msleep(500);
1320 1353
1321 DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n", 1354 DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
1322 ha->host_no, fw_state, jiffies)); 1355 ha->host_no, state[0], jiffies));
1323 } while (1); 1356 } while (1);
1324 1357
1325 DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n", 1358 DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
1326 ha->host_no, fw_state, jiffies)); 1359 ha->host_no, state[0], jiffies));
1327 1360
1328 if (rval) { 1361 if (rval) {
1329 DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n", 1362 DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n",
@@ -4038,3 +4071,73 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha)
4038 4071
4039 return rval; 4072 return rval;
4040} 4073}
4074
4075/* 84XX Support **************************************************************/
4076
4077static LIST_HEAD(qla_cs84xx_list);
4078static DEFINE_MUTEX(qla_cs84xx_mutex);
4079
4080static struct qla_chip_state_84xx *
4081qla84xx_get_chip(struct scsi_qla_host *ha)
4082{
4083 struct qla_chip_state_84xx *cs84xx;
4084
4085 mutex_lock(&qla_cs84xx_mutex);
4086
4087 /* Find any shared 84xx chip. */
4088 list_for_each_entry(cs84xx, &qla_cs84xx_list, list) {
4089 if (cs84xx->bus == ha->pdev->bus) {
4090 kref_get(&cs84xx->kref);
4091 goto done;
4092 }
4093 }
4094
4095 cs84xx = kzalloc(sizeof(*cs84xx), GFP_KERNEL);
4096 if (!cs84xx)
4097 goto done;
4098
4099 kref_init(&cs84xx->kref);
4100 spin_lock_init(&cs84xx->access_lock);
4101 mutex_init(&cs84xx->fw_update_mutex);
4102 cs84xx->bus = ha->pdev->bus;
4103
4104 list_add_tail(&cs84xx->list, &qla_cs84xx_list);
4105done:
4106 mutex_unlock(&qla_cs84xx_mutex);
4107 return cs84xx;
4108}
4109
4110static void
4111__qla84xx_chip_release(struct kref *kref)
4112{
4113 struct qla_chip_state_84xx *cs84xx =
4114 container_of(kref, struct qla_chip_state_84xx, kref);
4115
4116 mutex_lock(&qla_cs84xx_mutex);
4117 list_del(&cs84xx->list);
4118 mutex_unlock(&qla_cs84xx_mutex);
4119 kfree(cs84xx);
4120}
4121
4122void
4123qla84xx_put_chip(struct scsi_qla_host *ha)
4124{
4125 if (ha->cs84xx)
4126 kref_put(&ha->cs84xx->kref, __qla84xx_chip_release);
4127}
4128
4129static int
4130qla84xx_init_chip(scsi_qla_host_t *ha)
4131{
4132 int rval;
4133 uint16_t status[2];
4134
4135 mutex_lock(&ha->cs84xx->fw_update_mutex);
4136
4137 rval = qla84xx_verify_chip(ha, status);
4138
4139 mutex_unlock(&ha->cs84xx->fw_update_mutex);
4140
4141 return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED:
4142 QLA_SUCCESS;
4143}