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

eth: fbnic: Configure RDE settings for pause frame

fbnic supports pause frames. When pause frames are enabled presumably
user expects lossless operation from the NIC. Make sure we configure
RDE (Rx DMA Engine) to DROP_NEVER mode to avoid discards due to delays
in fetching Rx descriptors from the host.

While at it enable DROP_NEVER when NIC only has a single queue
configured. In this case the NIC acts as a FIFO so there's no risk
of head-of-line blocking other queues by making RDE wait. If pause
is disabled this just moves the packet loss from the DMA engine to
the Rx buffer.

Remove redundant call to fbnic_config_drop_mode_rcq(), introduced by
commit 0cb4c0a13723 ("eth: fbnic: Implement Rx queue
alloc/start/stop/free"). This call does not add value as
fbnic_enable_rcq(), which is called immediately afterward, already
handles this.

Although we do not support autoneg at this time, preserve tx_pause in
.mac_link_up instead of fbnic_phylink_get_pauseparam()

Signed-off-by: Mohsin Bashir <mohsin.bashr@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20251113232610.1151712-1-mohsin.bashr@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Mohsin Bashir and committed by
Jakub Kicinski
01353339 122ac16b

+28 -4
+2
drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
··· 73 73 74 74 /* Time stamping filter config */ 75 75 struct kernel_hwtstamp_config hwtstamp_config; 76 + 77 + bool tx_pause; 76 78 }; 77 79 78 80 int __fbnic_open(struct fbnic_net *fbn);
+3
drivers/net/ethernet/meta/fbnic/fbnic_phylink.c
··· 208 208 struct fbnic_net *fbn = netdev_priv(netdev); 209 209 struct fbnic_dev *fbd = fbn->fbd; 210 210 211 + fbn->tx_pause = tx_pause; 212 + fbnic_config_drop_mode(fbn, tx_pause); 213 + 211 214 fbd->mac->link_up(fbd, tx_pause, rx_pause); 212 215 } 213 216
+22 -4
drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
··· 2574 2574 } 2575 2575 2576 2576 static void fbnic_config_drop_mode_rcq(struct fbnic_napi_vector *nv, 2577 - struct fbnic_ring *rcq) 2577 + struct fbnic_ring *rcq, bool tx_pause) 2578 2578 { 2579 + struct fbnic_net *fbn = netdev_priv(nv->napi.dev); 2579 2580 u32 drop_mode, rcq_ctl; 2580 2581 2581 - drop_mode = FBNIC_QUEUE_RDE_CTL0_DROP_IMMEDIATE; 2582 + if (!tx_pause && fbn->num_rx_queues > 1) 2583 + drop_mode = FBNIC_QUEUE_RDE_CTL0_DROP_IMMEDIATE; 2584 + else 2585 + drop_mode = FBNIC_QUEUE_RDE_CTL0_DROP_NEVER; 2582 2586 2583 2587 /* Specify packet layout */ 2584 2588 rcq_ctl = FIELD_PREP(FBNIC_QUEUE_RDE_CTL0_DROP_MODE_MASK, drop_mode) | ··· 2590 2586 FIELD_PREP(FBNIC_QUEUE_RDE_CTL0_MIN_TROOM_MASK, FBNIC_RX_TROOM); 2591 2587 2592 2588 fbnic_ring_wr32(rcq, FBNIC_QUEUE_RDE_CTL0, rcq_ctl); 2589 + } 2590 + 2591 + void fbnic_config_drop_mode(struct fbnic_net *fbn, bool tx_pause) 2592 + { 2593 + int i, t; 2594 + 2595 + for (i = 0; i < fbn->num_napi; i++) { 2596 + struct fbnic_napi_vector *nv = fbn->napi[i]; 2597 + 2598 + for (t = 0; t < nv->rxt_count; t++) { 2599 + struct fbnic_q_triad *qt = &nv->qt[nv->txt_count + t]; 2600 + 2601 + fbnic_config_drop_mode_rcq(nv, &qt->cmpl, tx_pause); 2602 + } 2603 + } 2593 2604 } 2594 2605 2595 2606 static void fbnic_config_rim_threshold(struct fbnic_ring *rcq, u16 nv_idx, u32 rx_desc) ··· 2656 2637 u32 hds_thresh = fbn->hds_thresh; 2657 2638 u32 rcq_ctl = 0; 2658 2639 2659 - fbnic_config_drop_mode_rcq(nv, rcq); 2640 + fbnic_config_drop_mode_rcq(nv, rcq, fbn->tx_pause); 2660 2641 2661 2642 /* Force lower bound on MAX_HEADER_BYTES. Below this, all frames should 2662 2643 * be split at L4. It would also result in the frames being split at ··· 2719 2700 &nv->napi); 2720 2701 2721 2702 fbnic_enable_bdq(&qt->sub0, &qt->sub1); 2722 - fbnic_config_drop_mode_rcq(nv, &qt->cmpl); 2723 2703 fbnic_enable_rcq(nv, &qt->cmpl); 2724 2704 } 2725 2705 }
+1
drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
··· 184 184 irqreturn_t fbnic_msix_clean_rings(int irq, void *data); 185 185 void fbnic_napi_enable(struct fbnic_net *fbn); 186 186 void fbnic_napi_disable(struct fbnic_net *fbn); 187 + void fbnic_config_drop_mode(struct fbnic_net *fbn, bool tx_pause); 187 188 void fbnic_enable(struct fbnic_net *fbn); 188 189 void fbnic_disable(struct fbnic_net *fbn); 189 190 void fbnic_flush(struct fbnic_net *fbn);