[SCSI] qla4xxx: Add support for multiple session per host.
authorManish Rangankar <manish.rangankar@qlogic.com>
Mon, 27 Feb 2012 11:08:55 +0000 (03:08 -0800)
committerJames Bottomley <JBottomley@Parallels.com>
Wed, 29 Feb 2012 23:00:24 +0000 (17:00 -0600)
This patch will allow iscsiadm to create multiple session
for the same target on per host.

Signed-off-by: Manish Rangankar <manish.rangankar@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla4xxx/ql4_def.h
drivers/scsi/qla4xxx/ql4_mbx.c
drivers/scsi/qla4xxx/ql4_os.c

index 0b2487631d5254fc07da7d703c3419435fe1660b..7f2492e88be72085325bbb58debacefe9aaf288c 100644 (file)
@@ -291,6 +291,7 @@ struct ql4_tuple_ddb {
        uint16_t options;
 #define DDB_OPT_IPV6 0x0e0e
 #define DDB_OPT_IPV4 0x0f0f
+       uint8_t isid[6];
 };
 
 /*
index 71331e3b44041f866c738bd743662987643f9f60..b2d336c236c02eb060bffc102a9cad38e11e3188 100644 (file)
@@ -1607,7 +1607,7 @@ int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
        char *ip;
        uint16_t iscsi_opts = 0;
        uint32_t options = 0;
-       uint16_t idx;
+       uint16_t idx, *ptid;
 
        fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
                                          &fw_ddb_entry_dma, GFP_KERNEL);
@@ -1633,6 +1633,14 @@ int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
                goto exit_set_param;
        }
 
+       ptid = (uint16_t *)&fw_ddb_entry->isid[1];
+       *ptid = cpu_to_le16((uint16_t)ddb_entry->sess->target_id);
+
+       DEBUG2(ql4_printk(KERN_INFO, ha, "ISID [%02x%02x%02x%02x%02x%02x]\n",
+                         fw_ddb_entry->isid[5], fw_ddb_entry->isid[4],
+                         fw_ddb_entry->isid[3], fw_ddb_entry->isid[2],
+                         fw_ddb_entry->isid[1], fw_ddb_entry->isid[0]));
+
        iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options);
        memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias));
 
index cbaf2b33e48533c74e57cebc1127876ba7ae6aca..50074ed95767c2593ef72db92637d4d2087ee9b7 100644 (file)
@@ -4252,11 +4252,13 @@ static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry,
                sprintf(tddb->ip_addr, "%pI4", fw_ddb_entry->ip_addr);
 
        tddb->port = le16_to_cpu(fw_ddb_entry->port);
+       memcpy(&tddb->isid[0], &fw_ddb_entry->isid[0], sizeof(tddb->isid));
 }
 
 static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha,
                                     struct ql4_tuple_ddb *old_tddb,
-                                    struct ql4_tuple_ddb *new_tddb)
+                                    struct ql4_tuple_ddb *new_tddb,
+                                    uint8_t is_isid_compare)
 {
        if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name))
                return QLA_ERROR;
@@ -4267,6 +4269,26 @@ static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha,
        if (old_tddb->port != new_tddb->port)
                return QLA_ERROR;
 
+       /* For multi sessions, driver generates the ISID, so do not compare
+        * ISID in reset path since it would be a comparision between the
+        * driver generated ISID and firmware generated ISID. This could
+        * lead to adding duplicated DDBs in the list as driver generated
+        * ISID would not match firmware generated ISID.
+        */
+       if (is_isid_compare) {
+               DEBUG2(ql4_printk(KERN_INFO, ha, "%s: old ISID [%02x%02x%02x"
+                       "%02x%02x%02x] New ISID [%02x%02x%02x%02x%02x%02x]\n",
+                       __func__, old_tddb->isid[5], old_tddb->isid[4],
+                       old_tddb->isid[3], old_tddb->isid[2], old_tddb->isid[1],
+                       old_tddb->isid[0], new_tddb->isid[5], new_tddb->isid[4],
+                       new_tddb->isid[3], new_tddb->isid[2], new_tddb->isid[1],
+                       new_tddb->isid[0]));
+
+               if (memcmp(&old_tddb->isid[0], &new_tddb->isid[0],
+                          sizeof(old_tddb->isid)))
+                       return QLA_ERROR;
+       }
+
        DEBUG2(ql4_printk(KERN_INFO, ha,
                          "Match Found, fw[%d,%d,%s,%s], [%d,%d,%s,%s]",
                          old_tddb->port, old_tddb->tpgt, old_tddb->ip_addr,
@@ -4309,7 +4331,7 @@ static int qla4xxx_is_session_exists(struct scsi_qla_host *ha,
                        continue;
 
                qla4xxx_get_param_ddb(ddb_entry, tmp_tddb);
-               if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) {
+               if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, false)) {
                        ret = QLA_SUCCESS; /* found */
                        goto exit_check;
                }
@@ -4352,7 +4374,7 @@ static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha,
 
        list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
                qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb);
-               if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) {
+               if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, true)) {
                        ret = QLA_SUCCESS; /* found */
                        goto exit_check;
                }