linux/drivers/net/ethernet/meta/fbnic/fbnic_mac.h
Mohsin Bashir 9b7c8728f5 eth: fbnic: Add protection against pause storm
Add protection against TX pause storms. A pause storm occurs when a
device fails to send received packets up to the stack. When a pause
storm is detected (pause state persists beyond the configured timeout),
the device stops sending the pause frames and begins dropping packets
instead of back-pressuring.

The timeout is configurable via ethtool tunable (pfc-prevention-tout)
with a maximum value of 10485ms, and the default value of 500ms.

Once the device transitions to the storm-detected state, the service
task periodically attempts recovery, returning the device to normal
operation to handle any subsequent pause storm episodes.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Mohsin Bashir <mohsin.bashr@gmail.com>
Link: https://patch.msgid.link/20260302230149.1580195-4-mohsin.bashr@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-03-05 16:26:52 +01:00

150 lines
5.1 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
#ifndef _FBNIC_MAC_H_
#define _FBNIC_MAC_H_
#include <linux/types.h>
struct fbnic_dev;
/* The RXB clock runs at 600 MHZ in the ASIC and the PAUSE_STORM_UNIT_WR
* is 10us granularity, so set the clock to 6000 (0x1770)
*/
#define FBNIC_RXB_PS_CLK_DIV 0x1770
/* Convert milliseconds to pause storm timeout units (10us granularity) */
#define FBNIC_MAC_RXB_PS_TO(ms) ((ms) * 100)
/* Convert pause storm timeout units (10us granularity) to milliseconds */
#define FBNIC_MAC_RXB_PS_TO_MS(ps) ((ps) / 100)
/* Set the default timer to 500ms, which should be longer than any
* reasonable period of continuous pausing. The service task, which runs
* once per second, periodically resets the pause storm trigger.
*
* As a result, on a functioning system, if pause continues, we enforce
* a duty cycle determined by the configured pause storm timeout (50%
* default). A crashed system will not have the service task and therefore
* pause will remain disabled until reboot recovery.
*/
#define FBNIC_MAC_PS_TO_DEFAULT_MS 500
#define FBNIC_MAC_PS_TO_MAX_MS \
FBNIC_MAC_RXB_PS_TO_MS(FIELD_MAX(FBNIC_RXB_PAUSE_STORM_THLD_TIME))
#define FBNIC_MAX_JUMBO_FRAME_SIZE 9742
/* States loosely based on section 136.8.11.7.5 of IEEE 802.3-2022 Ethernet
* Standard. These are needed to track the state of the PHY as it has a delay
* of several seconds from the time link comes up until it has completed
* training that we need to wait to report the link.
*
* Currently we treat training as a single block as this is managed by the
* firmware.
*
* We have FBNIC_PMD_SEND_DATA set to 0 as the expected default at driver load
* and we initialize the structure containing it to zero at allocation.
*/
enum {
FBNIC_PMD_SEND_DATA = 0x0,
FBNIC_PMD_INITIALIZE = 0x1,
FBNIC_PMD_TRAINING = 0x2,
FBNIC_PMD_LINK_READY = 0x3,
};
enum {
FBNIC_LINK_EVENT_NONE = 0,
FBNIC_LINK_EVENT_UP = 1,
FBNIC_LINK_EVENT_DOWN = 2,
};
/* Treat the FEC bits as a bitmask laid out as follows:
* Bit 0: RS Enabled
* Bit 1: BASER(Firecode) Enabled
* Bit 2: Retrieve FEC from FW
*/
enum {
FBNIC_FEC_OFF = 0,
FBNIC_FEC_RS = 1,
FBNIC_FEC_BASER = 2,
};
/* Treat the AUI modes as a modulation/lanes bitmask:
* Bit 0: Lane Count, 0 = R1, 1 = R2
* Bit 1: Modulation, 0 = NRZ, 1 = PAM4
* Bit 2: Unknown Modulation/Lane Configuration
*/
enum {
FBNIC_AUI_25GAUI = 0, /* 25.7812GBd 25.78125 * 1 */
FBNIC_AUI_LAUI2 = 1, /* 51.5625GBd 25.78128 * 2 */
FBNIC_AUI_50GAUI1 = 2, /* 53.125GBd 53.125 * 1 */
FBNIC_AUI_100GAUI2 = 3, /* 106.25GBd 53.125 * 2 */
FBNIC_AUI_UNKNOWN = 4,
__FBNIC_AUI_MAX__
};
#define FBNIC_AUI_MODE_R2 (FBNIC_AUI_LAUI2)
#define FBNIC_AUI_MODE_PAM4 (FBNIC_AUI_50GAUI1)
enum fbnic_sensor_id {
FBNIC_SENSOR_TEMP, /* Temp in millidegrees Centigrade */
FBNIC_SENSOR_VOLTAGE, /* Voltage in millivolts */
};
/* This structure defines the interface hooks for the MAC. The MAC hooks
* will be configured as a const struct provided with a set of function
* pointers.
*
* void (*init_regs)(struct fbnic_dev *fbd);
* Initialize MAC registers to enable Tx/Rx paths and FIFOs.
*
* int (*get_link_event)(struct fbnic_dev *fbd)
* Get the current link event status, reports true if link has
* changed to either FBNIC_LINK_EVENT_DOWN or FBNIC_LINK_EVENT_UP
* bool (*get_link)(struct fbnic_dev *fbd, u8 aui, u8 fec);
* Check link status
*
* void (*prepare)(struct fbnic_dev *fbd, u8 aui, u8 fec);
* Prepare PHY for init by fetching settings, disabling interrupts,
* and sending an updated PHY config to FW if needed.
*
* void (*link_down)(struct fbnic_dev *fbd);
* Configure MAC for link down event
* void (*link_up)(struct fbnic_dev *fbd, bool tx_pause, bool rx_pause);
* Configure MAC for link up event;
*
*/
struct fbnic_mac {
void (*init_regs)(struct fbnic_dev *fbd);
int (*get_link_event)(struct fbnic_dev *fbd);
bool (*get_link)(struct fbnic_dev *fbd, u8 aui, u8 fec);
void (*prepare)(struct fbnic_dev *fbd, u8 aui, u8 fec);
void (*get_fec_stats)(struct fbnic_dev *fbd, bool reset,
struct fbnic_fec_stats *fec_stats);
void (*get_pcs_stats)(struct fbnic_dev *fbd, bool reset,
struct fbnic_pcs_stats *pcs_stats);
void (*get_eth_mac_stats)(struct fbnic_dev *fbd, bool reset,
struct fbnic_eth_mac_stats *mac_stats);
void (*get_pause_stats)(struct fbnic_dev *fbd, bool reset,
struct fbnic_pause_stats *pause_stats);
void (*get_eth_ctrl_stats)(struct fbnic_dev *fbd, bool reset,
struct fbnic_eth_ctrl_stats *ctrl_stats);
void (*get_rmon_stats)(struct fbnic_dev *fbd, bool reset,
struct fbnic_rmon_stats *rmon_stats);
void (*link_down)(struct fbnic_dev *fbd);
void (*link_up)(struct fbnic_dev *fbd, bool tx_pause, bool rx_pause);
int (*get_sensor)(struct fbnic_dev *fbd, int id, long *val);
};
int fbnic_mac_init(struct fbnic_dev *fbd);
void fbnic_mac_get_fw_settings(struct fbnic_dev *fbd, u8 *aui, u8 *fec);
int fbnic_mac_ps_protect_to_config(struct fbnic_dev *fbd, u16 timeout);
void fbnic_mac_ps_protect_handler(struct fbnic_dev *fbd);
bool fbnic_mac_check_tx_pause(struct fbnic_dev *fbd);
#endif /* _FBNIC_MAC_H_ */