aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx/ql4_init.c
diff options
context:
space:
mode:
authorManish Rangankar <manish.rangankar@qlogic.com>2011-07-25 14:48:53 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-08-27 10:36:24 -0400
commitb3a271a94d0034dd3bab10b8d8cd432843be629e (patch)
treee6b3db659daf0aa5c18394e0e58eb43c0a1c68af /drivers/scsi/qla4xxx/ql4_init.c
parent17fa575eec7254fb089f858cae135d64cd015440 (diff)
[SCSI] qla4xxx: support iscsiadm session mgmt
Add scsi_transport_iscsi hooks in qla4xxx to support iSCSI session management using iscsiadm. This patch is based on discussion here http://groups.google.com/group/open-iscsi/browse_thread/thread/e89fd888baf656a0# Now users can use iscsiadm to do target discovery and do login/logout to individual targets using the qla4xxx iSCSI class interface. This patch leaves some dead code, but to make it easier to review we are leaving and in the next patch we will remove that old code. V2 - NOTE: Added code to avoid waiting for AEN during login/logout in the driver, instead added a kernel to user event to notify iscsid about login status. Because of this iscsid will not get blocked. Signed-off-by: Manish Rangankar <manish.rangankar@qlogic.com> Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_init.c')
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c128
1 files changed, 50 insertions, 78 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 30680124c5c1..ca6b2c5f0fdd 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -48,22 +48,15 @@ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
48 * @ha: pointer to host adapter structure. 48 * @ha: pointer to host adapter structure.
49 * @ddb_entry: pointer to device database entry 49 * @ddb_entry: pointer to device database entry
50 * 50 *
51 * This routine deallocates and unlinks the specified ddb_entry from the 51 * This routine marks a DDB entry INVALID
52 * adapter's
53 **/ 52 **/
54void qla4xxx_free_ddb(struct scsi_qla_host *ha, 53void qla4xxx_free_ddb(struct scsi_qla_host *ha,
55 struct ddb_entry *ddb_entry) 54 struct ddb_entry *ddb_entry)
56{ 55{
57 /* Remove device entry from list */
58 list_del_init(&ddb_entry->list);
59
60 /* Remove device pointer from index mapping arrays */ 56 /* Remove device pointer from index mapping arrays */
61 ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = 57 ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] =
62 (struct ddb_entry *) INVALID_ENTRY; 58 (struct ddb_entry *) INVALID_ENTRY;
63 ha->tot_ddbs--; 59 ha->tot_ddbs--;
64
65 /* Free memory and scsi-ml struct for device entry */
66 qla4xxx_destroy_sess(ddb_entry);
67} 60}
68 61
69/** 62/**
@@ -820,7 +813,8 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha)
820 ((!ipv6_device && 813 ((!ipv6_device &&
821 *((uint32_t *)fw_ddb_entry->ip_addr)) 814 *((uint32_t *)fw_ddb_entry->ip_addr))
822 || ipv6_device)) { 815 || ipv6_device)) {
823 qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0); 816 qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0,
817 NULL);
824 if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, 818 if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index,
825 NULL, 0, NULL, 819 NULL, 0, NULL,
826 &next_fw_ddb_index, 820 &next_fw_ddb_index,
@@ -927,7 +921,7 @@ int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host *ha)
927 ddb_entry->fw_ddb_index)); 921 ddb_entry->fw_ddb_index));
928 iscsi_unblock_session(ddb_entry->sess); 922 iscsi_unblock_session(ddb_entry->sess);
929 } else if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) 923 } else if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
930 qla4xxx_mark_device_missing(ha, ddb_entry); 924 qla4xxx_mark_device_missing(ddb_entry->sess);
931 } 925 }
932 return status; 926 return status;
933} 927}
@@ -952,7 +946,7 @@ int qla4xxx_relogin_device(struct scsi_qla_host *ha,
952 DEBUG2(printk("scsi%ld: Relogin ddb [%d]. TOV=%d\n", ha->host_no, 946 DEBUG2(printk("scsi%ld: Relogin ddb [%d]. TOV=%d\n", ha->host_no,
953 ddb_entry->fw_ddb_index, relogin_timer)); 947 ddb_entry->fw_ddb_index, relogin_timer));
954 948
955 qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 0); 949 qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 0, NULL);
956 950
957 return QLA_SUCCESS; 951 return QLA_SUCCESS;
958} 952}
@@ -1418,88 +1412,66 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
1418 uint32_t state, uint32_t conn_err) 1412 uint32_t state, uint32_t conn_err)
1419{ 1413{
1420 struct ddb_entry * ddb_entry; 1414 struct ddb_entry * ddb_entry;
1415 uint32_t old_fw_ddb_device_state;
1416 int status = QLA_ERROR;
1421 1417
1422 /* check for out of range index */ 1418 /* check for out of range index */
1423 if (fw_ddb_index >= MAX_DDB_ENTRIES) 1419 if (fw_ddb_index >= MAX_DDB_ENTRIES)
1424 return QLA_ERROR; 1420 goto exit_ddb_event;
1425 1421
1426 /* Get the corresponging ddb entry */ 1422 /* Get the corresponging ddb entry */
1427 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index); 1423 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index);
1428 /* Device does not currently exist in our database. */ 1424 /* Device does not currently exist in our database. */
1429 if (ddb_entry == NULL) { 1425 if (ddb_entry == NULL) {
1430 if (state == DDB_DS_SESSION_ACTIVE) 1426 ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n",
1431 qla4xxx_add_device_dynamically(ha, fw_ddb_index); 1427 __func__, fw_ddb_index);
1432 return QLA_SUCCESS; 1428 goto exit_ddb_event;
1433 } 1429 }
1434 1430
1435 /* Device already exists in our database. */ 1431 old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
1436 DEBUG2(printk("scsi%ld: %s DDB - old state= 0x%x, new state=0x%x for " 1432 DEBUG2(ql4_printk(KERN_INFO, ha,
1437 "index [%d]\n", ha->host_no, __func__, 1433 "%s: DDB - old state = 0x%x, new state = 0x%x for "
1438 ddb_entry->fw_ddb_device_state, state, fw_ddb_index)); 1434 "index [%d]\n", __func__,
1435 ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
1439 1436
1440 ddb_entry->fw_ddb_device_state = state; 1437 ddb_entry->fw_ddb_device_state = state;
1441 /* Device is back online. */
1442 if ((ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) &&
1443 (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)) {
1444 atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
1445 atomic_set(&ddb_entry->relogin_retry_count, 0);
1446 atomic_set(&ddb_entry->relogin_timer, 0);
1447 clear_bit(DF_RELOGIN, &ddb_entry->flags);
1448 iscsi_unblock_session(ddb_entry->sess);
1449 iscsi_session_event(ddb_entry->sess,
1450 ISCSI_KEVENT_CREATE_SESSION);
1451 /*
1452 * Change the lun state to READY in case the lun TIMEOUT before
1453 * the device came back.
1454 */
1455 } else if (ddb_entry->fw_ddb_device_state != DDB_DS_SESSION_ACTIVE) {
1456 /* Device went away, mark device missing */
1457 if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) {
1458 DEBUG2(ql4_printk(KERN_INFO, ha, "%s mark missing "
1459 "ddb_entry 0x%p sess 0x%p conn 0x%p\n",
1460 __func__, ddb_entry,
1461 ddb_entry->sess, ddb_entry->conn));
1462 qla4xxx_mark_device_missing(ha, ddb_entry);
1463 }
1464 1438
1465 /* 1439 switch (old_fw_ddb_device_state) {
1466 * Relogin if device state changed to a not active state. 1440 case DDB_DS_LOGIN_IN_PROCESS:
1467 * However, do not relogin if a RELOGIN is in process, or 1441 switch (state) {
1468 * we are not allowed to relogin to this DDB. 1442 case DDB_DS_SESSION_ACTIVE:
1469 */ 1443 case DDB_DS_DISCOVERY:
1470 if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED && 1444 iscsi_conn_login_event(ddb_entry->conn,
1471 !test_bit(DF_RELOGIN, &ddb_entry->flags) && 1445 ISCSI_CONN_STATE_LOGGED_IN);
1472 qla4_is_relogin_allowed(ha, conn_err)) { 1446 qla4xxx_update_session_conn_param(ha, ddb_entry);
1447 status = QLA_SUCCESS;
1448 break;
1449 case DDB_DS_SESSION_FAILED:
1450 case DDB_DS_NO_CONNECTION_ACTIVE:
1451 iscsi_conn_login_event(ddb_entry->conn,
1452 ISCSI_CONN_STATE_FREE);
1453 status = QLA_SUCCESS;
1454 break;
1455 }
1456 break;
1457 case DDB_DS_SESSION_ACTIVE:
1458 if (state == DDB_DS_SESSION_FAILED) {
1473 /* 1459 /*
1474 * This triggers a relogin. After the relogin_timer 1460 * iscsi_session failure will cause userspace to
1475 * expires, the relogin gets scheduled. We must wait a 1461 * stop the connection which in turn would block the
1476 * minimum amount of time since receiving an 0x8014 AEN 1462 * iscsi_session and start relogin
1477 * with failed device_state or a logout response before
1478 * we can issue another relogin.
1479 */
1480 /* Firmware pads this timeout: (time2wait +1).
1481 * Driver retry to login should be longer than F/W.
1482 * Otherwise F/W will fail
1483 * set_ddb() mbx cmd with 0x4005 since it still
1484 * counting down its time2wait.
1485 */ 1463 */
1486 atomic_set(&ddb_entry->relogin_timer, 0); 1464 iscsi_session_failure(ddb_entry->sess->dd_data,
1487 atomic_set(&ddb_entry->retry_relogin_timer, 1465 ISCSI_ERR_CONN_FAILED);
1488 ddb_entry->default_time2wait + 4); 1466 status = QLA_SUCCESS;
1489 DEBUG(printk("scsi%ld: %s: ddb[%d] "
1490 "initiate relogin after %d seconds\n",
1491 ha->host_no, __func__,
1492 ddb_entry->fw_ddb_index,
1493 ddb_entry->default_time2wait + 4));
1494 } else {
1495 DEBUG(printk("scsi%ld: %s: ddb[%d] "
1496 "relogin not initiated, state = %d, "
1497 "ddb_entry->flags = 0x%lx\n",
1498 ha->host_no, __func__,
1499 ddb_entry->fw_ddb_index,
1500 ddb_entry->fw_ddb_device_state,
1501 ddb_entry->flags));
1502 } 1467 }
1468 break;
1469 default:
1470 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unknown Event\n",
1471 __func__));
1472 break;
1503 } 1473 }
1504 return QLA_SUCCESS; 1474
1475exit_ddb_event:
1476 return status;
1505} 1477}