Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

RDMA/irdma: CQ size and shadow update changes for GEN3

CQ shadow area should not be updated at the end of a page (once every
64th CQ entry), except when CQ has no more CQEs. SW must also increase
the requested CQ size by 1 and make sure the CQ is not exactly one page
in size. This is to address a quirk in the hardware.

Signed-off-by: Jay Bhat <jay.bhat@intel.com>
Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
Link: https://patch.msgid.link/20251031021726.1003-4-tatyana.e.nikolova@intel.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>

authored by

Jay Bhat and committed by
Leon Romanovsky
0a192745 cd84d800

+56 -40
-1
drivers/infiniband/hw/irdma/main.h
··· 564 564 void (*callback_fcn)(struct irdma_cqp_request *cqp_request), 565 565 void *cb_param); 566 566 void irdma_gsi_ud_qp_ah_cb(struct irdma_cqp_request *cqp_request); 567 - bool irdma_cq_empty(struct irdma_cq *iwcq); 568 567 int irdma_inetaddr_event(struct notifier_block *notifier, unsigned long event, 569 568 void *ptr); 570 569 int irdma_inet6addr_event(struct notifier_block *notifier, unsigned long event,
+24 -2
drivers/infiniband/hw/irdma/uk.c
··· 1138 1138 } 1139 1139 1140 1140 /** 1141 + * irdma_uk_cq_empty - Check if CQ is empty 1142 + * @cq: hw cq 1143 + */ 1144 + bool irdma_uk_cq_empty(struct irdma_cq_uk *cq) 1145 + { 1146 + __le64 *cqe; 1147 + u8 polarity; 1148 + u64 qword3; 1149 + 1150 + if (cq->avoid_mem_cflct) 1151 + cqe = IRDMA_GET_CURRENT_EXTENDED_CQ_ELEM(cq); 1152 + else 1153 + cqe = IRDMA_GET_CURRENT_CQ_ELEM(cq); 1154 + 1155 + get_64bit_val(cqe, 24, &qword3); 1156 + polarity = (u8)FIELD_GET(IRDMA_CQ_VALID, qword3); 1157 + 1158 + return polarity != cq->polarity; 1159 + } 1160 + 1161 + /** 1141 1162 * irdma_uk_cq_poll_cmpl - get cq completion info 1142 1163 * @cq: hw cq 1143 1164 * @info: cq poll information returned ··· 1446 1425 IRDMA_RING_MOVE_TAIL(cq->cq_ring); 1447 1426 if (!cq->avoid_mem_cflct && ext_valid) 1448 1427 IRDMA_RING_MOVE_TAIL(cq->cq_ring); 1449 - set_64bit_val(cq->shadow_area, 0, 1450 - IRDMA_RING_CURRENT_HEAD(cq->cq_ring)); 1428 + if (IRDMA_RING_CURRENT_HEAD(cq->cq_ring) & 0x3F || irdma_uk_cq_empty(cq)) 1429 + set_64bit_val(cq->shadow_area, 0, 1430 + IRDMA_RING_CURRENT_HEAD(cq->cq_ring)); 1451 1431 } else { 1452 1432 qword3 &= ~IRDMA_CQ_WQEIDX; 1453 1433 qword3 |= FIELD_PREP(IRDMA_CQ_WQEIDX, pring->tail);
+1
drivers/infiniband/hw/irdma/user.h
··· 429 429 struct irdma_bind_window *op_info); 430 430 }; 431 431 432 + bool irdma_uk_cq_empty(struct irdma_cq_uk *cq); 432 433 int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, 433 434 struct irdma_cq_poll_info *info); 434 435 void irdma_uk_cq_request_notification(struct irdma_cq_uk *cq,
+18 -34
drivers/infiniband/hw/irdma/utils.c
··· 2353 2353 iwqp->ibqp.event_handler(&ibevent, iwqp->ibqp.qp_context); 2354 2354 } 2355 2355 2356 - bool irdma_cq_empty(struct irdma_cq *iwcq) 2357 - { 2358 - struct irdma_cq_uk *ukcq; 2359 - u64 qword3; 2360 - __le64 *cqe; 2361 - u8 polarity; 2362 - 2363 - ukcq = &iwcq->sc_cq.cq_uk; 2364 - if (ukcq->avoid_mem_cflct) 2365 - cqe = IRDMA_GET_CURRENT_EXTENDED_CQ_ELEM(ukcq); 2366 - else 2367 - cqe = IRDMA_GET_CURRENT_CQ_ELEM(ukcq); 2368 - get_64bit_val(cqe, 24, &qword3); 2369 - polarity = (u8)FIELD_GET(IRDMA_CQ_VALID, qword3); 2370 - 2371 - return polarity != ukcq->polarity; 2372 - } 2373 - 2374 2356 void irdma_remove_cmpls_list(struct irdma_cq *iwcq) 2375 2357 { 2376 2358 struct irdma_cmpl_gen *cmpl_node; ··· 2414 2432 struct irdma_qp_uk *qp = &iwqp->sc_qp.qp_uk; 2415 2433 struct irdma_ring *sq_ring = &qp->sq_ring; 2416 2434 struct irdma_ring *rq_ring = &qp->rq_ring; 2435 + struct irdma_cq *iwscq = iwqp->iwscq; 2436 + struct irdma_cq *iwrcq = iwqp->iwrcq; 2417 2437 struct irdma_cmpl_gen *cmpl; 2418 2438 __le64 *sw_wqe; 2419 2439 u64 wqe_qword; ··· 2423 2439 bool compl_generated = false; 2424 2440 unsigned long flags1; 2425 2441 2426 - spin_lock_irqsave(&iwqp->iwscq->lock, flags1); 2427 - if (irdma_cq_empty(iwqp->iwscq)) { 2442 + spin_lock_irqsave(&iwscq->lock, flags1); 2443 + if (irdma_uk_cq_empty(&iwscq->sc_cq.cq_uk)) { 2428 2444 unsigned long flags2; 2429 2445 2430 2446 spin_lock_irqsave(&iwqp->lock, flags2); ··· 2432 2448 cmpl = kzalloc(sizeof(*cmpl), GFP_ATOMIC); 2433 2449 if (!cmpl) { 2434 2450 spin_unlock_irqrestore(&iwqp->lock, flags2); 2435 - spin_unlock_irqrestore(&iwqp->iwscq->lock, flags1); 2451 + spin_unlock_irqrestore(&iwscq->lock, flags1); 2436 2452 return; 2437 2453 } 2438 2454 ··· 2451 2467 kfree(cmpl); 2452 2468 continue; 2453 2469 } 2454 - ibdev_dbg(iwqp->iwscq->ibcq.device, 2470 + ibdev_dbg(iwscq->ibcq.device, 2455 2471 "DEV: %s: adding wr_id = 0x%llx SQ Completion to list qp_id=%d\n", 2456 2472 __func__, cmpl->cpi.wr_id, qp->qp_id); 2457 - list_add_tail(&cmpl->list, &iwqp->iwscq->cmpl_generated); 2473 + list_add_tail(&cmpl->list, &iwscq->cmpl_generated); 2458 2474 compl_generated = true; 2459 2475 } 2460 2476 spin_unlock_irqrestore(&iwqp->lock, flags2); 2461 - spin_unlock_irqrestore(&iwqp->iwscq->lock, flags1); 2477 + spin_unlock_irqrestore(&iwscq->lock, flags1); 2462 2478 if (compl_generated) 2463 - irdma_comp_handler(iwqp->iwscq); 2479 + irdma_comp_handler(iwscq); 2464 2480 } else { 2465 - spin_unlock_irqrestore(&iwqp->iwscq->lock, flags1); 2481 + spin_unlock_irqrestore(&iwscq->lock, flags1); 2466 2482 mod_delayed_work(iwqp->iwdev->cleanup_wq, &iwqp->dwork_flush, 2467 2483 msecs_to_jiffies(IRDMA_FLUSH_DELAY_MS)); 2468 2484 } 2469 2485 2470 - spin_lock_irqsave(&iwqp->iwrcq->lock, flags1); 2471 - if (irdma_cq_empty(iwqp->iwrcq)) { 2486 + spin_lock_irqsave(&iwrcq->lock, flags1); 2487 + if (irdma_uk_cq_empty(&iwrcq->sc_cq.cq_uk)) { 2472 2488 unsigned long flags2; 2473 2489 2474 2490 spin_lock_irqsave(&iwqp->lock, flags2); ··· 2476 2492 cmpl = kzalloc(sizeof(*cmpl), GFP_ATOMIC); 2477 2493 if (!cmpl) { 2478 2494 spin_unlock_irqrestore(&iwqp->lock, flags2); 2479 - spin_unlock_irqrestore(&iwqp->iwrcq->lock, flags1); 2495 + spin_unlock_irqrestore(&iwrcq->lock, flags1); 2480 2496 return; 2481 2497 } 2482 2498 ··· 2488 2504 cmpl->cpi.q_type = IRDMA_CQE_QTYPE_RQ; 2489 2505 /* remove the RQ WR by moving RQ tail */ 2490 2506 IRDMA_RING_SET_TAIL(*rq_ring, rq_ring->tail + 1); 2491 - ibdev_dbg(iwqp->iwrcq->ibcq.device, 2507 + ibdev_dbg(iwrcq->ibcq.device, 2492 2508 "DEV: %s: adding wr_id = 0x%llx RQ Completion to list qp_id=%d, wqe_idx=%d\n", 2493 2509 __func__, cmpl->cpi.wr_id, qp->qp_id, 2494 2510 wqe_idx); 2495 - list_add_tail(&cmpl->list, &iwqp->iwrcq->cmpl_generated); 2511 + list_add_tail(&cmpl->list, &iwrcq->cmpl_generated); 2496 2512 2497 2513 compl_generated = true; 2498 2514 } 2499 2515 spin_unlock_irqrestore(&iwqp->lock, flags2); 2500 - spin_unlock_irqrestore(&iwqp->iwrcq->lock, flags1); 2516 + spin_unlock_irqrestore(&iwrcq->lock, flags1); 2501 2517 if (compl_generated) 2502 - irdma_comp_handler(iwqp->iwrcq); 2518 + irdma_comp_handler(iwrcq); 2503 2519 } else { 2504 - spin_unlock_irqrestore(&iwqp->iwrcq->lock, flags1); 2520 + spin_unlock_irqrestore(&iwrcq->lock, flags1); 2505 2521 mod_delayed_work(iwqp->iwdev->cleanup_wq, &iwqp->dwork_flush, 2506 2522 msecs_to_jiffies(IRDMA_FLUSH_DELAY_MS)); 2507 2523 }
+13 -3
drivers/infiniband/hw/irdma/verbs.c
··· 2028 2028 struct irdma_pci_f *rf; 2029 2029 struct irdma_cq_buf *cq_buf = NULL; 2030 2030 unsigned long flags; 2031 + u8 cqe_size; 2031 2032 int ret; 2032 2033 2033 2034 iwdev = to_iwdev(ibcq->device); ··· 2045 2044 return -EINVAL; 2046 2045 2047 2046 if (!iwcq->user_mode) { 2048 - entries++; 2047 + entries += 2; 2049 2048 2050 2049 if (!iwcq->sc_cq.cq_uk.avoid_mem_cflct && 2051 2050 dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) ··· 2053 2052 2054 2053 if (entries & 1) 2055 2054 entries += 1; /* cq size must be an even number */ 2055 + 2056 + cqe_size = iwcq->sc_cq.cq_uk.avoid_mem_cflct ? 64 : 32; 2057 + if (entries * cqe_size == IRDMA_HW_PAGE_SIZE) 2058 + entries += 2; 2056 2059 } 2057 2060 2058 2061 info.cq_size = max(entries, 4); ··· 2487 2482 int err_code; 2488 2483 int entries = attr->cqe; 2489 2484 bool cqe_64byte_ena; 2485 + u8 cqe_size; 2490 2486 2491 2487 err_code = cq_validate_flags(attr->flags, dev->hw_attrs.uk_attrs.hw_rev); 2492 2488 if (err_code) ··· 2513 2507 ukinfo->cq_id = cq_num; 2514 2508 cqe_64byte_ena = dev->hw_attrs.uk_attrs.feature_flags & IRDMA_FEATURE_64_BYTE_CQE ? 2515 2509 true : false; 2510 + cqe_size = cqe_64byte_ena ? 64 : 32; 2516 2511 ukinfo->avoid_mem_cflct = cqe_64byte_ena; 2517 2512 iwcq->ibcq.cqe = info.cq_uk_init_info.cq_size; 2518 2513 if (attr->comp_vector < rf->ceqs_count) ··· 2586 2579 goto cq_free_rsrc; 2587 2580 } 2588 2581 2589 - entries++; 2582 + entries += 2; 2590 2583 if (!cqe_64byte_ena && dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) 2591 2584 entries *= 2; 2592 2585 2593 2586 if (entries & 1) 2594 2587 entries += 1; /* cq size must be an even number */ 2588 + 2589 + if (entries * cqe_size == IRDMA_HW_PAGE_SIZE) 2590 + entries += 2; 2595 2591 2596 2592 ukinfo->cq_size = entries; 2597 2593 ··· 4510 4500 } 4511 4501 4512 4502 if ((notify_flags & IB_CQ_REPORT_MISSED_EVENTS) && 4513 - (!irdma_cq_empty(iwcq) || !list_empty(&iwcq->cmpl_generated))) 4503 + (!irdma_uk_cq_empty(ukcq) || !list_empty(&iwcq->cmpl_generated))) 4514 4504 ret = 1; 4515 4505 spin_unlock_irqrestore(&iwcq->lock, flags); 4516 4506