mirror of https://gitee.com/openkylin/linux.git
qla2xxx: Change scsi host lookup method.
For target mode, when new scsi command arrive, driver first performs a look up of the SCSI Host. The current look up method is based on the ALPA portion of the NPort ID. For Cisco switch, the ALPA can not be used as the index. Instead, the new search method is based on the full value of the Nport_ID via btree lib. Signed-off-by: Quinn Tran <quinn.tran@cavium.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
c423437e3f
commit
482c9dc792
|
@ -3,6 +3,7 @@ config SCSI_QLA_FC
|
||||||
depends on PCI && SCSI
|
depends on PCI && SCSI
|
||||||
depends on SCSI_FC_ATTRS
|
depends on SCSI_FC_ATTRS
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
|
select BTREE
|
||||||
---help---
|
---help---
|
||||||
This qla2xxx driver supports all QLogic Fibre Channel
|
This qla2xxx driver supports all QLogic Fibre Channel
|
||||||
PCI and PCIe host adapters.
|
PCI and PCIe host adapters.
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <linux/aer.h>
|
#include <linux/aer.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/btree.h>
|
||||||
|
|
||||||
#include <scsi/scsi.h>
|
#include <scsi/scsi.h>
|
||||||
#include <scsi/scsi_host.h>
|
#include <scsi/scsi_host.h>
|
||||||
|
@ -3311,6 +3312,7 @@ struct qlt_hw_data {
|
||||||
spinlock_t sess_lock;
|
spinlock_t sess_lock;
|
||||||
int rspq_vector_cpuid;
|
int rspq_vector_cpuid;
|
||||||
spinlock_t atio_lock ____cacheline_aligned;
|
spinlock_t atio_lock ____cacheline_aligned;
|
||||||
|
struct btree_head32 host_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_QFULL_CMDS_ALLOC 8192
|
#define MAX_QFULL_CMDS_ALLOC 8192
|
||||||
|
|
|
@ -854,5 +854,7 @@ extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
|
||||||
uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
|
uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
|
||||||
void qla24xx_delete_sess_fn(struct work_struct *);
|
void qla24xx_delete_sess_fn(struct work_struct *);
|
||||||
void qlt_unknown_atio_work_fn(struct work_struct *);
|
void qlt_unknown_atio_work_fn(struct work_struct *);
|
||||||
|
void qlt_update_host_map(struct scsi_qla_host *, port_id_t);
|
||||||
|
void qlt_remove_target_resources(struct qla_hw_data *);
|
||||||
|
|
||||||
#endif /* _QLA_GBL_H */
|
#endif /* _QLA_GBL_H */
|
||||||
|
|
|
@ -3340,8 +3340,8 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
|
||||||
uint8_t domain;
|
uint8_t domain;
|
||||||
char connect_type[22];
|
char connect_type[22];
|
||||||
struct qla_hw_data *ha = vha->hw;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
unsigned long flags;
|
|
||||||
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
|
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
|
||||||
|
port_id_t id;
|
||||||
|
|
||||||
/* Get host addresses. */
|
/* Get host addresses. */
|
||||||
rval = qla2x00_get_adapter_id(vha,
|
rval = qla2x00_get_adapter_id(vha,
|
||||||
|
@ -3419,13 +3419,11 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
|
||||||
|
|
||||||
/* Save Host port and loop ID. */
|
/* Save Host port and loop ID. */
|
||||||
/* byte order - Big Endian */
|
/* byte order - Big Endian */
|
||||||
vha->d_id.b.domain = domain;
|
id.b.domain = domain;
|
||||||
vha->d_id.b.area = area;
|
id.b.area = area;
|
||||||
vha->d_id.b.al_pa = al_pa;
|
id.b.al_pa = al_pa;
|
||||||
|
id.b.rsvd_1 = 0;
|
||||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
qlt_update_host_map(vha, id);
|
||||||
qlt_update_vp_map(vha, SET_AL_PA);
|
|
||||||
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
|
||||||
|
|
||||||
if (!vha->flags.init_done)
|
if (!vha->flags.init_done)
|
||||||
ql_log(ql_log_info, vha, 0x2010,
|
ql_log(ql_log_info, vha, 0x2010,
|
||||||
|
|
|
@ -3623,6 +3623,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
|
||||||
scsi_qla_host_t *vp = NULL;
|
scsi_qla_host_t *vp = NULL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int found;
|
int found;
|
||||||
|
port_id_t id;
|
||||||
|
|
||||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b6,
|
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b6,
|
||||||
"Entered %s.\n", __func__);
|
"Entered %s.\n", __func__);
|
||||||
|
@ -3630,6 +3631,11 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
|
||||||
if (rptid_entry->entry_status != 0)
|
if (rptid_entry->entry_status != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
id.b.domain = rptid_entry->port_id[2];
|
||||||
|
id.b.area = rptid_entry->port_id[1];
|
||||||
|
id.b.al_pa = rptid_entry->port_id[0];
|
||||||
|
id.b.rsvd_1 = 0;
|
||||||
|
|
||||||
if (rptid_entry->format == 0) {
|
if (rptid_entry->format == 0) {
|
||||||
/* loop */
|
/* loop */
|
||||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b7,
|
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b7,
|
||||||
|
@ -3641,13 +3647,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
|
||||||
rptid_entry->port_id[2], rptid_entry->port_id[1],
|
rptid_entry->port_id[2], rptid_entry->port_id[1],
|
||||||
rptid_entry->port_id[0]);
|
rptid_entry->port_id[0]);
|
||||||
|
|
||||||
vha->d_id.b.domain = rptid_entry->port_id[2];
|
qlt_update_host_map(vha, id);
|
||||||
vha->d_id.b.area = rptid_entry->port_id[1];
|
|
||||||
vha->d_id.b.al_pa = rptid_entry->port_id[0];
|
|
||||||
|
|
||||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
|
||||||
qlt_update_vp_map(vha, SET_AL_PA);
|
|
||||||
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
|
||||||
|
|
||||||
} else if (rptid_entry->format == 1) {
|
} else if (rptid_entry->format == 1) {
|
||||||
/* fabric */
|
/* fabric */
|
||||||
|
@ -3673,12 +3673,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
|
||||||
WWN_SIZE);
|
WWN_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
vha->d_id.b.domain = rptid_entry->port_id[2];
|
qlt_update_host_map(vha, id);
|
||||||
vha->d_id.b.area = rptid_entry->port_id[1];
|
|
||||||
vha->d_id.b.al_pa = rptid_entry->port_id[0];
|
|
||||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
|
||||||
qlt_update_vp_map(vha, SET_AL_PA);
|
|
||||||
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fc_host_port_name(vha->host) =
|
fc_host_port_name(vha->host) =
|
||||||
|
@ -3714,12 +3709,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
|
||||||
if (!found)
|
if (!found)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vp->d_id.b.domain = rptid_entry->port_id[2];
|
qlt_update_host_map(vp, id);
|
||||||
vp->d_id.b.area = rptid_entry->port_id[1];
|
|
||||||
vp->d_id.b.al_pa = rptid_entry->port_id[0];
|
|
||||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
|
||||||
qlt_update_vp_map(vp, SET_AL_PA);
|
|
||||||
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cannot configure here as we are still sitting on the
|
* Cannot configure here as we are still sitting on the
|
||||||
|
|
|
@ -3469,6 +3469,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
|
||||||
qla2x00_free_sysfs_attr(base_vha, true);
|
qla2x00_free_sysfs_attr(base_vha, true);
|
||||||
|
|
||||||
fc_remove_host(base_vha->host);
|
fc_remove_host(base_vha->host);
|
||||||
|
qlt_remove_target_resources(ha);
|
||||||
|
|
||||||
scsi_remove_host(base_vha->host);
|
scsi_remove_host(base_vha->host);
|
||||||
|
|
||||||
|
|
|
@ -187,21 +187,23 @@ static inline
|
||||||
struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha,
|
struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha,
|
||||||
uint8_t *d_id)
|
uint8_t *d_id)
|
||||||
{
|
{
|
||||||
struct qla_hw_data *ha = vha->hw;
|
struct scsi_qla_host *host;
|
||||||
uint8_t vp_idx;
|
uint32_t key = 0;
|
||||||
|
|
||||||
if ((vha->d_id.b.area != d_id[1]) || (vha->d_id.b.domain != d_id[0]))
|
if ((vha->d_id.b.area == d_id[1]) && (vha->d_id.b.domain == d_id[0]) &&
|
||||||
return NULL;
|
(vha->d_id.b.al_pa == d_id[2]))
|
||||||
|
|
||||||
if (vha->d_id.b.al_pa == d_id[2])
|
|
||||||
return vha;
|
return vha;
|
||||||
|
|
||||||
BUG_ON(ha->tgt.tgt_vp_map == NULL);
|
key = (uint32_t)d_id[0] << 16;
|
||||||
vp_idx = ha->tgt.tgt_vp_map[d_id[2]].idx;
|
key |= (uint32_t)d_id[1] << 8;
|
||||||
if (likely(test_bit(vp_idx, ha->vp_idx_map)))
|
key |= (uint32_t)d_id[2];
|
||||||
return ha->tgt.tgt_vp_map[vp_idx].vha;
|
|
||||||
|
|
||||||
return NULL;
|
host = btree_lookup32(&vha->hw->tgt.host_map, key);
|
||||||
|
if (!host)
|
||||||
|
ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
|
||||||
|
"Unable to find host %06x\n", key);
|
||||||
|
|
||||||
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
|
@ -6040,6 +6042,17 @@ int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void qlt_remove_target_resources(struct qla_hw_data *ha)
|
||||||
|
{
|
||||||
|
struct scsi_qla_host *node;
|
||||||
|
u32 key = 0;
|
||||||
|
|
||||||
|
btree_for_each_safe32(&ha->tgt.host_map, key, node)
|
||||||
|
btree_remove32(&ha->tgt.host_map, key);
|
||||||
|
|
||||||
|
btree_destroy32(&ha->tgt.host_map);
|
||||||
|
}
|
||||||
|
|
||||||
static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn,
|
static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn,
|
||||||
unsigned char *b)
|
unsigned char *b)
|
||||||
{
|
{
|
||||||
|
@ -6693,6 +6706,8 @@ qlt_modify_vp_config(struct scsi_qla_host *vha,
|
||||||
void
|
void
|
||||||
qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
|
qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!QLA_TGT_MODE_ENABLED())
|
if (!QLA_TGT_MODE_ENABLED())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -6712,6 +6727,13 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
|
||||||
qlt_unknown_atio_work_fn);
|
qlt_unknown_atio_work_fn);
|
||||||
|
|
||||||
qlt_clear_mode(base_vha);
|
qlt_clear_mode(base_vha);
|
||||||
|
|
||||||
|
rc = btree_init32(&ha->tgt.host_map);
|
||||||
|
if (rc)
|
||||||
|
ql_log(ql_log_info, base_vha, 0xffff,
|
||||||
|
"Unable to initialize ha->host_map btree\n");
|
||||||
|
|
||||||
|
qlt_update_vp_map(base_vha, SET_VP_IDX);
|
||||||
}
|
}
|
||||||
|
|
||||||
irqreturn_t
|
irqreturn_t
|
||||||
|
@ -6820,25 +6842,69 @@ qlt_mem_free(struct qla_hw_data *ha)
|
||||||
void
|
void
|
||||||
qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
|
qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
|
||||||
{
|
{
|
||||||
|
void *slot;
|
||||||
|
u32 key;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!QLA_TGT_MODE_ENABLED())
|
if (!QLA_TGT_MODE_ENABLED())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
key = vha->d_id.b24;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SET_VP_IDX:
|
case SET_VP_IDX:
|
||||||
vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = vha;
|
vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = vha;
|
||||||
break;
|
break;
|
||||||
case SET_AL_PA:
|
case SET_AL_PA:
|
||||||
vha->hw->tgt.tgt_vp_map[vha->d_id.b.al_pa].idx = vha->vp_idx;
|
slot = btree_lookup32(&vha->hw->tgt.host_map, key);
|
||||||
|
if (!slot) {
|
||||||
|
ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
|
||||||
|
"Save vha in host_map %p %06x\n", vha, key);
|
||||||
|
rc = btree_insert32(&vha->hw->tgt.host_map,
|
||||||
|
key, vha, GFP_ATOMIC);
|
||||||
|
if (rc)
|
||||||
|
ql_log(ql_log_info, vha, 0xffff,
|
||||||
|
"Unable to insert s_id into host_map: %06x\n",
|
||||||
|
key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
|
||||||
|
"replace existing vha in host_map %p %06x\n", vha, key);
|
||||||
|
btree_update32(&vha->hw->tgt.host_map, key, vha);
|
||||||
break;
|
break;
|
||||||
case RESET_VP_IDX:
|
case RESET_VP_IDX:
|
||||||
vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = NULL;
|
vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = NULL;
|
||||||
break;
|
break;
|
||||||
case RESET_AL_PA:
|
case RESET_AL_PA:
|
||||||
vha->hw->tgt.tgt_vp_map[vha->d_id.b.al_pa].idx = 0;
|
ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
|
||||||
|
"clear vha in host_map %p %06x\n", vha, key);
|
||||||
|
slot = btree_lookup32(&vha->hw->tgt.host_map, key);
|
||||||
|
if (slot)
|
||||||
|
btree_remove32(&vha->hw->tgt.host_map, key);
|
||||||
|
vha->d_id.b24 = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void qlt_update_host_map(struct scsi_qla_host *vha, port_id_t id)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
|
||||||
|
if (!vha->d_id.b24) {
|
||||||
|
spin_lock_irqsave(&ha->vport_slock, flags);
|
||||||
|
vha->d_id = id;
|
||||||
|
qlt_update_vp_map(vha, SET_AL_PA);
|
||||||
|
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
||||||
|
} else if (vha->d_id.b24 != id.b24) {
|
||||||
|
spin_lock_irqsave(&ha->vport_slock, flags);
|
||||||
|
qlt_update_vp_map(vha, RESET_AL_PA);
|
||||||
|
vha->d_id = id;
|
||||||
|
qlt_update_vp_map(vha, SET_AL_PA);
|
||||||
|
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int __init qlt_parse_ini_mode(void)
|
static int __init qlt_parse_ini_mode(void)
|
||||||
{
|
{
|
||||||
if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_EXCLUSIVE) == 0)
|
if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_EXCLUSIVE) == 0)
|
||||||
|
|
Loading…
Reference in New Issue