Commit 5f16b331 authored by Chad Dupuis's avatar Chad Dupuis Committed by James Bottomley

[SCSI] qla2xxx: Use bitmap to store loop_id's for fcports.

Store used fcport loop_id's in a bitmap so that as opposed to looping through
all fcports to find the next free loop_id, new loop_id lookup can be just be
done via bitops.

[jejb: plus fix for incorrect LOOPID_MAP_SIZE from Andrew Vasquez]
Signed-off-by: default avatarGiridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarChad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 09543c09
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* ---------------------------------------------------------------------- * ----------------------------------------------------------------------
* | Level | Last Value Used | Holes | * | Level | Last Value Used | Holes |
* ---------------------------------------------------------------------- * ----------------------------------------------------------------------
* | Module Init and Probe | 0x0122 | 0x4b,0xba,0xfa | * | Module Init and Probe | 0x0123 | 0x4b,0xba,0xfa |
* | Mailbox commands | 0x1140 | 0x111a-0x111b | * | Mailbox commands | 0x1140 | 0x111a-0x111b |
* | | | 0x112c-0x112e | * | | | 0x112c-0x112e |
* | | | 0x113a | * | | | 0x113a |
......
...@@ -129,6 +129,7 @@ ...@@ -129,6 +129,7 @@
#define MAX_FIBRE_DEVICES_2400 2048 #define MAX_FIBRE_DEVICES_2400 2048
#define MAX_FIBRE_DEVICES_LOOP 128 #define MAX_FIBRE_DEVICES_LOOP 128
#define MAX_FIBRE_DEVICES_MAX MAX_FIBRE_DEVICES_2400 #define MAX_FIBRE_DEVICES_MAX MAX_FIBRE_DEVICES_2400
#define LOOPID_MAP_SIZE (ha->max_fibre_devices)
#define MAX_FIBRE_LUNS 0xFFFF #define MAX_FIBRE_LUNS 0xFFFF
#define MAX_HOST_COUNT 16 #define MAX_HOST_COUNT 16
...@@ -2918,6 +2919,7 @@ struct qla_hw_data { ...@@ -2918,6 +2919,7 @@ struct qla_hw_data {
void *md_dump; void *md_dump;
uint32_t md_dump_size; uint32_t md_dump_size;
void *loop_id_map;
struct qlt_hw_data tgt; struct qlt_hw_data tgt;
}; };
......
...@@ -3285,7 +3285,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, ...@@ -3285,7 +3285,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
*/ */
if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) { if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
fcport->d_id.b24 = new_fcport->d_id.b24; fcport->d_id.b24 = new_fcport->d_id.b24;
fcport->loop_id = FC_NO_LOOP_ID; qla2x00_clear_loop_id(fcport);
fcport->flags |= (FCF_FABRIC_DEVICE | fcport->flags |= (FCF_FABRIC_DEVICE |
FCF_LOGIN_NEEDED); FCF_LOGIN_NEEDED);
break; break;
...@@ -3306,7 +3306,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, ...@@ -3306,7 +3306,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
ha->isp_ops->fabric_logout(vha, fcport->loop_id, ha->isp_ops->fabric_logout(vha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa); fcport->d_id.b.al_pa);
fcport->loop_id = FC_NO_LOOP_ID; qla2x00_clear_loop_id(fcport);
} }
break; break;
...@@ -3352,71 +3352,32 @@ int ...@@ -3352,71 +3352,32 @@ int
qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
{ {
int rval; int rval;
int found;
fc_port_t *fcport;
uint16_t first_loop_id;
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *vp;
struct scsi_qla_host *tvp;
unsigned long flags = 0; unsigned long flags = 0;
rval = QLA_SUCCESS; rval = QLA_SUCCESS;
/* Save starting loop ID. */ spin_lock_irqsave(&ha->vport_slock, flags);
first_loop_id = dev->loop_id;
for (;;) {
/* Skip loop ID if already used by adapter. */
if (dev->loop_id == vha->loop_id)
dev->loop_id++;
/* Skip reserved loop IDs. */
while (qla2x00_is_reserved_id(vha, dev->loop_id))
dev->loop_id++;
/* Reset loop ID if passed the end. */
if (dev->loop_id > ha->max_loop_id) {
/* first loop ID. */
dev->loop_id = ha->min_external_loopid;
}
/* Check for loop ID being already in use. */ dev->loop_id = find_first_zero_bit(ha->loop_id_map,
found = 0; LOOPID_MAP_SIZE);
fcport = NULL; if (dev->loop_id >= LOOPID_MAP_SIZE ||
qla2x00_is_reserved_id(vha, dev->loop_id)) {
dev->loop_id = FC_NO_LOOP_ID;
rval = QLA_FUNCTION_FAILED;
} else
set_bit(dev->loop_id, ha->loop_id_map);
spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
list_for_each_entry(fcport, &vp->vp_fcports, list) {
if (fcport->loop_id == dev->loop_id &&
fcport != dev) {
/* ID possibly in use */
found++;
break;
}
}
if (found)
break;
}
spin_unlock_irqrestore(&ha->vport_slock, flags); spin_unlock_irqrestore(&ha->vport_slock, flags);
/* If not in use then it is free to use. */ if (rval == QLA_SUCCESS)
if (!found) {
ql_dbg(ql_dbg_disc, dev->vha, 0x2086, ql_dbg(ql_dbg_disc, dev->vha, 0x2086,
"Assigning new loopid=%x, portid=%x.\n", "Assigning new loopid=%x, portid=%x.\n",
dev->loop_id, dev->d_id.b24); dev->loop_id, dev->d_id.b24);
break; else
} ql_log(ql_log_warn, dev->vha, 0x2087,
"No loop_id's available, portid=%x.\n",
/* ID in use. Try next value. */ dev->d_id.b24);
dev->loop_id++;
/* If wrap around. No free ID to use. */
if (dev->loop_id == first_loop_id) {
dev->loop_id = FC_NO_LOOP_ID;
rval = QLA_FUNCTION_FAILED;
break;
}
}
return (rval); return (rval);
} }
...@@ -3616,7 +3577,7 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport, ...@@ -3616,7 +3577,7 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
ha->isp_ops->fabric_logout(vha, fcport->loop_id, ha->isp_ops->fabric_logout(vha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa); fcport->d_id.b.al_pa);
fcport->loop_id = FC_NO_LOOP_ID; qla2x00_clear_loop_id(fcport);
fcport->login_retry = 0; fcport->login_retry = 0;
rval = 3; rval = 3;
......
...@@ -57,6 +57,20 @@ host_to_fcp_swap(uint8_t *fcp, uint32_t bsize) ...@@ -57,6 +57,20 @@ host_to_fcp_swap(uint8_t *fcp, uint32_t bsize)
return fcp; return fcp;
} }
static inline void
qla2x00_set_reserved_loop_ids(struct qla_hw_data *ha)
{
int i;
if (IS_FWI2_CAPABLE(ha))
return;
for (i = 0; i < SNS_FIRST_LOOP_ID; i++)
set_bit(i, ha->loop_id_map);
set_bit(MANAGEMENT_SERVER, ha->loop_id_map);
set_bit(BROADCAST, ha->loop_id_map);
}
static inline int static inline int
qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id) qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id)
{ {
...@@ -68,6 +82,18 @@ qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id) ...@@ -68,6 +82,18 @@ qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id)
loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST); loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST);
} }
static inline void
qla2x00_clear_loop_id(fc_port_t *fcport) {
struct qla_hw_data *ha = fcport->vha->hw;
if (fcport->loop_id == FC_NO_LOOP_ID ||
qla2x00_is_reserved_id(fcport->vha, fcport->loop_id))
return;
clear_bit(fcport->loop_id, ha->loop_id_map);
fcport->loop_id = FC_NO_LOOP_ID;
}
static inline void static inline void
qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp) qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp)
{ {
......
...@@ -2872,6 +2872,7 @@ void qla2x00_free_fcports(struct scsi_qla_host *vha) ...@@ -2872,6 +2872,7 @@ void qla2x00_free_fcports(struct scsi_qla_host *vha)
list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) { list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) {
list_del(&fcport->list); list_del(&fcport->list);
qla2x00_clear_loop_id(fcport);
kfree(fcport); kfree(fcport);
fcport = NULL; fcport = NULL;
} }
...@@ -3169,6 +3170,18 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, ...@@ -3169,6 +3170,18 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
} }
INIT_LIST_HEAD(&ha->vp_list); INIT_LIST_HEAD(&ha->vp_list);
/* Allocate memory for our loop_id bitmap */
ha->loop_id_map = kzalloc(BITS_TO_LONGS(LOOPID_MAP_SIZE) * sizeof(long),
GFP_KERNEL);
if (!ha->loop_id_map)
goto fail_async_pd;
else {
qla2x00_set_reserved_loop_ids(ha);
ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0123,
"loop_id_map=%p. \n", ha->loop_id_map);
}
return 1; return 1;
fail_async_pd: fail_async_pd:
...@@ -3352,6 +3365,7 @@ qla2x00_mem_free(struct qla_hw_data *ha) ...@@ -3352,6 +3365,7 @@ qla2x00_mem_free(struct qla_hw_data *ha)
kfree(ha->nvram); kfree(ha->nvram);
kfree(ha->npiv_info); kfree(ha->npiv_info);
kfree(ha->swl); kfree(ha->swl);
kfree(ha->loop_id_map);
ha->srb_mempool = NULL; ha->srb_mempool = NULL;
ha->ctx_mempool = NULL; ha->ctx_mempool = NULL;
...@@ -3687,7 +3701,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha) ...@@ -3687,7 +3701,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
} }
if (fcport->login_retry == 0 && status != QLA_SUCCESS) if (fcport->login_retry == 0 && status != QLA_SUCCESS)
fcport->loop_id = FC_NO_LOOP_ID; qla2x00_clear_loop_id(fcport);
} }
if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment