diff options
author | Krishna Gudipati <kgudipat@brocade.com> | 2011-07-20 20:04:03 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-27 06:55:03 -0400 |
commit | 83763d591b343b07331cebe86715205230c568b1 (patch) | |
tree | 3d81bae3ca6ddcee24415001b1dd8ed2d27e3599 /drivers/scsi/bfa/bfa_fcpim.c | |
parent | 45c5dc1d3f42d4f54a5ab5f45ee55f0ffe1099f1 (diff) |
[SCSI] bfa: Introduced initiator based lun masking feature.
- Added support to enable initiator based lun masking.
- Initiator based Lun masking works similar to zoning where
initiator port is allowed to see only those LUNs which are
configured to be seen.
Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bfa/bfa_fcpim.c')
-rw-r--r-- | drivers/scsi/bfa/bfa_fcpim.c | 469 |
1 files changed, 467 insertions, 2 deletions
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 |