aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.c140
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 */
220static bfa_boolean_t bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim); 220static bfa_boolean_t bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);
221static bfa_boolean_t bfa_ioim_sge_setup(struct bfa_ioim_s *ioim); 221static bfa_boolean_t bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim);
222static void bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim);
223static bfa_boolean_t bfa_ioim_send_abort(struct bfa_ioim_s *ioim); 222static bfa_boolean_t bfa_ioim_send_abort(struct bfa_ioim_s *ioim);
224static void bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim); 223static void bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);
225static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete); 224static 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 */
2416static bfa_boolean_t 2456static bfa_boolean_t
2417bfa_ioim_sge_setup(struct bfa_ioim_s *ioim) 2457bfa_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
2442static void
2443bfa_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 */