forked from luck/tmp_suning_uos_patched
[SCSI] qla4xxx: multi-session fix for flash ddbs
Allow multi-session to target (for flash ddbs) accesible via multiple network portal Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
bc97f4bb44
commit
1cb78d73d3
|
@ -279,6 +279,7 @@ struct qla_ddb_index {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
uint16_t fw_ddb_idx;
|
uint16_t fw_ddb_idx;
|
||||||
struct dev_db_entry fw_ddb;
|
struct dev_db_entry fw_ddb;
|
||||||
|
uint8_t flash_isid[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DDB_IPADDR_LEN 64
|
#define DDB_IPADDR_LEN 64
|
||||||
|
|
|
@ -4299,7 +4299,8 @@ static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry,
|
static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry,
|
||||||
struct ql4_tuple_ddb *tddb)
|
struct ql4_tuple_ddb *tddb,
|
||||||
|
uint8_t *flash_isid)
|
||||||
{
|
{
|
||||||
uint16_t options = 0;
|
uint16_t options = 0;
|
||||||
|
|
||||||
|
@ -4314,7 +4315,12 @@ static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry,
|
||||||
sprintf(tddb->ip_addr, "%pI4", fw_ddb_entry->ip_addr);
|
sprintf(tddb->ip_addr, "%pI4", fw_ddb_entry->ip_addr);
|
||||||
|
|
||||||
tddb->port = le16_to_cpu(fw_ddb_entry->port);
|
tddb->port = le16_to_cpu(fw_ddb_entry->port);
|
||||||
memcpy(&tddb->isid[0], &fw_ddb_entry->isid[0], sizeof(tddb->isid));
|
|
||||||
|
if (flash_isid == NULL)
|
||||||
|
memcpy(&tddb->isid[0], &fw_ddb_entry->isid[0],
|
||||||
|
sizeof(tddb->isid));
|
||||||
|
else
|
||||||
|
memcpy(&tddb->isid[0], &flash_isid[0], sizeof(tddb->isid));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha,
|
static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha,
|
||||||
|
@ -4385,7 +4391,7 @@ static int qla4xxx_is_session_exists(struct scsi_qla_host *ha,
|
||||||
goto exit_check;
|
goto exit_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb);
|
qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb, NULL);
|
||||||
|
|
||||||
for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) {
|
for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) {
|
||||||
ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
|
ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
|
||||||
|
@ -4407,6 +4413,102 @@ static int qla4xxx_is_session_exists(struct scsi_qla_host *ha,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qla4xxx_check_existing_isid - check if target with same isid exist
|
||||||
|
* in target list
|
||||||
|
* @list_nt: list of target
|
||||||
|
* @isid: isid to check
|
||||||
|
*
|
||||||
|
* This routine return QLA_SUCCESS if target with same isid exist
|
||||||
|
**/
|
||||||
|
static int qla4xxx_check_existing_isid(struct list_head *list_nt, uint8_t *isid)
|
||||||
|
{
|
||||||
|
struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp;
|
||||||
|
struct dev_db_entry *fw_ddb_entry;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
|
||||||
|
fw_ddb_entry = &nt_ddb_idx->fw_ddb;
|
||||||
|
|
||||||
|
if (memcmp(&fw_ddb_entry->isid[0], &isid[0],
|
||||||
|
sizeof(nt_ddb_idx->fw_ddb.isid)) == 0) {
|
||||||
|
return QLA_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QLA_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qla4xxx_update_isid - compare ddbs and updated isid
|
||||||
|
* @ha: Pointer to host adapter structure.
|
||||||
|
* @list_nt: list of nt target
|
||||||
|
* @fw_ddb_entry: firmware ddb entry
|
||||||
|
*
|
||||||
|
* This routine update isid if ddbs have same iqn, same isid and
|
||||||
|
* different IP addr.
|
||||||
|
* Return QLA_SUCCESS if isid is updated.
|
||||||
|
**/
|
||||||
|
static int qla4xxx_update_isid(struct scsi_qla_host *ha,
|
||||||
|
struct list_head *list_nt,
|
||||||
|
struct dev_db_entry *fw_ddb_entry)
|
||||||
|
{
|
||||||
|
uint8_t base_value, i;
|
||||||
|
|
||||||
|
base_value = fw_ddb_entry->isid[1] & 0x1f;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
fw_ddb_entry->isid[1] = (base_value | (i << 5));
|
||||||
|
if (qla4xxx_check_existing_isid(list_nt, fw_ddb_entry->isid))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!qla4xxx_check_existing_isid(list_nt, fw_ddb_entry->isid))
|
||||||
|
return QLA_ERROR;
|
||||||
|
|
||||||
|
return QLA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qla4xxx_should_update_isid - check if isid need to update
|
||||||
|
* @ha: Pointer to host adapter structure.
|
||||||
|
* @old_tddb: ddb tuple
|
||||||
|
* @new_tddb: ddb tuple
|
||||||
|
*
|
||||||
|
* Return QLA_SUCCESS if different IP, different PORT, same iqn,
|
||||||
|
* same isid
|
||||||
|
**/
|
||||||
|
static int qla4xxx_should_update_isid(struct scsi_qla_host *ha,
|
||||||
|
struct ql4_tuple_ddb *old_tddb,
|
||||||
|
struct ql4_tuple_ddb *new_tddb)
|
||||||
|
{
|
||||||
|
if (strcmp(old_tddb->ip_addr, new_tddb->ip_addr) == 0) {
|
||||||
|
/* Same ip */
|
||||||
|
if (old_tddb->port == new_tddb->port)
|
||||||
|
return QLA_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name))
|
||||||
|
/* different iqn */
|
||||||
|
return QLA_ERROR;
|
||||||
|
|
||||||
|
if (memcmp(&old_tddb->isid[0], &new_tddb->isid[0],
|
||||||
|
sizeof(old_tddb->isid)))
|
||||||
|
/* different isid */
|
||||||
|
return QLA_ERROR;
|
||||||
|
|
||||||
|
return QLA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qla4xxx_is_flash_ddb_exists - check if fw_ddb_entry already exists in list_nt
|
||||||
|
* @ha: Pointer to host adapter structure.
|
||||||
|
* @list_nt: list of nt target.
|
||||||
|
* @fw_ddb_entry: firmware ddb entry.
|
||||||
|
*
|
||||||
|
* This routine check if fw_ddb_entry already exists in list_nt to avoid
|
||||||
|
* duplicate ddb in list_nt.
|
||||||
|
* Return QLA_SUCCESS if duplicate ddb exit in list_nl.
|
||||||
|
* Note: This function also update isid of DDB if required.
|
||||||
|
**/
|
||||||
|
|
||||||
static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha,
|
static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha,
|
||||||
struct list_head *list_nt,
|
struct list_head *list_nt,
|
||||||
struct dev_db_entry *fw_ddb_entry)
|
struct dev_db_entry *fw_ddb_entry)
|
||||||
|
@ -4414,7 +4516,7 @@ static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha,
|
||||||
struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp;
|
struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp;
|
||||||
struct ql4_tuple_ddb *fw_tddb = NULL;
|
struct ql4_tuple_ddb *fw_tddb = NULL;
|
||||||
struct ql4_tuple_ddb *tmp_tddb = NULL;
|
struct ql4_tuple_ddb *tmp_tddb = NULL;
|
||||||
int ret = QLA_ERROR;
|
int rval, ret = QLA_ERROR;
|
||||||
|
|
||||||
fw_tddb = vzalloc(sizeof(*fw_tddb));
|
fw_tddb = vzalloc(sizeof(*fw_tddb));
|
||||||
if (!fw_tddb) {
|
if (!fw_tddb) {
|
||||||
|
@ -4432,12 +4534,28 @@ static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha,
|
||||||
goto exit_check;
|
goto exit_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb);
|
qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb, NULL);
|
||||||
|
|
||||||
list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
|
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);
|
qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb,
|
||||||
if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, true)) {
|
nt_ddb_idx->flash_isid);
|
||||||
ret = QLA_SUCCESS; /* found */
|
ret = qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, true);
|
||||||
|
/* found duplicate ddb */
|
||||||
|
if (ret == QLA_SUCCESS)
|
||||||
|
goto exit_check;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, NULL);
|
||||||
|
|
||||||
|
ret = qla4xxx_should_update_isid(ha, tmp_tddb, fw_tddb);
|
||||||
|
if (ret == QLA_SUCCESS) {
|
||||||
|
rval = qla4xxx_update_isid(ha, list_nt, fw_ddb_entry);
|
||||||
|
if (rval == QLA_SUCCESS)
|
||||||
|
ret = QLA_ERROR;
|
||||||
|
else
|
||||||
|
ret = QLA_SUCCESS;
|
||||||
|
|
||||||
goto exit_check;
|
goto exit_check;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4788,14 +4906,26 @@ static void qla4xxx_build_nt_list(struct scsi_qla_host *ha,
|
||||||
|
|
||||||
nt_ddb_idx->fw_ddb_idx = idx;
|
nt_ddb_idx->fw_ddb_idx = idx;
|
||||||
|
|
||||||
memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
|
/* Copy original isid as it may get updated in function
|
||||||
sizeof(struct dev_db_entry));
|
* qla4xxx_update_isid(). We need original isid in
|
||||||
|
* function qla4xxx_compare_tuple_ddb to find duplicate
|
||||||
|
* target */
|
||||||
|
memcpy(&nt_ddb_idx->flash_isid[0],
|
||||||
|
&fw_ddb_entry->isid[0],
|
||||||
|
sizeof(nt_ddb_idx->flash_isid));
|
||||||
|
|
||||||
if (qla4xxx_is_flash_ddb_exists(ha, list_nt,
|
ret = qla4xxx_is_flash_ddb_exists(ha, list_nt,
|
||||||
fw_ddb_entry) == QLA_SUCCESS) {
|
fw_ddb_entry);
|
||||||
|
if (ret == QLA_SUCCESS) {
|
||||||
|
/* free nt_ddb_idx and do not add to list_nt */
|
||||||
vfree(nt_ddb_idx);
|
vfree(nt_ddb_idx);
|
||||||
goto continue_next_nt;
|
goto continue_next_nt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy updated isid */
|
||||||
|
memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
|
||||||
|
sizeof(struct dev_db_entry));
|
||||||
|
|
||||||
list_add_tail(&nt_ddb_idx->list, list_nt);
|
list_add_tail(&nt_ddb_idx->list, list_nt);
|
||||||
} else if (is_reset == RESET_ADAPTER) {
|
} else if (is_reset == RESET_ADAPTER) {
|
||||||
if (qla4xxx_is_session_exists(ha, fw_ddb_entry) ==
|
if (qla4xxx_is_session_exists(ha, fw_ddb_entry) ==
|
||||||
|
|
Loading…
Reference in New Issue
Block a user