Skip to content

Commit

Permalink
net/ngbe: fix flow control
Browse files Browse the repository at this point in the history
[ upstream commit d19fa5a1f447244aa961a3cc8c52c9024f9109ab ]

Fix flow control high/low water limit.

Fixes: f40e9f0 ("net/ngbe: support flow control")

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
  • Loading branch information
Jiawen Wu authored and kevintraynor committed Oct 31, 2023
1 parent 289d492 commit 51451e5
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 0 deletions.
40 changes: 40 additions & 0 deletions drivers/net/ngbe/base/ngbe_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,46 @@ struct ngbe_fc_info {
enum ngbe_fc_mode requested_mode; /* FC mode requested by caller */
};

/* Flow Control Data Sheet defined values
* Calculation and defines taken from 802.1bb Annex O
*/
/* BitTimes (BT) conversion */
#define NGBE_BT2KB(BT) (((BT) + (8 * 1024 - 1)) / (8 * 1024))
#define NGBE_B2BT(BT) ((BT) * 8)

/* Calculate Delay to respond to PFC */
#define NGBE_PFC_D 672

/* Calculate Cable Delay */
#define NGBE_CABLE_DC 5556 /* Delay Copper */

/* Calculate Interface Delay */
#define NGBE_PHY_D 12800
#define NGBE_MAC_D 4096
#define NGBE_XAUI_D (2 * 1024)

#define NGBE_ID (NGBE_MAC_D + NGBE_XAUI_D + NGBE_PHY_D)

/* Calculate Delay incurred from higher layer */
#define NGBE_HD 6144

/* Calculate PCI Bus delay for low thresholds */
#define NGBE_PCI_DELAY 10000

/* Calculate delay value in bit times */
#define NGBE_DV(_max_frame_link, _max_frame_tc) \
((36 * \
(NGBE_B2BT(_max_frame_link) + \
NGBE_PFC_D + \
(2 * NGBE_CABLE_DC) + \
(2 * NGBE_ID) + \
NGBE_HD) / 25 + 1) + \
2 * NGBE_B2BT(_max_frame_tc))

#define NGBE_LOW_DV(_max_frame_tc) \
(2 * ((2 * NGBE_B2BT(_max_frame_tc) + \
(36 * NGBE_PCI_DELAY / 25) + 1)))

/* Statistics counters collected by the MAC */
/* PB[] RxTx */
struct ngbe_pb_stats {
Expand Down
89 changes: 89 additions & 0 deletions drivers/net/ngbe/ngbe_ethdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ static int ngbe_dev_misc_interrupt_setup(struct rte_eth_dev *dev);
static int ngbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev);
static void ngbe_dev_interrupt_handler(void *param);
static void ngbe_configure_msix(struct rte_eth_dev *dev);
static void ngbe_pbthresh_set(struct rte_eth_dev *dev);

#define NGBE_SET_HWSTRIP(h, q) do {\
uint32_t idx = (q) / (sizeof((h)->bitmap[0]) * NBBY); \
Expand Down Expand Up @@ -1020,6 +1021,7 @@ ngbe_dev_start(struct rte_eth_dev *dev)
}

hw->mac.setup_pba(hw);
ngbe_pbthresh_set(dev);
ngbe_configure_port(dev);

err = ngbe_dev_rxtx_start(dev);
Expand Down Expand Up @@ -2340,6 +2342,93 @@ ngbe_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
return -EIO;
}

/* Additional bittime to account for NGBE framing */
#define NGBE_ETH_FRAMING 20

/*
* ngbe_fc_hpbthresh_set - calculate high water mark for flow control
*
* @dv_id: device interface delay
* @pb: packet buffer to calculate
*/
static s32
ngbe_fc_hpbthresh_set(struct rte_eth_dev *dev)
{
struct ngbe_hw *hw = ngbe_dev_hw(dev);
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
u32 max_frame_size, tc, dv_id, rx_pb;
s32 kb, marker;

/* Calculate max LAN frame size */
max_frame_size = rd32m(hw, NGBE_FRMSZ, NGBE_FRMSZ_MAX_MASK);
tc = max_frame_size + NGBE_ETH_FRAMING;

/* Calculate delay value for device */
dv_id = NGBE_DV(tc, tc);

/* Loopback switch introduces additional latency */
if (pci_dev->max_vfs)
dv_id += NGBE_B2BT(tc);

/* Delay value is calculated in bit times convert to KB */
kb = NGBE_BT2KB(dv_id);
rx_pb = rd32(hw, NGBE_PBRXSIZE) >> 10;

marker = rx_pb - kb;

/* It is possible that the packet buffer is not large enough
* to provide required headroom. In this case throw an error
* to user and do the best we can.
*/
if (marker < 0) {
PMD_DRV_LOG(WARNING, "Packet Buffer can not provide enough headroom to support flow control.");
marker = tc + 1;
}

return marker;
}

/*
* ngbe_fc_lpbthresh_set - calculate low water mark for flow control
*
* @dv_id: device interface delay
*/
static s32
ngbe_fc_lpbthresh_set(struct rte_eth_dev *dev)
{
struct ngbe_hw *hw = ngbe_dev_hw(dev);
u32 max_frame_size, tc, dv_id;
s32 kb;

/* Calculate max LAN frame size */
max_frame_size = rd32m(hw, NGBE_FRMSZ, NGBE_FRMSZ_MAX_MASK);
tc = max_frame_size + NGBE_ETH_FRAMING;

/* Calculate delay value for device */
dv_id = NGBE_LOW_DV(tc);

/* Delay value is calculated in bit times convert to KB */
kb = NGBE_BT2KB(dv_id);

return kb;
}

/*
* ngbe_pbthresh_setup - calculate and setup high low water marks
*/
static void
ngbe_pbthresh_set(struct rte_eth_dev *dev)
{
struct ngbe_hw *hw = ngbe_dev_hw(dev);

hw->fc.high_water = ngbe_fc_hpbthresh_set(dev);
hw->fc.low_water = ngbe_fc_lpbthresh_set(dev);

/* Low water marks must not be larger than high water marks */
if (hw->fc.low_water > hw->fc.high_water)
hw->fc.low_water = 0;
}

int
ngbe_dev_rss_reta_update(struct rte_eth_dev *dev,
struct rte_eth_rss_reta_entry64 *reta_conf,
Expand Down

0 comments on commit 51451e5

Please sign in to comment.