diff options
author | Krishna Gudipati <kgudipat@brocade.com> | 2011-12-20 21:58:32 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-01-10 18:01:24 -0500 |
commit | 5b7db7af522d9f281ff8bf540d2b5cbea2206b27 (patch) | |
tree | 7e2b2750a13a5ee9794d1893a0b575419cde95cf /drivers/scsi/bfa | |
parent | 8ca2dd87e7f29df99389e9dc41f7a45a35223672 (diff) |
[SCSI] bfa: Implement LUN Masking feature using the SCSI Slave Callouts.
This patch re-implements LUN Masking feature using SCSI Slave Callouts. With
the new design in the slave_alloc entry point; for each new LUN discovered we
check with our internal LUN Masking config whether to expose or to mask this
particular LUN. We return -ENXIO (No such device or address) from slave_alloc
for the LUNs we don't want to be exposed. We also notify the SCSI mid-layer
to do a sequential LUN scan rather than REPORT_LUNS based scan if LUN masking
is enabled on our HBA port, since a -ENXIO from any LUN in REPORT_LUNS based
scan translates to a scan abort. This patch also handles the dynamic lun
masking config change from enable to disable or vice-versa by resetting
sdev_bflags of LUN 0 appropriately.
Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bfa')
-rw-r--r-- | drivers/scsi/bfa/bfad.c | 2 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_attr.c | 2 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_bsg.c | 27 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_drv.h | 2 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_im.c | 56 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_im.h | 27 |
6 files changed, 112 insertions, 4 deletions
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 66fb72531b34..404fd10ddb21 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c | |||
@@ -674,6 +674,7 @@ bfad_vport_create(struct bfad_s *bfad, u16 vf_id, | |||
674 | 674 | ||
675 | spin_lock_irqsave(&bfad->bfad_lock, flags); | 675 | spin_lock_irqsave(&bfad->bfad_lock, flags); |
676 | bfa_fcs_vport_start(&vport->fcs_vport); | 676 | bfa_fcs_vport_start(&vport->fcs_vport); |
677 | list_add_tail(&vport->list_entry, &bfad->vport_list); | ||
677 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | 678 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
678 | 679 | ||
679 | return BFA_STATUS_OK; | 680 | return BFA_STATUS_OK; |
@@ -1404,6 +1405,7 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1404 | bfad->ref_count = 0; | 1405 | bfad->ref_count = 0; |
1405 | bfad->pport.bfad = bfad; | 1406 | bfad->pport.bfad = bfad; |
1406 | INIT_LIST_HEAD(&bfad->pbc_vport_list); | 1407 | INIT_LIST_HEAD(&bfad->pbc_vport_list); |
1408 | INIT_LIST_HEAD(&bfad->vport_list); | ||
1407 | 1409 | ||
1408 | /* Setup the debugfs node for this bfad */ | 1410 | /* Setup the debugfs node for this bfad */ |
1409 | if (bfa_debugfs_enable) | 1411 | if (bfa_debugfs_enable) |
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 9d95844ab463..1938fe0473e9 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c | |||
@@ -491,7 +491,7 @@ bfad_im_vport_delete(struct fc_vport *fc_vport) | |||
491 | 491 | ||
492 | free_scsi_host: | 492 | free_scsi_host: |
493 | bfad_scsi_host_free(bfad, im_port); | 493 | bfad_scsi_host_free(bfad, im_port); |
494 | 494 | list_del(&vport->list_entry); | |
495 | kfree(vport); | 495 | kfree(vport); |
496 | 496 | ||
497 | return 0; | 497 | return 0; |
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 06fc00caeb41..530de2b1200a 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c | |||
@@ -2394,6 +2394,21 @@ out: | |||
2394 | return 0; | 2394 | return 0; |
2395 | } | 2395 | } |
2396 | 2396 | ||
2397 | /* Function to reset the LUN SCAN mode */ | ||
2398 | static void | ||
2399 | bfad_iocmd_lunmask_reset_lunscan_mode(struct bfad_s *bfad, int lunmask_cfg) | ||
2400 | { | ||
2401 | struct bfad_im_port_s *pport_im = bfad->pport.im_port; | ||
2402 | struct bfad_vport_s *vport = NULL; | ||
2403 | |||
2404 | /* Set the scsi device LUN SCAN flags for base port */ | ||
2405 | bfad_reset_sdev_bflags(pport_im, lunmask_cfg); | ||
2406 | |||
2407 | /* Set the scsi device LUN SCAN flags for the vports */ | ||
2408 | list_for_each_entry(vport, &bfad->vport_list, list_entry) | ||
2409 | bfad_reset_sdev_bflags(vport->drv_port.im_port, lunmask_cfg); | ||
2410 | } | ||
2411 | |||
2397 | int | 2412 | int |
2398 | bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd) | 2413 | bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd) |
2399 | { | 2414 | { |
@@ -2401,11 +2416,17 @@ bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd) | |||
2401 | unsigned long flags; | 2416 | unsigned long flags; |
2402 | 2417 | ||
2403 | spin_lock_irqsave(&bfad->bfad_lock, flags); | 2418 | spin_lock_irqsave(&bfad->bfad_lock, flags); |
2404 | if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE) | 2419 | if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE) { |
2405 | iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_TRUE); | 2420 | iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_TRUE); |
2406 | else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE) | 2421 | /* Set the LUN Scanning mode to be Sequential scan */ |
2422 | if (iocmd->status == BFA_STATUS_OK) | ||
2423 | bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_TRUE); | ||
2424 | } else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE) { | ||
2407 | iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_FALSE); | 2425 | iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_FALSE); |
2408 | else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR) | 2426 | /* Set the LUN Scanning mode to default REPORT_LUNS scan */ |
2427 | if (iocmd->status == BFA_STATUS_OK) | ||
2428 | bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_FALSE); | ||
2429 | } else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR) | ||
2409 | iocmd->status = bfa_fcpim_lunmask_clear(&bfad->bfa); | 2430 | iocmd->status = bfa_fcpim_lunmask_clear(&bfad->bfa); |
2410 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | 2431 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
2411 | return 0; | 2432 | return 0; |
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index 5e19a5f820ec..dc5b9d99c450 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <scsi/scsi_transport_fc.h> | 43 | #include <scsi/scsi_transport_fc.h> |
44 | #include <scsi/scsi_transport.h> | 44 | #include <scsi/scsi_transport.h> |
45 | #include <scsi/scsi_bsg_fc.h> | 45 | #include <scsi/scsi_bsg_fc.h> |
46 | #include <scsi/scsi_devinfo.h> | ||
46 | 47 | ||
47 | #include "bfa_modules.h" | 48 | #include "bfa_modules.h" |
48 | #include "bfa_fcs.h" | 49 | #include "bfa_fcs.h" |
@@ -227,6 +228,7 @@ struct bfad_s { | |||
227 | struct list_head active_aen_q; | 228 | struct list_head active_aen_q; |
228 | struct bfa_aen_entry_s aen_list[BFA_AEN_MAX_ENTRY]; | 229 | struct bfa_aen_entry_s aen_list[BFA_AEN_MAX_ENTRY]; |
229 | spinlock_t bfad_aen_spinlock; | 230 | spinlock_t bfad_aen_spinlock; |
231 | struct list_head vport_list; | ||
230 | }; | 232 | }; |
231 | 233 | ||
232 | /* BFAD state machine events */ | 234 | /* BFAD state machine events */ |
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index e5db649e8eb7..3153923f5b60 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c | |||
@@ -918,16 +918,70 @@ bfad_get_itnim(struct bfad_im_port_s *im_port, int id) | |||
918 | } | 918 | } |
919 | 919 | ||
920 | /* | 920 | /* |
921 | * Function is invoked from the SCSI Host Template slave_alloc() entry point. | ||
922 | * Has the logic to query the LUN Mask database to check if this LUN needs to | ||
923 | * be made visible to the SCSI mid-layer or not. | ||
924 | * | ||
925 | * Returns BFA_STATUS_OK if this LUN needs to be added to the OS stack. | ||
926 | * Returns -ENXIO to notify SCSI mid-layer to not add this LUN to the OS stack. | ||
927 | */ | ||
928 | static int | ||
929 | bfad_im_check_if_make_lun_visible(struct scsi_device *sdev, | ||
930 | struct fc_rport *rport) | ||
931 | { | ||
932 | struct bfad_itnim_data_s *itnim_data = | ||
933 | (struct bfad_itnim_data_s *) rport->dd_data; | ||
934 | struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa; | ||
935 | struct bfa_rport_s *bfa_rport = itnim_data->itnim->bfa_itnim->rport; | ||
936 | struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(bfa); | ||
937 | int i = 0, ret = -ENXIO; | ||
938 | |||
939 | for (i = 0; i < MAX_LUN_MASK_CFG; i++) { | ||
940 | if (lun_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE && | ||
941 | scsilun_to_int(&lun_list[i].lun) == sdev->lun && | ||
942 | lun_list[i].rp_tag == bfa_rport->rport_tag && | ||
943 | lun_list[i].lp_tag == (u8)bfa_rport->rport_info.lp_tag) { | ||
944 | ret = BFA_STATUS_OK; | ||
945 | break; | ||
946 | } | ||
947 | } | ||
948 | return ret; | ||
949 | } | ||
950 | |||
951 | /* | ||
921 | * Scsi_Host template entry slave_alloc | 952 | * Scsi_Host template entry slave_alloc |
922 | */ | 953 | */ |
923 | static int | 954 | static int |
924 | bfad_im_slave_alloc(struct scsi_device *sdev) | 955 | bfad_im_slave_alloc(struct scsi_device *sdev) |
925 | { | 956 | { |
926 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); | 957 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); |
958 | struct bfad_itnim_data_s *itnim_data = | ||
959 | (struct bfad_itnim_data_s *) rport->dd_data; | ||
960 | struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa; | ||
927 | 961 | ||
928 | if (!rport || fc_remote_port_chkready(rport)) | 962 | if (!rport || fc_remote_port_chkready(rport)) |
929 | return -ENXIO; | 963 | return -ENXIO; |
930 | 964 | ||
965 | if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED) { | ||
966 | /* | ||
967 | * We should not mask LUN 0 - since this will translate | ||
968 | * to no LUN / TARGET for SCSI ml resulting no scan. | ||
969 | */ | ||
970 | if (sdev->lun == 0) { | ||
971 | sdev->sdev_bflags |= BLIST_NOREPORTLUN | | ||
972 | BLIST_SPARSELUN; | ||
973 | goto done; | ||
974 | } | ||
975 | |||
976 | /* | ||
977 | * Query LUN Mask configuration - to expose this LUN | ||
978 | * to the SCSI mid-layer or to mask it. | ||
979 | */ | ||
980 | if (bfad_im_check_if_make_lun_visible(sdev, rport) != | ||
981 | BFA_STATUS_OK) | ||
982 | return -ENXIO; | ||
983 | } | ||
984 | done: | ||
931 | sdev->hostdata = rport->dd_data; | 985 | sdev->hostdata = rport->dd_data; |
932 | 986 | ||
933 | return 0; | 987 | return 0; |
@@ -1037,6 +1091,8 @@ bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim) | |||
1037 | && (fc_rport->scsi_target_id < MAX_FCP_TARGET)) | 1091 | && (fc_rport->scsi_target_id < MAX_FCP_TARGET)) |
1038 | itnim->scsi_tgt_id = fc_rport->scsi_target_id; | 1092 | itnim->scsi_tgt_id = fc_rport->scsi_target_id; |
1039 | 1093 | ||
1094 | itnim->channel = fc_rport->channel; | ||
1095 | |||
1040 | return; | 1096 | return; |
1041 | } | 1097 | } |
1042 | 1098 | ||
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h index 004b6cf848d9..0814367ef101 100644 --- a/drivers/scsi/bfa/bfad_im.h +++ b/drivers/scsi/bfa/bfad_im.h | |||
@@ -91,6 +91,7 @@ struct bfad_itnim_s { | |||
91 | struct fc_rport *fc_rport; | 91 | struct fc_rport *fc_rport; |
92 | struct bfa_itnim_s *bfa_itnim; | 92 | struct bfa_itnim_s *bfa_itnim; |
93 | u16 scsi_tgt_id; | 93 | u16 scsi_tgt_id; |
94 | u16 channel; | ||
94 | u16 queue_work; | 95 | u16 queue_work; |
95 | unsigned long last_ramp_up_time; | 96 | unsigned long last_ramp_up_time; |
96 | unsigned long last_queue_full_time; | 97 | unsigned long last_queue_full_time; |
@@ -166,4 +167,30 @@ irqreturn_t bfad_intx(int irq, void *dev_id); | |||
166 | int bfad_im_bsg_request(struct fc_bsg_job *job); | 167 | int bfad_im_bsg_request(struct fc_bsg_job *job); |
167 | int bfad_im_bsg_timeout(struct fc_bsg_job *job); | 168 | int bfad_im_bsg_timeout(struct fc_bsg_job *job); |
168 | 169 | ||
170 | /* | ||
171 | * Macro to set the SCSI device sdev_bflags - sdev_bflags are used by the | ||
172 | * SCSI mid-layer to choose LUN Scanning mode REPORT_LUNS vs. Sequential Scan | ||
173 | * | ||
174 | * Internally iterate's over all the ITNIM's part of the im_port & set's the | ||
175 | * sdev_bflags for the scsi_device associated with LUN #0. | ||
176 | */ | ||
177 | #define bfad_reset_sdev_bflags(__im_port, __lunmask_cfg) do { \ | ||
178 | struct scsi_device *__sdev = NULL; \ | ||
179 | struct bfad_itnim_s *__itnim = NULL; \ | ||
180 | u32 scan_flags = BLIST_NOREPORTLUN | BLIST_SPARSELUN; \ | ||
181 | list_for_each_entry(__itnim, &((__im_port)->itnim_mapped_list), \ | ||
182 | list_entry) { \ | ||
183 | __sdev = scsi_device_lookup((__im_port)->shost, \ | ||
184 | __itnim->channel, \ | ||
185 | __itnim->scsi_tgt_id, 0); \ | ||
186 | if (__sdev) { \ | ||
187 | if ((__lunmask_cfg) == BFA_TRUE) \ | ||
188 | __sdev->sdev_bflags |= scan_flags; \ | ||
189 | else \ | ||
190 | __sdev->sdev_bflags &= ~scan_flags; \ | ||
191 | scsi_device_put(__sdev); \ | ||
192 | } \ | ||
193 | } \ | ||
194 | } while (0) | ||
195 | |||
169 | #endif | 196 | #endif |