aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChad Dupuis <chad.dupuis@qlogic.com>2012-08-22 14:21:00 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-09-24 04:03:36 -0400
commit5f16b331d83757ad5154af07b449c722fef45d5e (patch)
treee5ba70e771d5de6cf0e2d5ecf7ceb2ae9a90946d
parent09543c09ea37e15f806f29f0cdcbcc9417dbfa01 (diff)
[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: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c81
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h26
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c16
5 files changed, 65 insertions, 62 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index d651179899fa..0c4fd2cebc17 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -11,7 +11,7 @@
11 * ---------------------------------------------------------------------- 11 * ----------------------------------------------------------------------
12 * | Level | Last Value Used | Holes | 12 * | Level | Last Value Used | Holes |
13 * ---------------------------------------------------------------------- 13 * ----------------------------------------------------------------------
14 * | Module Init and Probe | 0x0122 | 0x4b,0xba,0xfa | 14 * | Module Init and Probe | 0x0123 | 0x4b,0xba,0xfa |
15 * | Mailbox commands | 0x1140 | 0x111a-0x111b | 15 * | Mailbox commands | 0x1140 | 0x111a-0x111b |
16 * | | | 0x112c-0x112e | 16 * | | | 0x112c-0x112e |
17 * | | | 0x113a | 17 * | | | 0x113a |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 39007f53aec0..28c0b3575616 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -129,6 +129,7 @@
129#define MAX_FIBRE_DEVICES_2400 2048 129#define MAX_FIBRE_DEVICES_2400 2048
130#define MAX_FIBRE_DEVICES_LOOP 128 130#define MAX_FIBRE_DEVICES_LOOP 128
131#define MAX_FIBRE_DEVICES_MAX MAX_FIBRE_DEVICES_2400 131#define MAX_FIBRE_DEVICES_MAX MAX_FIBRE_DEVICES_2400
132#define LOOPID_MAP_SIZE (ha->max_fibre_devices)
132#define MAX_FIBRE_LUNS 0xFFFF 133#define MAX_FIBRE_LUNS 0xFFFF
133#define MAX_HOST_COUNT 16 134#define MAX_HOST_COUNT 16
134 135
@@ -2918,6 +2919,7 @@ struct qla_hw_data {
2918 void *md_dump; 2919 void *md_dump;
2919 uint32_t md_dump_size; 2920 uint32_t md_dump_size;
2920 2921
2922 void *loop_id_map;
2921 struct qlt_hw_data tgt; 2923 struct qlt_hw_data tgt;
2922}; 2924};
2923 2925
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index a44653b42161..290052352619 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3285,7 +3285,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
3285 */ 3285 */
3286 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) { 3286 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
3287 fcport->d_id.b24 = new_fcport->d_id.b24; 3287 fcport->d_id.b24 = new_fcport->d_id.b24;
3288 fcport->loop_id = FC_NO_LOOP_ID; 3288 qla2x00_clear_loop_id(fcport);
3289 fcport->flags |= (FCF_FABRIC_DEVICE | 3289 fcport->flags |= (FCF_FABRIC_DEVICE |
3290 FCF_LOGIN_NEEDED); 3290 FCF_LOGIN_NEEDED);
3291 break; 3291 break;
@@ -3306,7 +3306,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
3306 ha->isp_ops->fabric_logout(vha, fcport->loop_id, 3306 ha->isp_ops->fabric_logout(vha, fcport->loop_id,
3307 fcport->d_id.b.domain, fcport->d_id.b.area, 3307 fcport->d_id.b.domain, fcport->d_id.b.area,
3308 fcport->d_id.b.al_pa); 3308 fcport->d_id.b.al_pa);
3309 fcport->loop_id = FC_NO_LOOP_ID; 3309 qla2x00_clear_loop_id(fcport);
3310 } 3310 }
3311 3311
3312 break; 3312 break;
@@ -3352,71 +3352,32 @@ int
3352qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) 3352qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
3353{ 3353{
3354 int rval; 3354 int rval;
3355 int found;
3356 fc_port_t *fcport;
3357 uint16_t first_loop_id;
3358 struct qla_hw_data *ha = vha->hw; 3355 struct qla_hw_data *ha = vha->hw;
3359 struct scsi_qla_host *vp;
3360 struct scsi_qla_host *tvp;
3361 unsigned long flags = 0; 3356 unsigned long flags = 0;
3362 3357
3363 rval = QLA_SUCCESS; 3358 rval = QLA_SUCCESS;
3364 3359
3365 /* Save starting loop ID. */ 3360 spin_lock_irqsave(&ha->vport_slock, flags);
3366 first_loop_id = dev->loop_id;
3367
3368 for (;;) {
3369 /* Skip loop ID if already used by adapter. */
3370 if (dev->loop_id == vha->loop_id)
3371 dev->loop_id++;
3372
3373 /* Skip reserved loop IDs. */
3374 while (qla2x00_is_reserved_id(vha, dev->loop_id))
3375 dev->loop_id++;
3376
3377 /* Reset loop ID if passed the end. */
3378 if (dev->loop_id > ha->max_loop_id) {
3379 /* first loop ID. */
3380 dev->loop_id = ha->min_external_loopid;
3381 }
3382
3383 /* Check for loop ID being already in use. */
3384 found = 0;
3385 fcport = NULL;
3386
3387 spin_lock_irqsave(&ha->vport_slock, flags);
3388 list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
3389 list_for_each_entry(fcport, &vp->vp_fcports, list) {
3390 if (fcport->loop_id == dev->loop_id &&
3391 fcport != dev) {
3392 /* ID possibly in use */
3393 found++;
3394 break;
3395 }
3396 }
3397 if (found)
3398 break;
3399 }
3400 spin_unlock_irqrestore(&ha->vport_slock, flags);
3401 3361
3402 /* If not in use then it is free to use. */ 3362 dev->loop_id = find_first_zero_bit(ha->loop_id_map,
3403 if (!found) { 3363 LOOPID_MAP_SIZE);
3404 ql_dbg(ql_dbg_disc, dev->vha, 0x2086, 3364 if (dev->loop_id >= LOOPID_MAP_SIZE ||
3405 "Assigning new loopid=%x, portid=%x.\n", 3365 qla2x00_is_reserved_id(vha, dev->loop_id)) {
3406 dev->loop_id, dev->d_id.b24); 3366 dev->loop_id = FC_NO_LOOP_ID;
3407 break; 3367 rval = QLA_FUNCTION_FAILED;
3408 } 3368 } else
3369 set_bit(dev->loop_id, ha->loop_id_map);
3409 3370
3410 /* ID in use. Try next value. */ 3371 spin_unlock_irqrestore(&ha->vport_slock, flags);
3411 dev->loop_id++;
3412 3372
3413 /* If wrap around. No free ID to use. */ 3373 if (rval == QLA_SUCCESS)
3414 if (dev->loop_id == first_loop_id) { 3374 ql_dbg(ql_dbg_disc, dev->vha, 0x2086,
3415 dev->loop_id = FC_NO_LOOP_ID; 3375 "Assigning new loopid=%x, portid=%x.\n",
3416 rval = QLA_FUNCTION_FAILED; 3376 dev->loop_id, dev->d_id.b24);
3417 break; 3377 else
3418 } 3378 ql_log(ql_log_warn, dev->vha, 0x2087,
3419 } 3379 "No loop_id's available, portid=%x.\n",
3380 dev->d_id.b24);
3420 3381
3421 return (rval); 3382 return (rval);
3422} 3383}
@@ -3616,7 +3577,7 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
3616 ha->isp_ops->fabric_logout(vha, fcport->loop_id, 3577 ha->isp_ops->fabric_logout(vha, fcport->loop_id,
3617 fcport->d_id.b.domain, fcport->d_id.b.area, 3578 fcport->d_id.b.domain, fcport->d_id.b.area,
3618 fcport->d_id.b.al_pa); 3579 fcport->d_id.b.al_pa);
3619 fcport->loop_id = FC_NO_LOOP_ID; 3580 qla2x00_clear_loop_id(fcport);
3620 fcport->login_retry = 0; 3581 fcport->login_retry = 0;
3621 3582
3622 rval = 3; 3583 rval = 3;
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 6e457643c639..c12add261712 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)
57 return fcp; 57 return fcp;
58} 58}
59 59
60static inline void
61qla2x00_set_reserved_loop_ids(struct qla_hw_data *ha)
62{
63 int i;
64
65 if (IS_FWI2_CAPABLE(ha))
66 return;
67
68 for (i = 0; i < SNS_FIRST_LOOP_ID; i++)
69 set_bit(i, ha->loop_id_map);
70 set_bit(MANAGEMENT_SERVER, ha->loop_id_map);
71 set_bit(BROADCAST, ha->loop_id_map);
72}
73
60static inline int 74static inline int
61qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id) 75qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id)
62{ 76{
@@ -69,6 +83,18 @@ qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id)
69} 83}
70 84
71static inline void 85static inline void
86qla2x00_clear_loop_id(fc_port_t *fcport) {
87 struct qla_hw_data *ha = fcport->vha->hw;
88
89 if (fcport->loop_id == FC_NO_LOOP_ID ||
90 qla2x00_is_reserved_id(fcport->vha, fcport->loop_id))
91 return;
92
93 clear_bit(fcport->loop_id, ha->loop_id_map);
94 fcport->loop_id = FC_NO_LOOP_ID;
95}
96
97static inline void
72qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp) 98qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp)
73{ 99{
74 struct dsd_dma *dsd_ptr, *tdsd_ptr; 100 struct dsd_dma *dsd_ptr, *tdsd_ptr;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index caa4ce417681..5f990291c259 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2872,6 +2872,7 @@ void qla2x00_free_fcports(struct scsi_qla_host *vha)
2872 2872
2873 list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) { 2873 list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) {
2874 list_del(&fcport->list); 2874 list_del(&fcport->list);
2875 qla2x00_clear_loop_id(fcport);
2875 kfree(fcport); 2876 kfree(fcport);
2876 fcport = NULL; 2877 fcport = NULL;
2877 } 2878 }
@@ -3169,6 +3170,18 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
3169 } 3170 }
3170 3171
3171 INIT_LIST_HEAD(&ha->vp_list); 3172 INIT_LIST_HEAD(&ha->vp_list);
3173
3174 /* Allocate memory for our loop_id bitmap */
3175 ha->loop_id_map = kzalloc(BITS_TO_LONGS(LOOPID_MAP_SIZE) * sizeof(long),
3176 GFP_KERNEL);
3177 if (!ha->loop_id_map)
3178 goto fail_async_pd;
3179 else {
3180 qla2x00_set_reserved_loop_ids(ha);
3181 ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0123,
3182 "loop_id_map=%p. \n", ha->loop_id_map);
3183 }
3184
3172 return 1; 3185 return 1;
3173 3186
3174fail_async_pd: 3187fail_async_pd:
@@ -3352,6 +3365,7 @@ qla2x00_mem_free(struct qla_hw_data *ha)
3352 kfree(ha->nvram); 3365 kfree(ha->nvram);
3353 kfree(ha->npiv_info); 3366 kfree(ha->npiv_info);
3354 kfree(ha->swl); 3367 kfree(ha->swl);
3368 kfree(ha->loop_id_map);
3355 3369
3356 ha->srb_mempool = NULL; 3370 ha->srb_mempool = NULL;
3357 ha->ctx_mempool = NULL; 3371 ha->ctx_mempool = NULL;
@@ -3687,7 +3701,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
3687 } 3701 }
3688 3702
3689 if (fcport->login_retry == 0 && status != QLA_SUCCESS) 3703 if (fcport->login_retry == 0 && status != QLA_SUCCESS)
3690 fcport->loop_id = FC_NO_LOOP_ID; 3704 qla2x00_clear_loop_id(fcport);
3691 } 3705 }
3692 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) 3706 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
3693 break; 3707 break;