From: Chad Dupuis Date: Thu, 19 Jul 2012 09:13:50 +0000 (+0530) Subject: qla2xxx: Use bitmap to store loop_id's for fcports. X-Git-Tag: v2.6.39-400.9.0~456 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=cf4bc87d925ed92e095cecb85e8883b31e85f3e1;p=users%2Fjedix%2Flinux-maple.git 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. JIRA Key: V2632FC-199 Signed-off-by: Saurav Kashyap --- diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index f4c7a4578dd8..028f2676597d 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -13,7 +13,7 @@ * ---------------------------------------------------------------------- * | Module Init and Probe | 0x0120 | 0x4b,0xba,0xfa | * | Mailbox commands | 0x113e | 0x111a-0x111b | - * | Device Discovery | 0x2086 | 0x2020-0x2022 | + * | Device Discovery | 0x2087 | 0x2020-0x2022 | * | Queue Command and IO tracing | 0x3030 | 0x3006,0x3008 | * | | | 0x302d,0x302e | * | DPC Thread | 0x401c | 0x4002,0x4013 | diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index eb34590dd8d9..a699e769caaa 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -129,6 +129,7 @@ #define MAX_FIBRE_DEVICES_2400 2048 #define MAX_FIBRE_DEVICES_LOOP 128 #define MAX_FIBRE_DEVICES_MAX MAX_FIBRE_DEVICES_2400 +#define LOOPID_MAP_SIZE (ha->max_fibre_devices / 8) #define MAX_FIBRE_LUNS 0xFFFF #define MAX_HOST_COUNT 16 @@ -2864,6 +2865,8 @@ struct qla_hw_data { dma_addr_t md_tmplt_hdr_dma; void *md_dump; uint32_t md_dump_size; + + void *loop_id_map; }; /* diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 726d9557ea83..a7fe8b31b4d7 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3255,7 +3255,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, */ if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) { 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 | FCF_LOGIN_NEEDED); break; @@ -3276,7 +3276,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, ha->isp_ops->fabric_logout(vha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); - fcport->loop_id = FC_NO_LOOP_ID; + qla2x00_clear_loop_id(fcport); } break; @@ -3322,71 +3322,32 @@ int qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) { int rval; - int found; - fc_port_t *fcport; - uint16_t first_loop_id; struct qla_hw_data *ha = vha->hw; - struct scsi_qla_host *vp; - struct scsi_qla_host *tvp; unsigned long flags = 0; rval = QLA_SUCCESS; - /* Save starting loop ID. */ - first_loop_id = dev->loop_id; + spin_lock_irqsave(&ha->vport_slock, flags); - 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; - } + dev->loop_id = find_first_zero_bit(ha->loop_id_map, + LOOPID_MAP_SIZE); - /* Check for loop ID being already in use. */ - found = 0; - fcport = NULL; - - 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); - - /* If not in use then it is free to use. */ - if (!found) { - ql_dbg(ql_dbg_disc, dev->vha, 0x2086, - "Assigning new loopid=%x, portid=%x.\n", - dev->loop_id, dev->d_id.b24); - break; - } + if (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); - /* ID in use. Try next value. */ - dev->loop_id++; + spin_unlock_irqrestore(&ha->vport_slock, flags); - /* 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; - } - } + if (rval == QLA_SUCCESS) + ql_dbg(ql_dbg_disc, dev->vha, 0x2086, + "Assigning new loopid=%x, portid=%x.\n", + dev->loop_id, dev->d_id.b24); + else + ql_log(ql_log_warn, dev->vha, 0x2087, + "No loop_id's available, portid=%x.\n", + dev->d_id.b24); return (rval); } @@ -3580,7 +3541,7 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport, ha->isp_ops->fabric_logout(vha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); - fcport->loop_id = FC_NO_LOOP_ID; + qla2x00_clear_loop_id(fcport); fcport->login_retry = 0; rval = 3; diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index c4c6ce08c2d2..4d731f29a6ba 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -57,6 +57,20 @@ host_to_fcp_swap(uint8_t *fcp, uint32_t bsize) 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 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); } +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 qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp) { diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 0f913fc5affb..3cd239d8c40e 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2834,6 +2834,7 @@ void qla2x00_free_fcports(struct scsi_qla_host *vha) list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) { list_del(&fcport->list); + qla2x00_clear_loop_id(fcport); kfree(fcport); fcport = NULL; } @@ -3126,6 +3127,17 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, } INIT_LIST_HEAD(&ha->vp_list); + + /* Allocate memory for our loop_id bitmap */ + ha->loop_id_map = kzalloc(LOOPID_MAP_SIZE, 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, 0x0121, + "loop_id_map=%p. \n", ha->loop_id_map); + } + return 1; fail_async_pd: @@ -3305,6 +3317,7 @@ qla2x00_mem_free(struct qla_hw_data *ha) kfree(ha->nvram); kfree(ha->npiv_info); kfree(ha->swl); + kfree(ha->loop_id_map); ha->srb_mempool = NULL; ha->ctx_mempool = NULL; @@ -3636,7 +3649,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha) } 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)) break;