diff options
-rw-r--r-- | drivers/scsi/bfa/bfa_fcpim.c | 140 |
1 files changed, 59 insertions, 81 deletions
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index d6aea5d4425f..c07ee42345bc 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c | |||
@@ -218,8 +218,7 @@ static void bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim, | |||
218 | * forward declaration for BFA IOIM functions | 218 | * forward declaration for BFA IOIM functions |
219 | */ | 219 | */ |
220 | static bfa_boolean_t bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim); | 220 | static bfa_boolean_t bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim); |
221 | static bfa_boolean_t bfa_ioim_sge_setup(struct bfa_ioim_s *ioim); | 221 | static bfa_boolean_t bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim); |
222 | static void bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim); | ||
223 | static bfa_boolean_t bfa_ioim_send_abort(struct bfa_ioim_s *ioim); | 222 | static bfa_boolean_t bfa_ioim_send_abort(struct bfa_ioim_s *ioim); |
224 | static void bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim); | 223 | static void bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim); |
225 | static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete); | 224 | static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete); |
@@ -1621,7 +1620,7 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | |||
1621 | } | 1620 | } |
1622 | 1621 | ||
1623 | if (ioim->nsges > BFI_SGE_INLINE) { | 1622 | if (ioim->nsges > BFI_SGE_INLINE) { |
1624 | if (!bfa_ioim_sge_setup(ioim)) { | 1623 | if (!bfa_ioim_sgpg_alloc(ioim)) { |
1625 | bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc); | 1624 | bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc); |
1626 | return; | 1625 | return; |
1627 | } | 1626 | } |
@@ -2304,7 +2303,7 @@ bfa_ioim_sgpg_alloced(void *cbarg) | |||
2304 | 2303 | ||
2305 | ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges); | 2304 | ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges); |
2306 | list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q); | 2305 | list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q); |
2307 | bfa_ioim_sgpg_setup(ioim); | 2306 | ioim->sgpg = bfa_q_first(&ioim->sgpg_q); |
2308 | bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED); | 2307 | bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED); |
2309 | } | 2308 | } |
2310 | 2309 | ||
@@ -2317,12 +2316,14 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) | |||
2317 | struct bfa_itnim_s *itnim = ioim->itnim; | 2316 | struct bfa_itnim_s *itnim = ioim->itnim; |
2318 | struct bfi_ioim_req_s *m; | 2317 | struct bfi_ioim_req_s *m; |
2319 | static struct fcp_cmnd_s cmnd_z0 = { 0 }; | 2318 | static struct fcp_cmnd_s cmnd_z0 = { 0 }; |
2320 | struct bfi_sge_s *sge; | 2319 | struct bfi_sge_s *sge, *sgpge; |
2321 | u32 pgdlen = 0; | 2320 | u32 pgdlen = 0; |
2322 | u32 fcp_dl; | 2321 | u32 fcp_dl; |
2323 | u64 addr; | 2322 | u64 addr; |
2324 | struct scatterlist *sg; | 2323 | struct scatterlist *sg; |
2324 | struct bfa_sgpg_s *sgpg; | ||
2325 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio; | 2325 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio; |
2326 | u32 i, sge_id, pgcumsz; | ||
2326 | 2327 | ||
2327 | /* | 2328 | /* |
2328 | * check for room in queue to send request now | 2329 | * check for room in queue to send request now |
@@ -2342,20 +2343,59 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) | |||
2342 | m->rport_hdl = ioim->itnim->rport->fw_handle; | 2343 | m->rport_hdl = ioim->itnim->rport->fw_handle; |
2343 | m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio); | 2344 | m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio); |
2344 | 2345 | ||
2345 | /* | ||
2346 | * build inline IO SG element here | ||
2347 | */ | ||
2348 | sge = &m->sges[0]; | 2346 | sge = &m->sges[0]; |
2349 | if (ioim->nsges) { | 2347 | sgpg = ioim->sgpg; |
2350 | sg = (struct scatterlist *)scsi_sglist(cmnd); | 2348 | sge_id = 0; |
2351 | addr = bfa_os_sgaddr(sg_dma_address(sg)); | 2349 | sgpge = NULL; |
2352 | sge->sga = *(union bfi_addr_u *) &addr; | 2350 | pgcumsz = 0; |
2353 | pgdlen = sg_dma_len(sg); | 2351 | scsi_for_each_sg(cmnd, sg, ioim->nsges, i) { |
2354 | sge->sg_len = pgdlen; | 2352 | if (i == 0) { |
2355 | sge->flags = (ioim->nsges > BFI_SGE_INLINE) ? | 2353 | /* build inline IO SG element */ |
2354 | addr = bfa_os_sgaddr(sg_dma_address(sg)); | ||
2355 | sge->sga = *(union bfi_addr_u *) &addr; | ||
2356 | pgdlen = sg_dma_len(sg); | ||
2357 | sge->sg_len = pgdlen; | ||
2358 | sge->flags = (ioim->nsges > BFI_SGE_INLINE) ? | ||
2356 | BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST; | 2359 | BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST; |
2357 | bfa_sge_to_be(sge); | 2360 | bfa_sge_to_be(sge); |
2358 | sge++; | 2361 | sge++; |
2362 | } else { | ||
2363 | if (sge_id == 0) | ||
2364 | sgpge = sgpg->sgpg->sges; | ||
2365 | |||
2366 | addr = bfa_os_sgaddr(sg_dma_address(sg)); | ||
2367 | sgpge->sga = *(union bfi_addr_u *) &addr; | ||
2368 | sgpge->sg_len = sg_dma_len(sg); | ||
2369 | pgcumsz += sgpge->sg_len; | ||
2370 | |||
2371 | /* set flags */ | ||
2372 | if (i < (ioim->nsges - 1) && | ||
2373 | sge_id < (BFI_SGPG_DATA_SGES - 1)) | ||
2374 | sgpge->flags = BFI_SGE_DATA; | ||
2375 | else if (i < (ioim->nsges - 1)) | ||
2376 | sgpge->flags = BFI_SGE_DATA_CPL; | ||
2377 | else | ||
2378 | sgpge->flags = BFI_SGE_DATA_LAST; | ||
2379 | |||
2380 | bfa_sge_to_le(sgpge); | ||
2381 | |||
2382 | sgpge++; | ||
2383 | if (i == (ioim->nsges - 1)) { | ||
2384 | sgpge->flags = BFI_SGE_PGDLEN; | ||
2385 | sgpge->sga.a32.addr_lo = 0; | ||
2386 | sgpge->sga.a32.addr_hi = 0; | ||
2387 | sgpge->sg_len = pgcumsz; | ||
2388 | bfa_sge_to_le(sgpge); | ||
2389 | } else if (++sge_id == BFI_SGPG_DATA_SGES) { | ||
2390 | sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg); | ||
2391 | sgpge->flags = BFI_SGE_LINK; | ||
2392 | sgpge->sga = sgpg->sgpg_pa; | ||
2393 | sgpge->sg_len = pgcumsz; | ||
2394 | bfa_sge_to_le(sgpge); | ||
2395 | sge_id = 0; | ||
2396 | pgcumsz = 0; | ||
2397 | } | ||
2398 | } | ||
2359 | } | 2399 | } |
2360 | 2400 | ||
2361 | if (ioim->nsges > BFI_SGE_INLINE) { | 2401 | if (ioim->nsges > BFI_SGE_INLINE) { |
@@ -2414,7 +2454,7 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) | |||
2414 | * at queuing time. | 2454 | * at queuing time. |
2415 | */ | 2455 | */ |
2416 | static bfa_boolean_t | 2456 | static bfa_boolean_t |
2417 | bfa_ioim_sge_setup(struct bfa_ioim_s *ioim) | 2457 | bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim) |
2418 | { | 2458 | { |
2419 | u16 nsgpgs; | 2459 | u16 nsgpgs; |
2420 | 2460 | ||
@@ -2434,73 +2474,11 @@ bfa_ioim_sge_setup(struct bfa_ioim_s *ioim) | |||
2434 | } | 2474 | } |
2435 | 2475 | ||
2436 | ioim->nsgpgs = nsgpgs; | 2476 | ioim->nsgpgs = nsgpgs; |
2437 | bfa_ioim_sgpg_setup(ioim); | 2477 | ioim->sgpg = bfa_q_first(&ioim->sgpg_q); |
2438 | 2478 | ||
2439 | return BFA_TRUE; | 2479 | return BFA_TRUE; |
2440 | } | 2480 | } |
2441 | 2481 | ||
2442 | static void | ||
2443 | bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim) | ||
2444 | { | ||
2445 | int sgeid, nsges, i; | ||
2446 | struct bfi_sge_s *sge; | ||
2447 | struct bfa_sgpg_s *sgpg; | ||
2448 | u32 pgcumsz; | ||
2449 | u64 addr; | ||
2450 | struct scatterlist *sg; | ||
2451 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio; | ||
2452 | |||
2453 | sgeid = BFI_SGE_INLINE; | ||
2454 | ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q); | ||
2455 | |||
2456 | sg = scsi_sglist(cmnd); | ||
2457 | sg = sg_next(sg); | ||
2458 | |||
2459 | do { | ||
2460 | sge = sgpg->sgpg->sges; | ||
2461 | nsges = ioim->nsges - sgeid; | ||
2462 | if (nsges > BFI_SGPG_DATA_SGES) | ||
2463 | nsges = BFI_SGPG_DATA_SGES; | ||
2464 | |||
2465 | pgcumsz = 0; | ||
2466 | for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) { | ||
2467 | addr = bfa_os_sgaddr(sg_dma_address(sg)); | ||
2468 | sge->sga = *(union bfi_addr_u *) &addr; | ||
2469 | sge->sg_len = sg_dma_len(sg); | ||
2470 | pgcumsz += sge->sg_len; | ||
2471 | |||
2472 | /* | ||
2473 | * set flags | ||
2474 | */ | ||
2475 | if (i < (nsges - 1)) | ||
2476 | sge->flags = BFI_SGE_DATA; | ||
2477 | else if (sgeid < (ioim->nsges - 1)) | ||
2478 | sge->flags = BFI_SGE_DATA_CPL; | ||
2479 | else | ||
2480 | sge->flags = BFI_SGE_DATA_LAST; | ||
2481 | |||
2482 | bfa_sge_to_le(sge); | ||
2483 | } | ||
2484 | |||
2485 | sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg); | ||
2486 | |||
2487 | /* | ||
2488 | * set the link element of each page | ||
2489 | */ | ||
2490 | if (sgeid == ioim->nsges) { | ||
2491 | sge->flags = BFI_SGE_PGDLEN; | ||
2492 | sge->sga.a32.addr_lo = 0; | ||
2493 | sge->sga.a32.addr_hi = 0; | ||
2494 | } else { | ||
2495 | sge->flags = BFI_SGE_LINK; | ||
2496 | sge->sga = sgpg->sgpg_pa; | ||
2497 | } | ||
2498 | sge->sg_len = pgcumsz; | ||
2499 | |||
2500 | bfa_sge_to_le(sge); | ||
2501 | } while (sgeid < ioim->nsges); | ||
2502 | } | ||
2503 | |||
2504 | /* | 2482 | /* |
2505 | * Send I/O abort request to firmware. | 2483 | * Send I/O abort request to firmware. |
2506 | */ | 2484 | */ |