diff options
-rw-r--r-- | drivers/scsi/bfa/bfa.h | 16 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_defs_svc.h | 30 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_fc.h | 156 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_fcpim.c | 469 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_fcpim.h | 12 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_svc.c | 33 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_svc.h | 15 |
7 files changed, 726 insertions, 5 deletions
diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h index 76300befffbe..a796de935054 100644 --- a/drivers/scsi/bfa/bfa.h +++ b/drivers/scsi/bfa/bfa.h | |||
@@ -382,6 +382,22 @@ int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, | |||
382 | #define bfa_get_fw_clock_res(__bfa) \ | 382 | #define bfa_get_fw_clock_res(__bfa) \ |
383 | ((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res) | 383 | ((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res) |
384 | 384 | ||
385 | /* | ||
386 | * lun mask macros return NULL when min cfg is enabled and there is | ||
387 | * no memory allocated for lunmask. | ||
388 | */ | ||
389 | #define bfa_get_lun_mask(__bfa) \ | ||
390 | ((&(__bfa)->modules.dconf_mod)->min_cfg) ? NULL : \ | ||
391 | (&(BFA_DCONF_MOD(__bfa)->dconf->lun_mask)) | ||
392 | |||
393 | #define bfa_get_lun_mask_list(_bfa) \ | ||
394 | ((&(_bfa)->modules.dconf_mod)->min_cfg) ? NULL : \ | ||
395 | (bfa_get_lun_mask(_bfa)->lun_list) | ||
396 | |||
397 | #define bfa_get_lun_mask_status(_bfa) \ | ||
398 | (((&(_bfa)->modules.dconf_mod)->min_cfg) \ | ||
399 | ? BFA_LUNMASK_MINCFG : ((bfa_get_lun_mask(_bfa))->status)) | ||
400 | |||
385 | void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids); | 401 | void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids); |
386 | void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg); | 402 | void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg); |
387 | void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg); | 403 | void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg); |
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h index 202cb692f981..863c6ba7d5eb 100644 --- a/drivers/scsi/bfa/bfa_defs_svc.h +++ b/drivers/scsi/bfa/bfa_defs_svc.h | |||
@@ -672,6 +672,12 @@ struct bfa_itnim_iostats_s { | |||
672 | u32 tm_iocdowns; /* TM cleaned-up due to IOC down */ | 672 | u32 tm_iocdowns; /* TM cleaned-up due to IOC down */ |
673 | u32 tm_cleanups; /* TM cleanup requests */ | 673 | u32 tm_cleanups; /* TM cleanup requests */ |
674 | u32 tm_cleanup_comps; /* TM cleanup completions */ | 674 | u32 tm_cleanup_comps; /* TM cleanup completions */ |
675 | u32 lm_lun_across_sg; /* LM lun is across sg data buf */ | ||
676 | u32 lm_lun_not_sup; /* LM lun not supported */ | ||
677 | u32 lm_rpl_data_changed; /* LM report-lun data changed */ | ||
678 | u32 lm_wire_residue_changed; /* LM report-lun rsp residue changed */ | ||
679 | u32 lm_small_buf_addresidue; /* LM buf smaller than reported cnt */ | ||
680 | u32 lm_lun_not_rdy; /* LM lun not ready */ | ||
675 | }; | 681 | }; |
676 | 682 | ||
677 | /* Modify char* port_stt[] in bfal_port.c if a new state was added */ | 683 | /* Modify char* port_stt[] in bfal_port.c if a new state was added */ |
@@ -787,6 +793,28 @@ enum bfa_port_linkstate_rsn { | |||
787 | CEE_ISCSI_PRI_PFC_OFF = 42, | 793 | CEE_ISCSI_PRI_PFC_OFF = 42, |
788 | CEE_ISCSI_PRI_OVERLAP_FCOE_PRI = 43 | 794 | CEE_ISCSI_PRI_OVERLAP_FCOE_PRI = 43 |
789 | }; | 795 | }; |
796 | |||
797 | #define MAX_LUN_MASK_CFG 16 | ||
798 | |||
799 | /* | ||
800 | * Initially flash content may be fff. On making LUN mask enable and disable | ||
801 | * state chnage. when report lun command is being processed it goes from | ||
802 | * BFA_LUN_MASK_ACTIVE to BFA_LUN_MASK_FETCH and comes back to | ||
803 | * BFA_LUN_MASK_ACTIVE. | ||
804 | */ | ||
805 | enum bfa_ioim_lun_mask_state_s { | ||
806 | BFA_IOIM_LUN_MASK_INACTIVE = 0, | ||
807 | BFA_IOIM_LUN_MASK_ACTIVE = 1, | ||
808 | BFA_IOIM_LUN_MASK_FETCHED = 2, | ||
809 | }; | ||
810 | |||
811 | enum bfa_lunmask_state_s { | ||
812 | BFA_LUNMASK_DISABLED = 0x00, | ||
813 | BFA_LUNMASK_ENABLED = 0x01, | ||
814 | BFA_LUNMASK_MINCFG = 0x02, | ||
815 | BFA_LUNMASK_UNINITIALIZED = 0xff, | ||
816 | }; | ||
817 | |||
790 | #pragma pack(1) | 818 | #pragma pack(1) |
791 | /* | 819 | /* |
792 | * LUN mask configuration | 820 | * LUN mask configuration |
@@ -794,7 +822,7 @@ enum bfa_port_linkstate_rsn { | |||
794 | struct bfa_lun_mask_s { | 822 | struct bfa_lun_mask_s { |
795 | wwn_t lp_wwn; | 823 | wwn_t lp_wwn; |
796 | wwn_t rp_wwn; | 824 | wwn_t rp_wwn; |
797 | lun_t lun; | 825 | struct scsi_lun lun; |
798 | u8 ua; | 826 | u8 ua; |
799 | u8 rsvd[3]; | 827 | u8 rsvd[3]; |
800 | u16 rp_tag; | 828 | u16 rp_tag; |
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h index a007345e472a..50b6a1c86195 100644 --- a/drivers/scsi/bfa/bfa_fc.h +++ b/drivers/scsi/bfa/bfa_fc.h | |||
@@ -21,7 +21,6 @@ | |||
21 | #include "bfad_drv.h" | 21 | #include "bfad_drv.h" |
22 | 22 | ||
23 | typedef u64 wwn_t; | 23 | typedef u64 wwn_t; |
24 | typedef u64 lun_t; | ||
25 | 24 | ||
26 | #define WWN_NULL (0) | 25 | #define WWN_NULL (0) |
27 | #define FC_SYMNAME_MAX 256 /* max name server symbolic name size */ | 26 | #define FC_SYMNAME_MAX 256 /* max name server symbolic name size */ |
@@ -57,6 +56,161 @@ struct scsi_cdb_s { | |||
57 | 56 | ||
58 | #define SCSI_MAX_ALLOC_LEN 0xFF /* maximum allocarion length */ | 57 | #define SCSI_MAX_ALLOC_LEN 0xFF /* maximum allocarion length */ |
59 | 58 | ||
59 | #define SCSI_SENSE_CUR_ERR 0x70 | ||
60 | #define SCSI_SENSE_DEF_ERR 0x71 | ||
61 | |||
62 | /* | ||
63 | * SCSI additional sense codes | ||
64 | */ | ||
65 | #define SCSI_ASC_LUN_NOT_READY 0x04 | ||
66 | #define SCSI_ASC_LUN_NOT_SUPPORTED 0x25 | ||
67 | #define SCSI_ASC_TOCC 0x3F | ||
68 | |||
69 | /* | ||
70 | * SCSI additional sense code qualifiers | ||
71 | */ | ||
72 | #define SCSI_ASCQ_MAN_INTR_REQ 0x03 /* manual intervention req */ | ||
73 | #define SCSI_ASCQ_RL_DATA_CHANGED 0x0E /* report luns data changed */ | ||
74 | |||
75 | /* | ||
76 | * Methods of reporting informational exceptions | ||
77 | */ | ||
78 | #define SCSI_MP_IEC_UNIT_ATTN 0x2 /* generate unit attention */ | ||
79 | |||
80 | struct scsi_report_luns_data_s { | ||
81 | u32 lun_list_length; /* length of LUN list length */ | ||
82 | u32 reserved; | ||
83 | struct scsi_lun lun[1]; /* first LUN in lun list */ | ||
84 | }; | ||
85 | |||
86 | struct scsi_inquiry_vendor_s { | ||
87 | u8 vendor_id[8]; | ||
88 | }; | ||
89 | |||
90 | struct scsi_inquiry_prodid_s { | ||
91 | u8 product_id[16]; | ||
92 | }; | ||
93 | |||
94 | struct scsi_inquiry_prodrev_s { | ||
95 | u8 product_rev[4]; | ||
96 | }; | ||
97 | |||
98 | struct scsi_inquiry_data_s { | ||
99 | #ifdef __BIG_ENDIAN | ||
100 | u8 peripheral_qual:3; /* peripheral qualifier */ | ||
101 | u8 device_type:5; /* peripheral device type */ | ||
102 | u8 rmb:1; /* removable medium bit */ | ||
103 | u8 device_type_mod:7; /* device type modifier */ | ||
104 | u8 version; | ||
105 | u8 aenc:1; /* async evt notification capability */ | ||
106 | u8 trm_iop:1; /* terminate I/O process */ | ||
107 | u8 norm_aca:1; /* normal ACA supported */ | ||
108 | u8 hi_support:1; /* SCSI-3: supports REPORT LUNS */ | ||
109 | u8 rsp_data_format:4; | ||
110 | u8 additional_len; | ||
111 | u8 sccs:1; | ||
112 | u8 reserved1:7; | ||
113 | u8 reserved2:1; | ||
114 | u8 enc_serv:1; /* enclosure service component */ | ||
115 | u8 reserved3:1; | ||
116 | u8 multi_port:1; /* multi-port device */ | ||
117 | u8 m_chngr:1; /* device in medium transport element */ | ||
118 | u8 ack_req_q:1; /* SIP specific bit */ | ||
119 | u8 addr32:1; /* SIP specific bit */ | ||
120 | u8 addr16:1; /* SIP specific bit */ | ||
121 | u8 rel_adr:1; /* relative address */ | ||
122 | u8 w_bus32:1; | ||
123 | u8 w_bus16:1; | ||
124 | u8 synchronous:1; | ||
125 | u8 linked_commands:1; | ||
126 | u8 trans_dis:1; | ||
127 | u8 cmd_queue:1; /* command queueing supported */ | ||
128 | u8 soft_reset:1; /* soft reset alternative (VS) */ | ||
129 | #else | ||
130 | u8 device_type:5; /* peripheral device type */ | ||
131 | u8 peripheral_qual:3; /* peripheral qualifier */ | ||
132 | u8 device_type_mod:7; /* device type modifier */ | ||
133 | u8 rmb:1; /* removable medium bit */ | ||
134 | u8 version; | ||
135 | u8 rsp_data_format:4; | ||
136 | u8 hi_support:1; /* SCSI-3: supports REPORT LUNS */ | ||
137 | u8 norm_aca:1; /* normal ACA supported */ | ||
138 | u8 terminate_iop:1;/* terminate I/O process */ | ||
139 | u8 aenc:1; /* async evt notification capability */ | ||
140 | u8 additional_len; | ||
141 | u8 reserved1:7; | ||
142 | u8 sccs:1; | ||
143 | u8 addr16:1; /* SIP specific bit */ | ||
144 | u8 addr32:1; /* SIP specific bit */ | ||
145 | u8 ack_req_q:1; /* SIP specific bit */ | ||
146 | u8 m_chngr:1; /* device in medium transport element */ | ||
147 | u8 multi_port:1; /* multi-port device */ | ||
148 | u8 reserved3:1; /* TBD - Vendor Specific */ | ||
149 | u8 enc_serv:1; /* enclosure service component */ | ||
150 | u8 reserved2:1; | ||
151 | u8 soft_seset:1; /* soft reset alternative (VS) */ | ||
152 | u8 cmd_queue:1; /* command queueing supported */ | ||
153 | u8 trans_dis:1; | ||
154 | u8 linked_commands:1; | ||
155 | u8 synchronous:1; | ||
156 | u8 w_bus16:1; | ||
157 | u8 w_bus32:1; | ||
158 | u8 rel_adr:1; /* relative address */ | ||
159 | #endif | ||
160 | struct scsi_inquiry_vendor_s vendor_id; | ||
161 | struct scsi_inquiry_prodid_s product_id; | ||
162 | struct scsi_inquiry_prodrev_s product_rev; | ||
163 | u8 vendor_specific[20]; | ||
164 | u8 reserved4[40]; | ||
165 | }; | ||
166 | |||
167 | /* | ||
168 | * SCSI sense data format | ||
169 | */ | ||
170 | struct scsi_sense_s { | ||
171 | #ifdef __BIG_ENDIAN | ||
172 | u8 valid:1; | ||
173 | u8 rsp_code:7; | ||
174 | #else | ||
175 | u8 rsp_code:7; | ||
176 | u8 valid:1; | ||
177 | #endif | ||
178 | u8 seg_num; | ||
179 | #ifdef __BIG_ENDIAN | ||
180 | u8 file_mark:1; | ||
181 | u8 eom:1; /* end of media */ | ||
182 | u8 ili:1; /* incorrect length indicator */ | ||
183 | u8 reserved:1; | ||
184 | u8 sense_key:4; | ||
185 | #else | ||
186 | u8 sense_key:4; | ||
187 | u8 reserved:1; | ||
188 | u8 ili:1; /* incorrect length indicator */ | ||
189 | u8 eom:1; /* end of media */ | ||
190 | u8 file_mark:1; | ||
191 | #endif | ||
192 | u8 information[4]; /* device-type or cmd specific info */ | ||
193 | u8 add_sense_length; /* additional sense length */ | ||
194 | u8 command_info[4];/* command specific information */ | ||
195 | u8 asc; /* additional sense code */ | ||
196 | u8 ascq; /* additional sense code qualifier */ | ||
197 | u8 fru_code; /* field replaceable unit code */ | ||
198 | #ifdef __BIG_ENDIAN | ||
199 | u8 sksv:1; /* sense key specific valid */ | ||
200 | u8 c_d:1; /* command/data bit */ | ||
201 | u8 res1:2; | ||
202 | u8 bpv:1; /* bit pointer valid */ | ||
203 | u8 bpointer:3; /* bit pointer */ | ||
204 | #else | ||
205 | u8 bpointer:3; /* bit pointer */ | ||
206 | u8 bpv:1; /* bit pointer valid */ | ||
207 | u8 res1:2; | ||
208 | u8 c_d:1; /* command/data bit */ | ||
209 | u8 sksv:1; /* sense key specific valid */ | ||
210 | #endif | ||
211 | u8 fpointer[2]; /* field pointer */ | ||
212 | }; | ||
213 | |||
60 | /* | 214 | /* |
61 | * Fibre Channel Header Structure (FCHS) definition | 215 | * Fibre Channel Header Structure (FCHS) definition |
62 | */ | 216 | */ |
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 7bc010dc17b1..e601f178c5a6 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c | |||
@@ -24,6 +24,9 @@ BFA_TRC_FILE(HAL, FCPIM); | |||
24 | * BFA ITNIM Related definitions | 24 | * BFA ITNIM Related definitions |
25 | */ | 25 | */ |
26 | static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim); | 26 | static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim); |
27 | static bfa_boolean_t bfa_ioim_lm_proc_rpl_data(struct bfa_ioim_s *ioim); | ||
28 | static bfa_boolean_t bfa_ioim_lm_proc_inq_data(struct bfa_ioim_s *ioim); | ||
29 | static void bfa_ioim_lm_init(struct bfa_s *bfa); | ||
27 | 30 | ||
28 | #define BFA_ITNIM_FROM_TAG(_fcpim, _tag) \ | 31 | #define BFA_ITNIM_FROM_TAG(_fcpim, _tag) \ |
29 | (((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1)))) | 32 | (((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1)))) |
@@ -57,6 +60,14 @@ static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim); | |||
57 | } \ | 60 | } \ |
58 | } while (0) | 61 | } while (0) |
59 | 62 | ||
63 | #define bfa_ioim_rp_wwn(__ioim) \ | ||
64 | (((struct bfa_fcs_rport_s *) \ | ||
65 | (__ioim)->itnim->rport->rport_drv)->pwwn) | ||
66 | |||
67 | #define bfa_ioim_lp_wwn(__ioim) \ | ||
68 | ((BFA_LPS_FROM_TAG(BFA_LPS_MOD((__ioim)->bfa), \ | ||
69 | (__ioim)->itnim->rport->rport_info.lp_tag))->pwwn) \ | ||
70 | |||
60 | #define bfa_itnim_sler_cb(__itnim) do { \ | 71 | #define bfa_itnim_sler_cb(__itnim) do { \ |
61 | if ((__itnim)->bfa->fcs) \ | 72 | if ((__itnim)->bfa->fcs) \ |
62 | bfa_cb_itnim_sler((__itnim)->ditn); \ | 73 | bfa_cb_itnim_sler((__itnim)->ditn); \ |
@@ -66,6 +77,18 @@ static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim); | |||
66 | } \ | 77 | } \ |
67 | } while (0) | 78 | } while (0) |
68 | 79 | ||
80 | enum bfa_ioim_lm_status { | ||
81 | BFA_IOIM_LM_PRESENT = 1, | ||
82 | BFA_IOIM_LM_LUN_NOT_SUP = 2, | ||
83 | BFA_IOIM_LM_RPL_DATA_CHANGED = 3, | ||
84 | BFA_IOIM_LM_LUN_NOT_RDY = 4, | ||
85 | }; | ||
86 | |||
87 | enum bfa_ioim_lm_ua_status { | ||
88 | BFA_IOIM_LM_UA_RESET = 0, | ||
89 | BFA_IOIM_LM_UA_SET = 1, | ||
90 | }; | ||
91 | |||
69 | /* | 92 | /* |
70 | * itnim state machine event | 93 | * itnim state machine event |
71 | */ | 94 | */ |
@@ -122,6 +145,9 @@ enum bfa_ioim_event { | |||
122 | BFA_IOIM_SM_TMDONE = 16, /* IO cleanup from tskim */ | 145 | BFA_IOIM_SM_TMDONE = 16, /* IO cleanup from tskim */ |
123 | BFA_IOIM_SM_HWFAIL = 17, /* IOC h/w failure event */ | 146 | BFA_IOIM_SM_HWFAIL = 17, /* IOC h/w failure event */ |
124 | BFA_IOIM_SM_IOTOV = 18, /* ITN offline TOV */ | 147 | BFA_IOIM_SM_IOTOV = 18, /* ITN offline TOV */ |
148 | BFA_IOIM_SM_LM_LUN_NOT_SUP = 19,/* lunmask lun not supported */ | ||
149 | BFA_IOIM_SM_LM_RPL_DC = 20, /* lunmask report-lun data changed */ | ||
150 | BFA_IOIM_SM_LM_LUN_NOT_RDY = 21,/* lunmask lun not ready */ | ||
125 | }; | 151 | }; |
126 | 152 | ||
127 | 153 | ||
@@ -219,6 +245,9 @@ static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete); | |||
219 | static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete); | 245 | static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete); |
220 | static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete); | 246 | static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete); |
221 | static bfa_boolean_t bfa_ioim_is_abortable(struct bfa_ioim_s *ioim); | 247 | static bfa_boolean_t bfa_ioim_is_abortable(struct bfa_ioim_s *ioim); |
248 | static void __bfa_cb_ioim_lm_lun_not_sup(void *cbarg, bfa_boolean_t complete); | ||
249 | static void __bfa_cb_ioim_lm_rpl_dc(void *cbarg, bfa_boolean_t complete); | ||
250 | static void __bfa_cb_ioim_lm_lun_not_rdy(void *cbarg, bfa_boolean_t complete); | ||
222 | 251 | ||
223 | /* | 252 | /* |
224 | * forward declaration of BFA IO state machine | 253 | * forward declaration of BFA IO state machine |
@@ -416,6 +445,12 @@ bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats, | |||
416 | bfa_fcpim_add_iostats(lstats, rstats, output_reqs); | 445 | bfa_fcpim_add_iostats(lstats, rstats, output_reqs); |
417 | bfa_fcpim_add_iostats(lstats, rstats, rd_throughput); | 446 | bfa_fcpim_add_iostats(lstats, rstats, rd_throughput); |
418 | bfa_fcpim_add_iostats(lstats, rstats, wr_throughput); | 447 | bfa_fcpim_add_iostats(lstats, rstats, wr_throughput); |
448 | bfa_fcpim_add_iostats(lstats, rstats, lm_lun_across_sg); | ||
449 | bfa_fcpim_add_iostats(lstats, rstats, lm_lun_not_sup); | ||
450 | bfa_fcpim_add_iostats(lstats, rstats, lm_rpl_data_changed); | ||
451 | bfa_fcpim_add_iostats(lstats, rstats, lm_wire_residue_changed); | ||
452 | bfa_fcpim_add_iostats(lstats, rstats, lm_small_buf_addresidue); | ||
453 | bfa_fcpim_add_iostats(lstats, rstats, lm_lun_not_rdy); | ||
419 | } | 454 | } |
420 | 455 | ||
421 | bfa_status_t | 456 | bfa_status_t |
@@ -1542,7 +1577,28 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | |||
1542 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | 1577 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); |
1543 | WARN_ON(!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim)); | 1578 | WARN_ON(!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim)); |
1544 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, | 1579 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, |
1545 | __bfa_cb_ioim_abort, ioim); | 1580 | __bfa_cb_ioim_abort, ioim); |
1581 | break; | ||
1582 | |||
1583 | case BFA_IOIM_SM_LM_LUN_NOT_SUP: | ||
1584 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
1585 | bfa_ioim_move_to_comp_q(ioim); | ||
1586 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, | ||
1587 | __bfa_cb_ioim_lm_lun_not_sup, ioim); | ||
1588 | break; | ||
1589 | |||
1590 | case BFA_IOIM_SM_LM_RPL_DC: | ||
1591 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
1592 | bfa_ioim_move_to_comp_q(ioim); | ||
1593 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, | ||
1594 | __bfa_cb_ioim_lm_rpl_dc, ioim); | ||
1595 | break; | ||
1596 | |||
1597 | case BFA_IOIM_SM_LM_LUN_NOT_RDY: | ||
1598 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
1599 | bfa_ioim_move_to_comp_q(ioim); | ||
1600 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, | ||
1601 | __bfa_cb_ioim_lm_lun_not_rdy, ioim); | ||
1546 | break; | 1602 | break; |
1547 | 1603 | ||
1548 | default: | 1604 | default: |
@@ -2082,6 +2138,264 @@ bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | |||
2082 | } | 2138 | } |
2083 | } | 2139 | } |
2084 | 2140 | ||
2141 | /* | ||
2142 | * This is called from bfa_fcpim_start after the bfa_init() with flash read | ||
2143 | * is complete by driver. now invalidate the stale content of lun mask | ||
2144 | * like unit attention, rp tag and lp tag. | ||
2145 | */ | ||
2146 | static void | ||
2147 | bfa_ioim_lm_init(struct bfa_s *bfa) | ||
2148 | { | ||
2149 | struct bfa_lun_mask_s *lunm_list; | ||
2150 | int i; | ||
2151 | |||
2152 | if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) | ||
2153 | return; | ||
2154 | |||
2155 | lunm_list = bfa_get_lun_mask_list(bfa); | ||
2156 | for (i = 0; i < MAX_LUN_MASK_CFG; i++) { | ||
2157 | lunm_list[i].ua = BFA_IOIM_LM_UA_RESET; | ||
2158 | lunm_list[i].lp_tag = BFA_LP_TAG_INVALID; | ||
2159 | lunm_list[i].rp_tag = BFA_RPORT_TAG_INVALID; | ||
2160 | } | ||
2161 | } | ||
2162 | |||
2163 | /* | ||
2164 | * Validate LUN for LUN masking | ||
2165 | */ | ||
2166 | static enum bfa_ioim_lm_status | ||
2167 | bfa_ioim_lm_check(struct bfa_ioim_s *ioim, struct bfa_lps_s *lps, | ||
2168 | struct bfa_rport_s *rp, struct scsi_lun lun) | ||
2169 | { | ||
2170 | u8 i; | ||
2171 | struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa); | ||
2172 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio; | ||
2173 | struct scsi_cdb_s *cdb = (struct scsi_cdb_s *)cmnd->cmnd; | ||
2174 | |||
2175 | if ((cdb->scsi_cdb[0] == REPORT_LUNS) && | ||
2176 | (scsilun_to_int((struct scsi_lun *)&lun) == 0)) { | ||
2177 | ioim->proc_rsp_data = bfa_ioim_lm_proc_rpl_data; | ||
2178 | return BFA_IOIM_LM_PRESENT; | ||
2179 | } | ||
2180 | |||
2181 | for (i = 0; i < MAX_LUN_MASK_CFG; i++) { | ||
2182 | |||
2183 | if (lun_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE) | ||
2184 | continue; | ||
2185 | |||
2186 | if ((scsilun_to_int((struct scsi_lun *)&lun_list[i].lun) == | ||
2187 | scsilun_to_int((struct scsi_lun *)&lun)) | ||
2188 | && (rp->rport_tag == lun_list[i].rp_tag) | ||
2189 | && ((u8)ioim->itnim->rport->rport_info.lp_tag == | ||
2190 | lun_list[i].lp_tag)) { | ||
2191 | bfa_trc(ioim->bfa, lun_list[i].rp_tag); | ||
2192 | bfa_trc(ioim->bfa, lun_list[i].lp_tag); | ||
2193 | bfa_trc(ioim->bfa, scsilun_to_int( | ||
2194 | (struct scsi_lun *)&lun_list[i].lun)); | ||
2195 | |||
2196 | if ((lun_list[i].ua == BFA_IOIM_LM_UA_SET) && | ||
2197 | ((cdb->scsi_cdb[0] != INQUIRY) || | ||
2198 | (cdb->scsi_cdb[0] != REPORT_LUNS))) { | ||
2199 | lun_list[i].ua = BFA_IOIM_LM_UA_RESET; | ||
2200 | return BFA_IOIM_LM_RPL_DATA_CHANGED; | ||
2201 | } | ||
2202 | |||
2203 | if (cdb->scsi_cdb[0] == REPORT_LUNS) | ||
2204 | ioim->proc_rsp_data = bfa_ioim_lm_proc_rpl_data; | ||
2205 | |||
2206 | return BFA_IOIM_LM_PRESENT; | ||
2207 | } | ||
2208 | } | ||
2209 | |||
2210 | if ((cdb->scsi_cdb[0] == INQUIRY) && | ||
2211 | (scsilun_to_int((struct scsi_lun *)&lun) == 0)) { | ||
2212 | ioim->proc_rsp_data = bfa_ioim_lm_proc_inq_data; | ||
2213 | return BFA_IOIM_LM_PRESENT; | ||
2214 | } | ||
2215 | |||
2216 | if (cdb->scsi_cdb[0] == TEST_UNIT_READY) | ||
2217 | return BFA_IOIM_LM_LUN_NOT_RDY; | ||
2218 | |||
2219 | return BFA_IOIM_LM_LUN_NOT_SUP; | ||
2220 | } | ||
2221 | |||
2222 | static bfa_boolean_t | ||
2223 | bfa_ioim_lm_proc_rsp_data_dummy(struct bfa_ioim_s *ioim) | ||
2224 | { | ||
2225 | return BFA_TRUE; | ||
2226 | } | ||
2227 | |||
2228 | static void | ||
2229 | bfa_ioim_lm_fetch_lun(struct bfa_ioim_s *ioim, u8 *rl_data, int offset, | ||
2230 | int buf_lun_cnt) | ||
2231 | { | ||
2232 | struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa); | ||
2233 | struct scsi_lun *lun_data = (struct scsi_lun *)(rl_data + offset); | ||
2234 | struct scsi_lun lun; | ||
2235 | int i, j; | ||
2236 | |||
2237 | bfa_trc(ioim->bfa, buf_lun_cnt); | ||
2238 | for (j = 0; j < buf_lun_cnt; j++) { | ||
2239 | lun = *((struct scsi_lun *)(lun_data + j)); | ||
2240 | for (i = 0; i < MAX_LUN_MASK_CFG; i++) { | ||
2241 | if (lun_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE) | ||
2242 | continue; | ||
2243 | if ((lun_list[i].rp_wwn == bfa_ioim_rp_wwn(ioim)) && | ||
2244 | (lun_list[i].lp_wwn == bfa_ioim_lp_wwn(ioim)) && | ||
2245 | (scsilun_to_int((struct scsi_lun *)&lun_list[i].lun) | ||
2246 | == scsilun_to_int((struct scsi_lun *)&lun))) { | ||
2247 | lun_list[i].state = BFA_IOIM_LUN_MASK_FETCHED; | ||
2248 | break; | ||
2249 | } | ||
2250 | } /* next lun in mask DB */ | ||
2251 | } /* next lun in buf */ | ||
2252 | } | ||
2253 | |||
2254 | static int | ||
2255 | bfa_ioim_lm_update_lun_sg(struct bfa_ioim_s *ioim, u32 *pgdlen, | ||
2256 | struct scsi_report_luns_data_s *rl) | ||
2257 | { | ||
2258 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio; | ||
2259 | struct scatterlist *sg = scsi_sglist(cmnd); | ||
2260 | struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa); | ||
2261 | struct scsi_lun *prev_rl_data = NULL, *base_rl_data; | ||
2262 | int i, j, sgeid, lun_fetched_cnt = 0, prev_sg_len = 0, base_count; | ||
2263 | int lun_across_sg_bytes, bytes_from_next_buf; | ||
2264 | u64 last_lun, temp_last_lun; | ||
2265 | |||
2266 | /* fetch luns from the first sg element */ | ||
2267 | bfa_ioim_lm_fetch_lun(ioim, (u8 *)(rl->lun), 0, | ||
2268 | (sg_dma_len(sg) / sizeof(struct scsi_lun)) - 1); | ||
2269 | |||
2270 | /* fetch luns from multiple sg elements */ | ||
2271 | scsi_for_each_sg(cmnd, sg, scsi_sg_count(cmnd), sgeid) { | ||
2272 | if (sgeid == 0) { | ||
2273 | prev_sg_len = sg_dma_len(sg); | ||
2274 | prev_rl_data = (struct scsi_lun *) | ||
2275 | phys_to_virt(sg_dma_address(sg)); | ||
2276 | continue; | ||
2277 | } | ||
2278 | |||
2279 | /* if the buf is having more data */ | ||
2280 | lun_across_sg_bytes = prev_sg_len % sizeof(struct scsi_lun); | ||
2281 | if (lun_across_sg_bytes) { | ||
2282 | bfa_trc(ioim->bfa, lun_across_sg_bytes); | ||
2283 | bfa_stats(ioim->itnim, lm_lun_across_sg); | ||
2284 | bytes_from_next_buf = sizeof(struct scsi_lun) - | ||
2285 | lun_across_sg_bytes; | ||
2286 | |||
2287 | /* from next buf take higher bytes */ | ||
2288 | temp_last_lun = *((u64 *) | ||
2289 | phys_to_virt(sg_dma_address(sg))); | ||
2290 | last_lun |= temp_last_lun >> | ||
2291 | (lun_across_sg_bytes * BITS_PER_BYTE); | ||
2292 | |||
2293 | /* from prev buf take higher bytes */ | ||
2294 | temp_last_lun = *((u64 *)(prev_rl_data + | ||
2295 | (prev_sg_len - lun_across_sg_bytes))); | ||
2296 | temp_last_lun >>= bytes_from_next_buf * BITS_PER_BYTE; | ||
2297 | last_lun = last_lun | (temp_last_lun << | ||
2298 | (bytes_from_next_buf * BITS_PER_BYTE)); | ||
2299 | |||
2300 | bfa_ioim_lm_fetch_lun(ioim, (u8 *)&last_lun, 0, 1); | ||
2301 | } else | ||
2302 | bytes_from_next_buf = 0; | ||
2303 | |||
2304 | *pgdlen += sg_dma_len(sg); | ||
2305 | prev_sg_len = sg_dma_len(sg); | ||
2306 | prev_rl_data = (struct scsi_lun *) | ||
2307 | phys_to_virt(sg_dma_address(sg)); | ||
2308 | bfa_ioim_lm_fetch_lun(ioim, (u8 *)prev_rl_data, | ||
2309 | bytes_from_next_buf, | ||
2310 | sg_dma_len(sg) / sizeof(struct scsi_lun)); | ||
2311 | } | ||
2312 | |||
2313 | /* update the report luns data - based on fetched luns */ | ||
2314 | sg = scsi_sglist(cmnd); | ||
2315 | base_rl_data = (struct scsi_lun *)rl->lun; | ||
2316 | base_count = (sg_dma_len(sg) / sizeof(struct scsi_lun)) - 1; | ||
2317 | for (i = 0, j = 0; i < MAX_LUN_MASK_CFG; i++) { | ||
2318 | if (lun_list[i].state == BFA_IOIM_LUN_MASK_FETCHED) { | ||
2319 | base_rl_data[j] = lun_list[i].lun; | ||
2320 | lun_list[i].state = BFA_IOIM_LUN_MASK_ACTIVE; | ||
2321 | j++; | ||
2322 | lun_fetched_cnt++; | ||
2323 | } | ||
2324 | |||
2325 | if (j > base_count) { | ||
2326 | j = 0; | ||
2327 | sg = sg_next(sg); | ||
2328 | base_rl_data = (struct scsi_lun *) | ||
2329 | phys_to_virt(sg_dma_address(sg)); | ||
2330 | base_count = sg_dma_len(sg) / sizeof(struct scsi_lun); | ||
2331 | } | ||
2332 | } | ||
2333 | |||
2334 | bfa_trc(ioim->bfa, lun_fetched_cnt); | ||
2335 | return lun_fetched_cnt; | ||
2336 | } | ||
2337 | |||
2338 | static bfa_boolean_t | ||
2339 | bfa_ioim_lm_proc_inq_data(struct bfa_ioim_s *ioim) | ||
2340 | { | ||
2341 | struct scsi_inquiry_data_s *inq; | ||
2342 | struct scatterlist *sg = scsi_sglist((struct scsi_cmnd *)ioim->dio); | ||
2343 | |||
2344 | ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; | ||
2345 | inq = (struct scsi_inquiry_data_s *)phys_to_virt(sg_dma_address(sg)); | ||
2346 | |||
2347 | bfa_trc(ioim->bfa, inq->device_type); | ||
2348 | inq->peripheral_qual = SCSI_INQ_PQ_NOT_CON; | ||
2349 | return 0; | ||
2350 | } | ||
2351 | |||
2352 | static bfa_boolean_t | ||
2353 | bfa_ioim_lm_proc_rpl_data(struct bfa_ioim_s *ioim) | ||
2354 | { | ||
2355 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio; | ||
2356 | struct scatterlist *sg = scsi_sglist(cmnd); | ||
2357 | struct bfi_ioim_rsp_s *m; | ||
2358 | struct scsi_report_luns_data_s *rl = NULL; | ||
2359 | int lun_count = 0, lun_fetched_cnt = 0; | ||
2360 | u32 residue, pgdlen = 0; | ||
2361 | |||
2362 | ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; | ||
2363 | if (bfa_get_lun_mask_status(ioim->bfa) != BFA_LUNMASK_ENABLED) | ||
2364 | return BFA_TRUE; | ||
2365 | |||
2366 | m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg; | ||
2367 | if (m->scsi_status == SCSI_STATUS_CHECK_CONDITION) | ||
2368 | return BFA_TRUE; | ||
2369 | |||
2370 | pgdlen = sg_dma_len(sg); | ||
2371 | bfa_trc(ioim->bfa, pgdlen); | ||
2372 | rl = (struct scsi_report_luns_data_s *)phys_to_virt(sg_dma_address(sg)); | ||
2373 | lun_count = cpu_to_be32(rl->lun_list_length) / sizeof(struct scsi_lun); | ||
2374 | lun_fetched_cnt = bfa_ioim_lm_update_lun_sg(ioim, &pgdlen, rl); | ||
2375 | |||
2376 | if (lun_count == lun_fetched_cnt) | ||
2377 | return BFA_TRUE; | ||
2378 | |||
2379 | bfa_trc(ioim->bfa, lun_count); | ||
2380 | bfa_trc(ioim->bfa, lun_fetched_cnt); | ||
2381 | bfa_trc(ioim->bfa, be32_to_cpu(rl->lun_list_length)); | ||
2382 | |||
2383 | if (be32_to_cpu(rl->lun_list_length) <= pgdlen) | ||
2384 | rl->lun_list_length = be32_to_cpu(lun_fetched_cnt) * | ||
2385 | sizeof(struct scsi_lun); | ||
2386 | else | ||
2387 | bfa_stats(ioim->itnim, lm_small_buf_addresidue); | ||
2388 | |||
2389 | bfa_trc(ioim->bfa, be32_to_cpu(rl->lun_list_length)); | ||
2390 | bfa_trc(ioim->bfa, be32_to_cpu(m->residue)); | ||
2391 | |||
2392 | residue = be32_to_cpu(m->residue); | ||
2393 | residue += (lun_count - lun_fetched_cnt) * sizeof(struct scsi_lun); | ||
2394 | bfa_stats(ioim->itnim, lm_wire_residue_changed); | ||
2395 | m->residue = be32_to_cpu(residue); | ||
2396 | bfa_trc(ioim->bfa, ioim->nsges); | ||
2397 | return BFA_FALSE; | ||
2398 | } | ||
2085 | 2399 | ||
2086 | static void | 2400 | static void |
2087 | __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete) | 2401 | __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete) |
@@ -2141,6 +2455,105 @@ __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete) | |||
2141 | } | 2455 | } |
2142 | 2456 | ||
2143 | static void | 2457 | static void |
2458 | __bfa_cb_ioim_lm_lun_not_sup(void *cbarg, bfa_boolean_t complete) | ||
2459 | { | ||
2460 | struct bfa_ioim_s *ioim = cbarg; | ||
2461 | int sns_len = 0xD; | ||
2462 | u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio); | ||
2463 | struct scsi_sense_s *snsinfo; | ||
2464 | |||
2465 | if (!complete) { | ||
2466 | bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB); | ||
2467 | return; | ||
2468 | } | ||
2469 | |||
2470 | snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG( | ||
2471 | ioim->fcpim->fcp, ioim->iotag); | ||
2472 | snsinfo->rsp_code = SCSI_SENSE_CUR_ERR; | ||
2473 | snsinfo->add_sense_length = 0xa; | ||
2474 | snsinfo->asc = SCSI_ASC_LUN_NOT_SUPPORTED; | ||
2475 | snsinfo->sense_key = ILLEGAL_REQUEST; | ||
2476 | bfa_trc(ioim->bfa, residue); | ||
2477 | bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK, | ||
2478 | SCSI_STATUS_CHECK_CONDITION, sns_len, | ||
2479 | (u8 *)snsinfo, residue); | ||
2480 | } | ||
2481 | |||
2482 | static void | ||
2483 | __bfa_cb_ioim_lm_rpl_dc(void *cbarg, bfa_boolean_t complete) | ||
2484 | { | ||
2485 | struct bfa_ioim_s *ioim = cbarg; | ||
2486 | int sns_len = 0xD; | ||
2487 | u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio); | ||
2488 | struct scsi_sense_s *snsinfo; | ||
2489 | |||
2490 | if (!complete) { | ||
2491 | bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB); | ||
2492 | return; | ||
2493 | } | ||
2494 | |||
2495 | snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(ioim->fcpim->fcp, | ||
2496 | ioim->iotag); | ||
2497 | snsinfo->rsp_code = SCSI_SENSE_CUR_ERR; | ||
2498 | snsinfo->sense_key = SCSI_MP_IEC_UNIT_ATTN; | ||
2499 | snsinfo->asc = SCSI_ASC_TOCC; | ||
2500 | snsinfo->add_sense_length = 0x6; | ||
2501 | snsinfo->ascq = SCSI_ASCQ_RL_DATA_CHANGED; | ||
2502 | bfa_trc(ioim->bfa, residue); | ||
2503 | bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK, | ||
2504 | SCSI_STATUS_CHECK_CONDITION, sns_len, | ||
2505 | (u8 *)snsinfo, residue); | ||
2506 | } | ||
2507 | |||
2508 | static void | ||
2509 | __bfa_cb_ioim_lm_lun_not_rdy(void *cbarg, bfa_boolean_t complete) | ||
2510 | { | ||
2511 | struct bfa_ioim_s *ioim = cbarg; | ||
2512 | int sns_len = 0xD; | ||
2513 | u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio); | ||
2514 | struct scsi_sense_s *snsinfo; | ||
2515 | |||
2516 | if (!complete) { | ||
2517 | bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB); | ||
2518 | return; | ||
2519 | } | ||
2520 | |||
2521 | snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG( | ||
2522 | ioim->fcpim->fcp, ioim->iotag); | ||
2523 | snsinfo->rsp_code = SCSI_SENSE_CUR_ERR; | ||
2524 | snsinfo->add_sense_length = 0xa; | ||
2525 | snsinfo->sense_key = NOT_READY; | ||
2526 | snsinfo->asc = SCSI_ASC_LUN_NOT_READY; | ||
2527 | snsinfo->ascq = SCSI_ASCQ_MAN_INTR_REQ; | ||
2528 | bfa_trc(ioim->bfa, residue); | ||
2529 | bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK, | ||
2530 | SCSI_STATUS_CHECK_CONDITION, sns_len, | ||
2531 | (u8 *)snsinfo, residue); | ||
2532 | } | ||
2533 | |||
2534 | void | ||
2535 | bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, wwn_t rp_wwn, | ||
2536 | u16 rp_tag, u8 lp_tag) | ||
2537 | { | ||
2538 | struct bfa_lun_mask_s *lun_list; | ||
2539 | u8 i; | ||
2540 | |||
2541 | if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) | ||
2542 | return; | ||
2543 | |||
2544 | lun_list = bfa_get_lun_mask_list(bfa); | ||
2545 | for (i = 0; i < MAX_LUN_MASK_CFG; i++) { | ||
2546 | if (lun_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE) { | ||
2547 | if ((lun_list[i].lp_wwn == lp_wwn) && | ||
2548 | (lun_list[i].rp_wwn == rp_wwn)) { | ||
2549 | lun_list[i].rp_tag = rp_tag; | ||
2550 | lun_list[i].lp_tag = lp_tag; | ||
2551 | } | ||
2552 | } | ||
2553 | } | ||
2554 | } | ||
2555 | |||
2556 | static void | ||
2144 | __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete) | 2557 | __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete) |
2145 | { | 2558 | { |
2146 | struct bfa_ioim_s *ioim = cbarg; | 2559 | struct bfa_ioim_s *ioim = cbarg; |
@@ -2150,6 +2563,7 @@ __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete) | |||
2150 | return; | 2563 | return; |
2151 | } | 2564 | } |
2152 | 2565 | ||
2566 | ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; | ||
2153 | bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED, | 2567 | bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED, |
2154 | 0, 0, NULL, 0); | 2568 | 0, 0, NULL, 0); |
2155 | } | 2569 | } |
@@ -2165,6 +2579,7 @@ __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete) | |||
2165 | return; | 2579 | return; |
2166 | } | 2580 | } |
2167 | 2581 | ||
2582 | ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; | ||
2168 | bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV, | 2583 | bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV, |
2169 | 0, 0, NULL, 0); | 2584 | 0, 0, NULL, 0); |
2170 | } | 2585 | } |
@@ -2179,6 +2594,7 @@ __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete) | |||
2179 | return; | 2594 | return; |
2180 | } | 2595 | } |
2181 | 2596 | ||
2597 | ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; | ||
2182 | bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio); | 2598 | bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio); |
2183 | } | 2599 | } |
2184 | 2600 | ||
@@ -2522,6 +2938,7 @@ bfa_ioim_attach(struct bfa_fcpim_s *fcpim) | |||
2522 | ioim->bfa = fcpim->bfa; | 2938 | ioim->bfa = fcpim->bfa; |
2523 | ioim->fcpim = fcpim; | 2939 | ioim->fcpim = fcpim; |
2524 | ioim->iosp = iosp; | 2940 | ioim->iosp = iosp; |
2941 | ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; | ||
2525 | INIT_LIST_HEAD(&ioim->sgpg_q); | 2942 | INIT_LIST_HEAD(&ioim->sgpg_q); |
2526 | bfa_reqq_winit(&ioim->iosp->reqq_wait, | 2943 | bfa_reqq_winit(&ioim->iosp->reqq_wait, |
2527 | bfa_ioim_qresume, ioim); | 2944 | bfa_ioim_qresume, ioim); |
@@ -2559,6 +2976,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | |||
2559 | evt = BFA_IOIM_SM_DONE; | 2976 | evt = BFA_IOIM_SM_DONE; |
2560 | else | 2977 | else |
2561 | evt = BFA_IOIM_SM_COMP; | 2978 | evt = BFA_IOIM_SM_COMP; |
2979 | ioim->proc_rsp_data(ioim); | ||
2562 | break; | 2980 | break; |
2563 | 2981 | ||
2564 | case BFI_IOIM_STS_TIMEDOUT: | 2982 | case BFI_IOIM_STS_TIMEDOUT: |
@@ -2594,6 +3012,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | |||
2594 | if (rsp->abort_tag != ioim->abort_tag) { | 3012 | if (rsp->abort_tag != ioim->abort_tag) { |
2595 | bfa_trc(ioim->bfa, rsp->abort_tag); | 3013 | bfa_trc(ioim->bfa, rsp->abort_tag); |
2596 | bfa_trc(ioim->bfa, ioim->abort_tag); | 3014 | bfa_trc(ioim->bfa, ioim->abort_tag); |
3015 | ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; | ||
2597 | return; | 3016 | return; |
2598 | } | 3017 | } |
2599 | 3018 | ||
@@ -2612,6 +3031,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | |||
2612 | WARN_ON(1); | 3031 | WARN_ON(1); |
2613 | } | 3032 | } |
2614 | 3033 | ||
3034 | ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; | ||
2615 | bfa_sm_send_event(ioim, evt); | 3035 | bfa_sm_send_event(ioim, evt); |
2616 | } | 3036 | } |
2617 | 3037 | ||
@@ -2629,7 +3049,16 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | |||
2629 | WARN_ON(BFA_IOIM_TAG_2_ID(ioim->iotag) != iotag); | 3049 | WARN_ON(BFA_IOIM_TAG_2_ID(ioim->iotag) != iotag); |
2630 | 3050 | ||
2631 | bfa_ioim_cb_profile_comp(fcpim, ioim); | 3051 | bfa_ioim_cb_profile_comp(fcpim, ioim); |
2632 | bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD); | 3052 | |
3053 | if (bfa_get_lun_mask_status(bfa) != BFA_LUNMASK_ENABLED) { | ||
3054 | bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD); | ||
3055 | return; | ||
3056 | } | ||
3057 | |||
3058 | if (ioim->proc_rsp_data(ioim) == BFA_TRUE) | ||
3059 | bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD); | ||
3060 | else | ||
3061 | bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP); | ||
2633 | } | 3062 | } |
2634 | 3063 | ||
2635 | /* | 3064 | /* |
@@ -2741,6 +3170,35 @@ bfa_ioim_free(struct bfa_ioim_s *ioim) | |||
2741 | void | 3170 | void |
2742 | bfa_ioim_start(struct bfa_ioim_s *ioim) | 3171 | bfa_ioim_start(struct bfa_ioim_s *ioim) |
2743 | { | 3172 | { |
3173 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio; | ||
3174 | struct bfa_lps_s *lps; | ||
3175 | enum bfa_ioim_lm_status status; | ||
3176 | struct scsi_lun scsilun; | ||
3177 | |||
3178 | if (bfa_get_lun_mask_status(ioim->bfa) == BFA_LUNMASK_ENABLED) { | ||
3179 | lps = BFA_IOIM_TO_LPS(ioim); | ||
3180 | int_to_scsilun(cmnd->device->lun, &scsilun); | ||
3181 | status = bfa_ioim_lm_check(ioim, lps, | ||
3182 | ioim->itnim->rport, scsilun); | ||
3183 | if (status == BFA_IOIM_LM_LUN_NOT_RDY) { | ||
3184 | bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_LUN_NOT_RDY); | ||
3185 | bfa_stats(ioim->itnim, lm_lun_not_rdy); | ||
3186 | return; | ||
3187 | } | ||
3188 | |||
3189 | if (status == BFA_IOIM_LM_LUN_NOT_SUP) { | ||
3190 | bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_LUN_NOT_SUP); | ||
3191 | bfa_stats(ioim->itnim, lm_lun_not_sup); | ||
3192 | return; | ||
3193 | } | ||
3194 | |||
3195 | if (status == BFA_IOIM_LM_RPL_DATA_CHANGED) { | ||
3196 | bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_RPL_DC); | ||
3197 | bfa_stats(ioim->itnim, lm_rpl_data_changed); | ||
3198 | return; | ||
3199 | } | ||
3200 | } | ||
3201 | |||
2744 | bfa_ioim_cb_profile_start(ioim->fcpim, ioim); | 3202 | bfa_ioim_cb_profile_start(ioim->fcpim, ioim); |
2745 | 3203 | ||
2746 | /* | 3204 | /* |
@@ -3484,6 +3942,13 @@ bfa_fcp_detach(struct bfa_s *bfa) | |||
3484 | static void | 3942 | static void |
3485 | bfa_fcp_start(struct bfa_s *bfa) | 3943 | bfa_fcp_start(struct bfa_s *bfa) |
3486 | { | 3944 | { |
3945 | struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa); | ||
3946 | |||
3947 | /* | ||
3948 | * bfa_init() with flash read is complete. now invalidate the stale | ||
3949 | * content of lun mask like unit attention, rp tag and lp tag. | ||
3950 | */ | ||
3951 | bfa_ioim_lm_init(fcp->bfa); | ||
3487 | } | 3952 | } |
3488 | 3953 | ||
3489 | static void | 3954 | static void |
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h index c224987b9c30..99fc913929b6 100644 --- a/drivers/scsi/bfa/bfa_fcpim.h +++ b/drivers/scsi/bfa/bfa_fcpim.h | |||
@@ -110,6 +110,7 @@ struct bfad_ioim_s; | |||
110 | struct bfad_tskim_s; | 110 | struct bfad_tskim_s; |
111 | 111 | ||
112 | typedef void (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim); | 112 | typedef void (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim); |
113 | typedef bfa_boolean_t (*bfa_ioim_lm_proc_rsp_data_t) (struct bfa_ioim_s *ioim); | ||
113 | 114 | ||
114 | struct bfa_fcpim_s { | 115 | struct bfa_fcpim_s { |
115 | struct bfa_s *bfa; | 116 | struct bfa_s *bfa; |
@@ -123,7 +124,7 @@ struct bfa_fcpim_s { | |||
123 | u32 path_tov; | 124 | u32 path_tov; |
124 | u16 q_depth; | 125 | u16 q_depth; |
125 | u8 reqq; /* Request queue to be used */ | 126 | u8 reqq; /* Request queue to be used */ |
126 | u8 rsvd; | 127 | u8 lun_masking_pending; |
127 | struct list_head itnim_q; /* queue of active itnim */ | 128 | struct list_head itnim_q; /* queue of active itnim */ |
128 | struct list_head ioim_resfree_q; /* IOs waiting for f/w */ | 129 | struct list_head ioim_resfree_q; /* IOs waiting for f/w */ |
129 | struct list_head ioim_comp_q; /* IO global comp Q */ | 130 | struct list_head ioim_comp_q; /* IO global comp Q */ |
@@ -178,7 +179,9 @@ struct bfa_ioim_s { | |||
178 | bfa_cb_cbfn_t io_cbfn; /* IO completion handler */ | 179 | bfa_cb_cbfn_t io_cbfn; /* IO completion handler */ |
179 | struct bfa_ioim_sp_s *iosp; /* slow-path IO handling */ | 180 | struct bfa_ioim_sp_s *iosp; /* slow-path IO handling */ |
180 | u8 reqq; /* Request queue for I/O */ | 181 | u8 reqq; /* Request queue for I/O */ |
182 | u8 mode; /* IO is passthrough or not */ | ||
181 | u64 start_time; /* IO's Profile start val */ | 183 | u64 start_time; /* IO's Profile start val */ |
184 | bfa_ioim_lm_proc_rsp_data_t proc_rsp_data; /* RSP data adjust */ | ||
182 | }; | 185 | }; |
183 | 186 | ||
184 | struct bfa_ioim_sp_s { | 187 | struct bfa_ioim_sp_s { |
@@ -258,6 +261,10 @@ struct bfa_itnim_s { | |||
258 | (__ioim)->iotag |= k << BFA_IOIM_RETRY_TAG_OFFSET; \ | 261 | (__ioim)->iotag |= k << BFA_IOIM_RETRY_TAG_OFFSET; \ |
259 | } while (0) | 262 | } while (0) |
260 | 263 | ||
264 | #define BFA_IOIM_TO_LPS(__ioim) \ | ||
265 | BFA_LPS_FROM_TAG(BFA_LPS_MOD(__ioim->bfa), \ | ||
266 | __ioim->itnim->rport->rport_info.lp_tag) | ||
267 | |||
261 | static inline bfa_boolean_t | 268 | static inline bfa_boolean_t |
262 | bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim) | 269 | bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim) |
263 | { | 270 | { |
@@ -407,4 +414,7 @@ void bfa_tskim_start(struct bfa_tskim_s *tskim, | |||
407 | void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk, | 414 | void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk, |
408 | enum bfi_tskim_status tsk_status); | 415 | enum bfi_tskim_status tsk_status); |
409 | 416 | ||
417 | void bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, | ||
418 | wwn_t rp_wwn, u16 rp_tag, u8 lp_tag); | ||
419 | |||
410 | #endif /* __BFA_FCPIM_H__ */ | 420 | #endif /* __BFA_FCPIM_H__ */ |
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index d0ed4dd6f35a..aa8a0eaf91f9 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c | |||
@@ -4677,6 +4677,7 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | |||
4677 | rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle); | 4677 | rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle); |
4678 | rp->fw_handle = msg.create_rsp->fw_handle; | 4678 | rp->fw_handle = msg.create_rsp->fw_handle; |
4679 | rp->qos_attr = msg.create_rsp->qos_attr; | 4679 | rp->qos_attr = msg.create_rsp->qos_attr; |
4680 | bfa_rport_set_lunmask(bfa, rp); | ||
4680 | WARN_ON(msg.create_rsp->status != BFA_STATUS_OK); | 4681 | WARN_ON(msg.create_rsp->status != BFA_STATUS_OK); |
4681 | bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP); | 4682 | bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP); |
4682 | break; | 4683 | break; |
@@ -4684,6 +4685,7 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | |||
4684 | case BFI_RPORT_I2H_DELETE_RSP: | 4685 | case BFI_RPORT_I2H_DELETE_RSP: |
4685 | rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle); | 4686 | rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle); |
4686 | WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK); | 4687 | WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK); |
4688 | bfa_rport_unset_lunmask(bfa, rp); | ||
4687 | bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP); | 4689 | bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP); |
4688 | break; | 4690 | break; |
4689 | 4691 | ||
@@ -4764,6 +4766,37 @@ bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed) | |||
4764 | bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED); | 4766 | bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED); |
4765 | } | 4767 | } |
4766 | 4768 | ||
4769 | /* Set Rport LUN Mask */ | ||
4770 | void | ||
4771 | bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp) | ||
4772 | { | ||
4773 | struct bfa_lps_mod_s *lps_mod = BFA_LPS_MOD(bfa); | ||
4774 | wwn_t lp_wwn, rp_wwn; | ||
4775 | u8 lp_tag = (u8)rp->rport_info.lp_tag; | ||
4776 | |||
4777 | rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn; | ||
4778 | lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn; | ||
4779 | |||
4780 | BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask = | ||
4781 | rp->lun_mask = BFA_TRUE; | ||
4782 | bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn, rp->rport_tag, lp_tag); | ||
4783 | } | ||
4784 | |||
4785 | /* Unset Rport LUN mask */ | ||
4786 | void | ||
4787 | bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp) | ||
4788 | { | ||
4789 | struct bfa_lps_mod_s *lps_mod = BFA_LPS_MOD(bfa); | ||
4790 | wwn_t lp_wwn, rp_wwn; | ||
4791 | |||
4792 | rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn; | ||
4793 | lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn; | ||
4794 | |||
4795 | BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask = | ||
4796 | rp->lun_mask = BFA_FALSE; | ||
4797 | bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn, | ||
4798 | BFA_RPORT_TAG_INVALID, BFA_LP_TAG_INVALID); | ||
4799 | } | ||
4767 | 4800 | ||
4768 | /* | 4801 | /* |
4769 | * SGPG related functions | 4802 | * SGPG related functions |
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h index 01db3520070f..95adb86d3769 100644 --- a/drivers/scsi/bfa/bfa_svc.h +++ b/drivers/scsi/bfa/bfa_svc.h | |||
@@ -297,6 +297,7 @@ struct bfa_rport_s { | |||
297 | void *rport_drv; /* fcs/driver rport object */ | 297 | void *rport_drv; /* fcs/driver rport object */ |
298 | u16 fw_handle; /* firmware rport handle */ | 298 | u16 fw_handle; /* firmware rport handle */ |
299 | u16 rport_tag; /* BFA rport tag */ | 299 | u16 rport_tag; /* BFA rport tag */ |
300 | u8 lun_mask; /* LUN mask flag */ | ||
300 | struct bfa_rport_info_s rport_info; /* rport info from fcs/driver */ | 301 | struct bfa_rport_info_s rport_info; /* rport info from fcs/driver */ |
301 | struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ | 302 | struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ |
302 | struct bfa_cb_qe_s hcb_qe; /* BFA callback qelem */ | 303 | struct bfa_cb_qe_s hcb_qe; /* BFA callback qelem */ |
@@ -404,6 +405,7 @@ struct bfa_lps_s { | |||
404 | u8 bb_scn; /* local BB_SCN */ | 405 | u8 bb_scn; /* local BB_SCN */ |
405 | u8 lsrjt_rsn; /* LSRJT reason */ | 406 | u8 lsrjt_rsn; /* LSRJT reason */ |
406 | u8 lsrjt_expl; /* LSRJT explanation */ | 407 | u8 lsrjt_expl; /* LSRJT explanation */ |
408 | u8 lun_mask; /* LUN mask flag */ | ||
407 | wwn_t pwwn; /* port wwn of lport */ | 409 | wwn_t pwwn; /* port wwn of lport */ |
408 | wwn_t nwwn; /* node wwn of lport */ | 410 | wwn_t nwwn; /* node wwn of lport */ |
409 | wwn_t pr_pwwn; /* port wwn of lport peer */ | 411 | wwn_t pr_pwwn; /* port wwn of lport peer */ |
@@ -574,6 +576,19 @@ void bfa_cb_rport_qos_scn_prio(void *rport, | |||
574 | struct bfa_rport_qos_attr_s new_qos_attr); | 576 | struct bfa_rport_qos_attr_s new_qos_attr); |
575 | 577 | ||
576 | /* | 578 | /* |
579 | * Rport LUN masking related | ||
580 | */ | ||
581 | #define BFA_RPORT_TAG_INVALID 0xffff | ||
582 | #define BFA_LP_TAG_INVALID 0xff | ||
583 | void bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp); | ||
584 | void bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp); | ||
585 | bfa_boolean_t bfa_rport_lunmask_active(struct bfa_rport_s *rp); | ||
586 | wwn_t bfa_rport_get_pwwn(struct bfa_s *bfa, struct bfa_rport_s *rp); | ||
587 | struct bfa_rport_s *bfa_rport_get_by_wwn(struct bfa_s *bfa, u16 vf_id, | ||
588 | wwn_t *lpwwn, wwn_t rpwwn); | ||
589 | void *bfa_cb_get_rp_by_wwn(void *arg, u16 vf_id, wwn_t *lpwwn, wwn_t rpwwn); | ||
590 | |||
591 | /* | ||
577 | * bfa fcxp API functions | 592 | * bfa fcxp API functions |
578 | */ | 593 | */ |
579 | struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa, | 594 | struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa, |