diff options
author | Chad Dupuis <chad.dupuis@qlogic.com> | 2012-08-22 14:21:00 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-09-24 04:03:36 -0400 |
commit | 5f16b331d83757ad5154af07b449c722fef45d5e (patch) | |
tree | e5ba70e771d5de6cf0e2d5ecf7ceb2ae9a90946d | |
parent | 09543c09ea37e15f806f29f0cdcbcc9417dbfa01 (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.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 81 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_inline.h | 26 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 16 |
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 | |||
3352 | qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) | 3352 | qla2x00_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 | ||
60 | static inline void | ||
61 | qla2x00_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 | |||
60 | static inline int | 74 | static inline int |
61 | qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id) | 75 | qla2x00_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 | ||
71 | static inline void | 85 | static inline void |
86 | qla2x00_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 | |||
97 | static inline void | ||
72 | qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp) | 98 | qla2x00_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 | ||
3174 | fail_async_pd: | 3187 | fail_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; |