[Intel-wired-lan] [PATCH iwl-next v4 1/9] net: ethtool: mm: extract stmmac verification logic into common library
From: Vladimir Oltean It appears that stmmac is not the only hardware which requires a software-driven verification state machine for the MAC Merge layer. While on the one hand it's good to encourage hardware implementations, on the other hand it's quite difficult to tolerate multiple drivers implementing independently fairly non-trivial logic. Extract the hardware-independent logic from stmmac into library code and put it in ethtool. Name the state structure "mmsv" for MAC Merge Software Verification. Let this expose an operations structure for executing the hardware stuff: sync hardware with the tx_active boolean (result of verification process), enable/disable the pMAC, send mPackets, notify library of external events (reception of mPackets), as well as link state changes. Note that it is assumed that the external events are received in hardirq context. If they are not, it is probably a good idea to disable hardirqs when calling ethtool_mmsv_event_handle(), because the library does not do so. Also, the MM software verification process has no business with the tx_min_frag_size, that is all the driver's to handle. Signed-off-by: Vladimir Oltean Co-developed-by: Choong Yong Liang Signed-off-by: Choong Yong Liang Co-developed-by: Faizal Rahim Signed-off-by: Faizal Rahim Tested-by: Choong Yong Liang --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 16 +- .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 41 +--- .../net/ethernet/stmicro/stmmac/stmmac_fpe.c | 174 +++--- .../net/ethernet/stmicro/stmmac/stmmac_fpe.h | 5 - .../net/ethernet/stmicro/stmmac/stmmac_main.c | 8 +- include/linux/ethtool.h | 61 + net/ethtool/mm.c | 222 ++ 7 files changed, 327 insertions(+), 200 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index f05cae103d83..c9cc41af258a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -147,21 +147,9 @@ struct stmmac_channel { }; struct stmmac_fpe_cfg { - /* Serialize access to MAC Merge state between ethtool requests -* and link state updates. -*/ - spinlock_t lock; - + struct ethtool_mmsv mmsv; const struct stmmac_fpe_reg *reg; - u32 fpe_csr;/* MAC_FPE_CTRL_STS reg cache */ - - enum ethtool_mm_verify_status status; - struct timer_list verify_timer; - bool verify_enabled; - int verify_retries; - bool pmac_enabled; - u32 verify_time; - bool tx_enabled; + u32 fpe_csr;/* MAC_FPE_CTRL_STS reg cache */ }; struct stmmac_tc_entry { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 918a32f8fda8..8e6b052e00d6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -1210,37 +1210,17 @@ static int stmmac_get_mm(struct net_device *ndev, struct ethtool_mm_state *state) { struct stmmac_priv *priv = netdev_priv(ndev); - unsigned long flags; u32 frag_size; if (!stmmac_fpe_supported(priv)) return -EOPNOTSUPP; - spin_lock_irqsave(&priv->fpe_cfg.lock, flags); + ethtool_mmsv_get_mm(&priv->fpe_cfg.mmsv, state); - state->max_verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS; - state->verify_enabled = priv->fpe_cfg.verify_enabled; - state->pmac_enabled = priv->fpe_cfg.pmac_enabled; - state->verify_time = priv->fpe_cfg.verify_time; - state->tx_enabled = priv->fpe_cfg.tx_enabled; - state->verify_status = priv->fpe_cfg.status; state->rx_min_frag_size = ETH_ZLEN; - - /* FPE active if common tx_enabled and -* (verification success or disabled(forced)) -*/ - if (state->tx_enabled && - (state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED || -state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED)) - state->tx_active = true; - else - state->tx_active = false; - frag_size = stmmac_fpe_get_add_frag_size(priv); state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size); - spin_unlock_irqrestore(&priv->fpe_cfg.lock, flags); - return 0; } @@ -1248,8 +1228,6 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg, struct netlink_ext_ack *extack) { struct stmmac_priv *priv = netdev_priv(ndev); - struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg; - unsigned long flags; u32 frag_size; int err; @@ -1258,23 +1236,8 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg, if (err) return err; - /* Wait for the verifi
[Intel-wired-lan] [PATCH iwl-next v4 0/9] igc: Add support for Frame Preemption feature in IGC
Introduces support for the FPE feature in the IGC driver. The patches aligns with the upstream FPE API: https://patchwork.kernel.org/project/netdevbpf/cover/20230220122343.1156614-1-vladimir.olt...@nxp.com/ https://patchwork.kernel.org/project/netdevbpf/cover/20230119122705.73054-1-vladimir.olt...@nxp.com/ It builds upon earlier work: https://patchwork.kernel.org/project/netdevbpf/cover/20220520011538.109-1-vinicius.go...@intel.com/ The patch series adds the following functionalities to the IGC driver: a) Configure FPE using `ethtool --set-mm`. b) Display FPE settings via `ethtool --show-mm`. c) View FPE statistics using `ethtool --include-statistics --show-mm'. e) Enable preemptible/express queue with `fp`: tc qdisc add ... root taprio \ fp E E P P Change Log: v3 -> v4: - Fix compilation warnings introduced by this patch series v2 -> v3: - Implement configure_tx() mmsv callback (Vladimir) - Use static_branch_inc() and static_branch_dec() (Vladimir) - Add adapter->fpe.mmsv.pmac_enabled as extra check (Vladimir) - Remove unnecessary error check in igc_fpe_init_tx_descriptor() (Vladimir) - Additional places to use FIELD_PREP() instead of manual bit manipulation (Vladimir) - IGC_TXD_POPTS_SMD_V and IGC_TXD_POPTS_SMD_R type change to enum (Vladimir) - Remove unnecessary netif_running() check in igc_fpe_xmit_frame (Vladimir) - Rate limit print in igc_fpe_send_mpacket (Vladimir) v1 -> v2: - Extract the stmmac verification logic into a common library (Vladimir) - igc to use common library for verification (Vladimir) - Fix syntax for kernel-doc to use "Return:" (Vladimir) - Use FIELD_GET instead of manual bit masking (Vladimir) - Don't assign 0 to statistics counter in igc_ethtool_get_mm_stats() (Vladimir) - Use pmac-enabled as a condition to allow MAC address value 0 (Vladimir) - Define macro register value in increasing value order (Vladimir) - Fix tx-min-frag-size handling for igc (Vladimir) - Handle link state changes with verification in igc (Vladimir) - Add static key for fast path code (Vladimir) - rx_min_frag_size get from constant (Vladimir) v1: https://patchwork.kernel.org/project/netdevbpf/cover/20241216064720.931522-1-faizal.abdul.ra...@linux.intel.com/ v2: https://patchwork.kernel.org/project/netdevbpf/cover/20250205100524.1138523-1-faizal.abdul.ra...@linux.intel.com/ v3: https://patchwork.kernel.org/project/netdevbpf/cover/20250207165649.2245320-1-faizal.abdul.ra...@linux.intel.com/ Faizal Rahim (8): igc: Rename xdp_get_tx_ring() for non-xdp usage igc: Optimize the TX packet buffer utilization igc: Set the RX packet buffer size for TSN mode igc: Add support for frame preemption verification igc: Add support to set tx-min-frag-size igc: Add support for preemptible traffic class in taprio igc: Add support to get MAC Merge data via ethtool igc: Add support to get frame preemption statistics via ethtool Vladimir Oltean (1): net: ethtool: mm: extract stmmac verification logic into common library drivers/net/ethernet/intel/igc/igc.h | 18 +- drivers/net/ethernet/intel/igc/igc_base.h | 1 + drivers/net/ethernet/intel/igc/igc_defines.h | 16 +- drivers/net/ethernet/intel/igc/igc_ethtool.c | 76 ++ drivers/net/ethernet/intel/igc/igc_main.c | 101 +++- drivers/net/ethernet/intel/igc/igc_regs.h | 16 ++ drivers/net/ethernet/intel/igc/igc_tsn.c | 219 - drivers/net/ethernet/intel/igc/igc_tsn.h | 34 +++ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 16 +- .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 41 +--- .../net/ethernet/stmicro/stmmac/stmmac_fpe.c | 174 +++--- .../net/ethernet/stmicro/stmmac/stmmac_fpe.h | 5 - .../net/ethernet/stmicro/stmmac/stmmac_main.c | 8 +- include/linux/ethtool.h | 61 + net/ethtool/mm.c | 224 +- 15 files changed, 793 insertions(+), 217 deletions(-) -- 2.34.1
[Intel-wired-lan] [PATCH iwl-next v4 5/9] igc: Add support for frame preemption verification
This patch implements the "ethtool --set-mm" callback to trigger the frame preemption verification handshake. Uses the MAC Merge Software Verification (mmsv) mechanism in ethtool to perform the verification handshake for igc. The structure fpe.mmsv is set by mmsv in ethtool and should remain read-only for the driver. Other mmsv callbacks: a) configure_tx() -> not used yet at this point - igc lacks registers to configure FPE in the transmit direction, so this API is not utilized for now. A future patch will use it to control preemptible queue config. b) configure_pmac() -> not used - this callback dynamically controls pmac_enabled at runtime. For example, mmsv calls configure_pmac() and disables pmac_enabled when the link partner goes down, even if the user previously enabled it. The intention is to save power but it is not feasible in igc because it causes an endless adapter reset loop: 1) Board A and Board B complete the verification handshake. Tx mode register for both boards are in TSN mode. 2) Board B link goes down. On Board A: 3) mmsv calls configure_pmac() with pmac_enabled = false. 4) configure_pmac() in igc updates a new field based on pmac_enabled. Driver uses this field in igc_tsn_new_flags() to indicate that the user enabled/disabled FPE. 5) configure_pmac() in igc calls igc_tsn_offload_apply() to check whether an adapter reset is needed. Calls existing logic in igc_tsn_will_tx_mode_change() and igc_tsn_new_flags(). 6) Since pmac_enabled is now disabled and no other TSN feature is active, igc_tsn_will_tx_mode_change() evaluates to true because Tx mode will switch from TSN to Legacy. 7) Driver resets the adapter. 8) Registers are set, and Tx mode switches to Legacy. 9) When link partner is up, steps 3–8 repeat, but this time with pmac_enabled = true, reactivating TSN. igc_tsn_will_tx_mode_change() evaluates to true again, since Tx mode will switch from Legacy to TSN. 10) Driver resets the adapter. 11) Rest adapter completes, registers are set, and Tx mode switches to TSN. On Board B: 12) Adapter reset on Board A at step 10 causes it to detect its link partner as down. 13) Repeats steps 3–8. 14) Once reset adapter on Board A is completed at step 11, it detects its link partner as up. 15) Repeats steps 9–11. - this cycle repeats indefinitely. To avoid this issue, igc only uses mmsv.pmac_enabled to track whether FPE is enabled or disabled. Co-developed-by: Vinicius Costa Gomes Signed-off-by: Vinicius Costa Gomes Co-developed-by: Choong Yong Liang Signed-off-by: Choong Yong Liang Signed-off-by: Faizal Rahim --- drivers/net/ethernet/intel/igc/igc.h | 12 +- drivers/net/ethernet/intel/igc/igc_base.h| 1 + drivers/net/ethernet/intel/igc/igc_defines.h | 8 +- drivers/net/ethernet/intel/igc/igc_ethtool.c | 21 +++ drivers/net/ethernet/intel/igc/igc_main.c| 54 ++- drivers/net/ethernet/intel/igc/igc_tsn.c | 156 ++- drivers/net/ethernet/intel/igc/igc_tsn.h | 33 7 files changed, 280 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 22ecdac26cf4..705bd4739e3b 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -40,6 +40,10 @@ void igc_ethtool_set_ops(struct net_device *); #define IGC_MAX_TX_TSTAMP_REGS 4 +struct fpe_t { + struct ethtool_mmsv mmsv; +}; + enum igc_mac_filter_type { IGC_MAC_FILTER_TYPE_DST = 0, IGC_MAC_FILTER_TYPE_SRC @@ -332,6 +336,8 @@ struct igc_adapter { struct timespec64 period; } perout[IGC_N_PEROUT]; + struct fpe_t fpe; + /* LEDs */ struct mutex led_mutex; struct igc_led_classdev *leds; @@ -389,10 +395,11 @@ extern char igc_driver_name[]; #define IGC_FLAG_TSN_QBV_ENABLED BIT(17) #define IGC_FLAG_TSN_QAV_ENABLED BIT(18) #define IGC_FLAG_TSN_LEGACY_ENABLEDBIT(19) +#define IGC_FLAG_TSN_PREEMPT_ENABLED BIT(20) #define IGC_FLAG_TSN_ANY_ENABLED \ (IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED | \ -IGC_FLAG_TSN_LEGACY_ENABLED) +IGC_FLAG_TSN_LEGACY_ENABLED | IGC_FLAG_TSN_PREEMPT_ENABLED) #define IGC_FLAG_RSS_FIELD_IPV4_UDPBIT(6) #define IGC_FLAG_RSS_FIELD_IPV6_UDPBIT(7) @@ -736,7 +743,10 @@ struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter, u32 location); int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule); void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule); +void igc_disab
[Intel-wired-lan] [PATCH iwl-next v4 8/9] igc: Add support to get MAC Merge data via ethtool
Implement "ethtool --show-mm" callback for IGC. Tested with command: $ ethtool --show-mm enp1s0. MAC Merge layer state for enp1s0: pMAC enabled: on TX enabled: on TX active: on TX minimum fragment size: 64 RX minimum fragment size: 60 Verify enabled: on Verify time: 128 Max verify time: 128 Verification status: SUCCEEDED Verified that the fields value are retrieved correctly. Signed-off-by: Faizal Rahim --- drivers/net/ethernet/intel/igc/igc_ethtool.c | 14 ++ drivers/net/ethernet/intel/igc/igc_tsn.h | 1 + 2 files changed, 15 insertions(+) diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c index 081e24f228b2..7f0052e0d50c 100644 --- a/drivers/net/ethernet/intel/igc/igc_ethtool.c +++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c @@ -1782,6 +1782,19 @@ static int igc_ethtool_set_eee(struct net_device *netdev, return 0; } +static int igc_ethtool_get_mm(struct net_device *netdev, + struct ethtool_mm_state *cmd) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct fpe_t *fpe = &adapter->fpe; + + ethtool_mmsv_get_mm(&fpe->mmsv, cmd); + cmd->tx_min_frag_size = fpe->tx_min_frag_size; + cmd->rx_min_frag_size = IGC_RX_MIN_FRAG_SIZE; + + return 0; +} + static int igc_ethtool_set_mm(struct net_device *netdev, struct ethtool_mm_cfg *cmd, struct netlink_ext_ack *extack) @@ -2093,6 +2106,7 @@ static const struct ethtool_ops igc_ethtool_ops = { .set_rxfh = igc_ethtool_set_rxfh, .get_ts_info= igc_ethtool_get_ts_info, .get_channels = igc_ethtool_get_channels, + .get_mm = igc_ethtool_get_mm, .set_mm = igc_ethtool_set_mm, .set_channels = igc_ethtool_set_channels, .get_priv_flags = igc_ethtool_get_priv_flags, diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h index 898c4630bc70..c82f9718cb85 100644 --- a/drivers/net/ethernet/intel/igc/igc_tsn.h +++ b/drivers/net/ethernet/intel/igc/igc_tsn.h @@ -4,6 +4,7 @@ #ifndef _IGC_TSN_H_ #define _IGC_TSN_H_ +#define IGC_RX_MIN_FRAG_SIZE 60 #define SMD_FRAME_SIZE 60 DECLARE_STATIC_KEY_FALSE(igc_fpe_enabled); -- 2.34.1
[Intel-wired-lan] [PATCH iwl-next v4 9/9] igc: Add support to get frame preemption statistics via ethtool
Implemented "ethtool --include-statistics --show-mm" callback for IGC. Tested preemption scenario to check preemption statistics: 1) Trigger verification handshake on both boards: $ sudo ethtool --set-mm enp1s0 pmac-enabled on $ sudo ethtool --set-mm enp1s0 tx-enabled on $ sudo ethtool --set-mm enp1s0 verify-enabled on 2) Set preemptible or express queue in taprio for tx board: $ sudo tc qdisc replace dev enp1s0 parent root handle 100 taprio \ num_tc 4 map 3 2 1 0 3 3 3 3 3 3 3 3 3 3 3 3 \ queues 1@0 1@1 1@2 1@3 base-time 0 sched-entry S F 10 \ fp E E P P 3) Send large size packets on preemptible queue 4) Send small size packets on express queue to preempt packets in preemptible queue 5) Show preemption statistics on the receiving board: $ ethtool --include-statistics --show-mm enp1s0 MAC Merge layer state for enp1s0: pMAC enabled: on TX enabled: on TX active: on TX minimum fragment size: 64 RX minimum fragment size: 60 Verify enabled: on Verify time: 128 Max verify time: 128 Verification status: SUCCEEDED Statistics: MACMergeFrameAssErrorCount: 0 MACMergeFrameSmdErrorCount: 0 MACMergeFrameAssOkCount: 511 MACMergeFragCountRx: 764 MACMergeFragCountTx: 0 MACMergeHoldCount: 0 Co-developed-by: Vinicius Costa Gomes Signed-off-by: Vinicius Costa Gomes Signed-off-by: Faizal Rahim --- drivers/net/ethernet/intel/igc/igc_ethtool.c | 36 drivers/net/ethernet/intel/igc/igc_main.c| 1 + drivers/net/ethernet/intel/igc/igc_regs.h| 16 + 3 files changed, 53 insertions(+) diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c index 7f0052e0d50c..97a1194399b1 100644 --- a/drivers/net/ethernet/intel/igc/igc_ethtool.c +++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c @@ -1819,6 +1819,41 @@ static int igc_ethtool_set_mm(struct net_device *netdev, return igc_tsn_offload_apply(adapter); } +/** + * igc_ethtool_get_frame_ass_error - Get the frame assembly error count. + * @dev: Pointer to the net_device structure. + * Return: The count of frame assembly errors. + */ +static u64 igc_ethtool_get_frame_ass_error(struct net_device *dev) +{ + struct igc_adapter *adapter = netdev_priv(dev); + u32 ooo_smdc, ooo_frame_cnt, ooo_frag_cnt; /* Out of order statistics */ + struct igc_hw *hw = &adapter->hw; + u32 miss_frame_frag_cnt; + u32 reg_value; + + reg_value = rd32(IGC_PRMEXPRCNT); + ooo_smdc = FIELD_GET(IGC_PRMEXPRCNT_OOO_SMDC, reg_value); + ooo_frame_cnt = FIELD_GET(IGC_PRMEXPRCNT_OOO_FRAME_CNT, reg_value); + ooo_frag_cnt = FIELD_GET(IGC_PRMEXPRCNT_OOO_FRAG_CNT, reg_value); + miss_frame_frag_cnt = FIELD_GET(IGC_PRMEXPRCNT_MISS_FRAME_FRAG_CNT, + reg_value); + + return ooo_smdc + ooo_frame_cnt + ooo_frag_cnt + miss_frame_frag_cnt; +} + +static void igc_ethtool_get_mm_stats(struct net_device *dev, +struct ethtool_mm_stats *stats) +{ + struct igc_adapter *adapter = netdev_priv(dev); + struct igc_hw *hw = &adapter->hw; + + stats->MACMergeFrameAssErrorCount = igc_ethtool_get_frame_ass_error(dev); + stats->MACMergeFrameAssOkCount = rd32(IGC_PRMPTDRCNT); + stats->MACMergeFragCountRx = rd32(IGC_PRMEVNTRCNT); + stats->MACMergeFragCountTx = rd32(IGC_PRMEVNTTCNT); +} + static int igc_ethtool_get_link_ksettings(struct net_device *netdev, struct ethtool_link_ksettings *cmd) { @@ -2108,6 +2143,7 @@ static const struct ethtool_ops igc_ethtool_ops = { .get_channels = igc_ethtool_get_channels, .get_mm = igc_ethtool_get_mm, .set_mm = igc_ethtool_set_mm, + .get_mm_stats = igc_ethtool_get_mm_stats, .set_channels = igc_ethtool_set_channels, .get_priv_flags = igc_ethtool_get_priv_flags, .set_priv_flags = igc_ethtool_set_priv_flags, diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index f15ac7565fbd..cd5160315993 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -3076,6 +3076,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget) break; if (static_branch_unlikely(&igc_fpe_enabled) && + adapter->fpe.mmsv.pmac_enabled && igc_fpe_transmitted_smd_v(tx_desc)) ethtool_mmsv_event_handle(&adapter->fpe.mmsv, ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET); diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h index 12ddc5793651..41dbfb07eb2f 100644 ---
[Intel-wired-lan] [PATCH iwl-next v4 6/9] igc: Add support to set tx-min-frag-size
Add support to set tx-min-frag-size via set_mm callback in igc. Increase the max limit of tx-ming-frag-size in ethtool from 252 to 256 since i225/6 value range is 64, 128, 192 and 256. Co-developed-by: Vinicius Costa Gomes Signed-off-by: Vinicius Costa Gomes Signed-off-by: Faizal Rahim --- drivers/net/ethernet/intel/igc/igc.h | 1 + drivers/net/ethernet/intel/igc/igc_defines.h | 1 + drivers/net/ethernet/intel/igc/igc_ethtool.c | 5 +++ drivers/net/ethernet/intel/igc/igc_tsn.c | 37 ++-- drivers/net/ethernet/intel/igc/igc_tsn.h | 2 +- net/ethtool/mm.c | 2 +- 6 files changed, 43 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 705bd4739e3b..2f3662143589 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -42,6 +42,7 @@ void igc_ethtool_set_ops(struct net_device *); struct fpe_t { struct ethtool_mmsv mmsv; + u32 tx_min_frag_size; }; enum igc_mac_filter_type { diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index 22db1de02964..038ee89f1e08 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -551,6 +551,7 @@ #define IGC_TQAVCTRL_PREEMPT_ENA 0x0002 #define IGC_TQAVCTRL_ENHANCED_QAV 0x0008 #define IGC_TQAVCTRL_FUTSCDDIS 0x0080 +#define IGC_TQAVCTRL_MIN_FRAG_MASK 0xC000 #define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x0001 #define IGC_TXQCTL_STRICT_CYCLE0x0002 diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c index e2a14edf7552..081e24f228b2 100644 --- a/drivers/net/ethernet/intel/igc/igc_ethtool.c +++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c @@ -1789,6 +1789,11 @@ static int igc_ethtool_set_mm(struct net_device *netdev, struct igc_adapter *adapter = netdev_priv(netdev); struct fpe_t *fpe = &adapter->fpe; + fpe->tx_min_frag_size = igc_fpe_get_supported_frag_size(cmd->tx_min_frag_size); + if (fpe->tx_min_frag_size != cmd->tx_min_frag_size) + NL_SET_ERR_MSG_MOD(extack, + "tx-min-frag-size value set is unsupported. Rounded up to supported value (64, 128, 192, 256)"); + if (fpe->mmsv.pmac_enabled != cmd->pmac_enabled) { if (cmd->pmac_enabled) static_branch_inc(&igc_fpe_enabled); diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c index dc35d40955c9..57fc4a876304 100644 --- a/drivers/net/ethernet/intel/igc/igc_tsn.c +++ b/drivers/net/ethernet/intel/igc/igc_tsn.c @@ -7,6 +7,12 @@ #include "igc_hw.h" #include "igc_tsn.h" +#define MIN_MULTPLIER_TX_MIN_FRAG 0 +#define MAX_MULTPLIER_TX_MIN_FRAG 3 +/* Frag size is based on the Section 8.12.2 of the SW User Manual */ +#define TX_MIN_FRAG_SIZE 64 +#define TX_MAX_FRAG_SIZE (TX_MIN_FRAG_SIZE * (MAX_MULTPLIER_TX_MIN_FRAG + 1)) + enum igc_txd_popts_type { SMD_V = 0x01, SMD_R = 0x02 @@ -141,6 +147,7 @@ static const struct ethtool_mmsv_ops igc_mmsv_ops = { void igc_fpe_init(struct igc_adapter *adapter) { + adapter->fpe.tx_min_frag_size = TX_MIN_FRAG_SIZE; ethtool_mmsv_init(&adapter->fpe.mmsv, adapter->netdev, &igc_mmsv_ops); } @@ -291,7 +298,7 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter) tqavctrl = rd32(IGC_TQAVCTRL); tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS | - IGC_TQAVCTRL_PREEMPT_ENA); + IGC_TQAVCTRL_PREEMPT_ENA | IGC_TQAVCTRL_MIN_FRAG_MASK); wr32(IGC_TQAVCTRL, tqavctrl); @@ -337,12 +344,34 @@ static void igc_tsn_set_retx_qbvfullthreshold(struct igc_adapter *adapter) wr32(IGC_RETX_CTL, retxctl); } +static u8 igc_fpe_get_frag_size_mult(const struct fpe_t *fpe) +{ + u8 mult = (fpe->tx_min_frag_size / TX_MIN_FRAG_SIZE) - 1; + + return clamp_t(u8, mult, MIN_MULTPLIER_TX_MIN_FRAG, + MAX_MULTPLIER_TX_MIN_FRAG); +} + +u32 igc_fpe_get_supported_frag_size(u32 frag_size) +{ + const u32 supported_sizes[] = {64, 128, 192, 256}; + + /* Find the smallest supported size that is >= frag_size */ + for (int i = 0; i < ARRAY_SIZE(supported_sizes); i++) { + if (frag_size <= supported_sizes[i]) + return supported_sizes[i]; + } + + return TX_MAX_FRAG_SIZE; /* Should not happen, value > 256 is blocked by ethtool */ +} + static int igc_tsn_enable_offload(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; u32 tqavctrl, baset_l, baset_h; u32 sec, nsec, cycle, rxpbs; ktime_t base_time, systim
[Intel-wired-lan] [PATCH iwl-next v4 7/9] igc: Add support for preemptible traffic class in taprio
Set queue as preemptible or express via taprio. This will eventually set queue-specific preemptible field in TXQCTL register. Implement configure_tx(), a callback triggered by mmsv, to set tx_enabled and update preemptible queue settings. tx_enabled is a new field that serves as a condition in igc_tsn_enable_offload() before configuring the preemptible queue. This provides some control over FPE in TX, despite lacking a dedicated register. Verified that the correct preemptible hardware queue is set using the following commands: a) 1:1 TC-to-Queue Mapping $ sudo tc qdisc replace dev enp1s0 parent root handle 100 \ taprio num_tc 4 map 3 2 1 0 3 3 3 3 3 3 3 3 3 3 3 3 \ queues 1@0 1@1 1@2 1@3 base-time 0 sched-entry S F 10 \ fp E E P P b) Non-1:1 TC-to-Queue Mapping $ sudo tc qdisc replace dev enp1s0 parent root handle 100 \ taprio num_tc 3 map 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 2 queues 2@0 1@2 1@3 fp E E P Co-developed-by: Vinicius Costa Gomes Signed-off-by: Vinicius Costa Gomes Signed-off-by: Faizal Rahim --- drivers/net/ethernet/intel/igc/igc.h | 3 +- drivers/net/ethernet/intel/igc/igc_defines.h | 1 + drivers/net/ethernet/intel/igc/igc_main.c| 36 drivers/net/ethernet/intel/igc/igc_tsn.c | 17 + 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 2f3662143589..59e6fca808e4 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -43,6 +43,7 @@ void igc_ethtool_set_ops(struct net_device *); struct fpe_t { struct ethtool_mmsv mmsv; u32 tx_min_frag_size; + bool tx_enabled; }; enum igc_mac_filter_type { @@ -163,7 +164,7 @@ struct igc_ring { bool launchtime_enable; /* true if LaunchTime is enabled */ ktime_t last_tx_cycle; /* end of the cycle with a launchtime transmission */ ktime_t last_ff_cycle; /* Last cycle with an active first flag */ - + bool preemptible; /* True if not express */ u32 start_time; u32 end_time; u32 max_sdu; diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index 038ee89f1e08..208899e67308 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -556,6 +556,7 @@ #define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x0001 #define IGC_TXQCTL_STRICT_CYCLE0x0002 #define IGC_TXQCTL_STRICT_END 0x0004 +#define IGC_TXQCTL_PREEMPTIBLE 0x0008 #define IGC_TXQCTL_QAV_SEL_MASK0x00C0 #define IGC_TXQCTL_QAV_SEL_CBS00x0080 #define IGC_TXQCTL_QAV_SEL_CBS10x00C0 diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 7fe6875d7bf7..f15ac7565fbd 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -6258,6 +6258,39 @@ static bool is_base_time_past(ktime_t base_time, const struct timespec64 *now) return timespec64_compare(now, &b) > 0; } +static u32 igc_map_tc_to_queue(const struct igc_adapter *adapter, + unsigned long preemptible_tcs) +{ + struct net_device *dev = adapter->netdev; + u32 i, queue = 0; + + for (i = 0; i < dev->num_tc; i++) { + u32 offset, count; + + if (!(preemptible_tcs & BIT(i))) + continue; + + offset = dev->tc_to_txq[i].offset; + count = dev->tc_to_txq[i].count; + queue |= GENMASK(offset + count - 1, offset); + } + + return queue; +} + +static void igc_save_preempt_queue(struct igc_adapter *adapter, + const struct tc_mqprio_qopt_offload *mqprio) +{ + u32 preemptible_queue = igc_map_tc_to_queue(adapter, + mqprio->preemptible_tcs); + + for (int i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *tx_ring = adapter->tx_ring[i]; + + tx_ring->preemptible = preemptible_queue & BIT(i); + } +} + static bool validate_schedule(struct igc_adapter *adapter, const struct tc_taprio_qopt_offload *qopt) { @@ -6344,6 +6377,7 @@ static int igc_qbv_clear_schedule(struct igc_adapter *adapter) ring->start_time = 0; ring->end_time = NSEC_PER_SEC; ring->max_sdu = 0; + ring->preemptible = false; } spin_lock_irqsave(&adapter->qbv_tx_lock, flags); @@ -6500,6 +6534,8 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, ring->max_sdu = 0; } + igc_save_preempt_queue(adapter, &qopt->mqprio); + return 0;
[Intel-wired-lan] [PATCH iwl-next v4 4/9] igc: Set the RX packet buffer size for TSN mode
In preparation for supporting frame preemption, when entering TSN mode set the receive packet buffer to 16KB for the Express MAC, 16KB for the Preemptible MAC and 2KB for the BMC, according to the datasheet section 7.1.3.2. Co-developed-by: Vinicius Costa Gomes Signed-off-by: Vinicius Costa Gomes Signed-off-by: Faizal Rahim --- drivers/net/ethernet/intel/igc/igc_defines.h | 3 +++ drivers/net/ethernet/intel/igc/igc_tsn.c | 13 +++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index 516ef70c98e9..b19ac6f30dac 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -402,6 +402,9 @@ /* 7KB bytes buffer for each tx queue (total 4 queues) + 4KB for BMC*/ #define IGC_TXPBSIZE_TSN 0x041c71c7 +/* 15KB for EXP + 15KB for BE + 2KB for BMC */ +#define IGC_RXPBSIZE_TSN 0xf08f +#define IGC_RXPBSIZE_SIZE_MASK 0x0001 #define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */ #define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */ diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c index 1e44374ca1ff..f0213cfce07d 100644 --- a/drivers/net/ethernet/intel/igc/igc_tsn.c +++ b/drivers/net/ethernet/intel/igc/igc_tsn.c @@ -132,13 +132,17 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter) { u16 queue_per_tc[4] = { 3, 2, 1, 0 }; struct igc_hw *hw = &adapter->hw; - u32 tqavctrl; + u32 tqavctrl, rxpbs; int i; wr32(IGC_GTXOFFSET, 0); wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT); wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT); + rxpbs = rd32(IGC_RXPBS) & ~IGC_RXPBSIZE_SIZE_MASK; + rxpbs |= I225_RXPBSIZE_DEFAULT; + wr32(IGC_RXPBS, rxpbs); + if (igc_is_device_id_i226(hw)) igc_tsn_restore_retx_default(adapter); @@ -194,7 +198,7 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; u32 tqavctrl, baset_l, baset_h; - u32 sec, nsec, cycle; + u32 sec, nsec, cycle, rxpbs; ktime_t base_time, systim; int i; @@ -202,6 +206,11 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN); wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN); + rxpbs = rd32(IGC_RXPBS) & ~IGC_RXPBSIZE_SIZE_MASK; + rxpbs |= IGC_RXPBSIZE_TSN; + + wr32(IGC_RXPBS, rxpbs); + if (igc_is_device_id_i226(hw)) igc_tsn_set_retx_qbvfullthreshold(adapter); -- 2.34.1
[Intel-wired-lan] [PATCH iwl-next v4 2/9] igc: Rename xdp_get_tx_ring() for non-xdp usage
Renamed xdp_get_tx_ring() function to a more generic name for use in upcoming frame preemption patches. Signed-off-by: Faizal Rahim --- drivers/net/ethernet/intel/igc/igc.h | 2 +- drivers/net/ethernet/intel/igc/igc_main.c | 10 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index b8111ad9a9a8..22ecdac26cf4 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -736,7 +736,7 @@ struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter, u32 location); int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule); void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule); - +struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu); void igc_ptp_init(struct igc_adapter *adapter); void igc_ptp_reset(struct igc_adapter *adapter); void igc_ptp_suspend(struct igc_adapter *adapter); diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 56a35d58e7a6..44e4f925491f 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -2444,8 +2444,8 @@ static int igc_xdp_init_tx_descriptor(struct igc_ring *ring, return -ENOMEM; } -static struct igc_ring *igc_xdp_get_tx_ring(struct igc_adapter *adapter, - int cpu) +struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, +int cpu) { int index = cpu; @@ -2469,7 +2469,7 @@ static int igc_xdp_xmit_back(struct igc_adapter *adapter, struct xdp_buff *xdp) if (unlikely(!xdpf)) return -EFAULT; - ring = igc_xdp_get_tx_ring(adapter, cpu); + ring = igc_get_tx_ring(adapter, cpu); nq = txring_txq(ring); __netif_tx_lock(nq, cpu); @@ -2546,7 +2546,7 @@ static void igc_finalize_xdp(struct igc_adapter *adapter, int status) struct igc_ring *ring; if (status & IGC_XDP_TX) { - ring = igc_xdp_get_tx_ring(adapter, cpu); + ring = igc_get_tx_ring(adapter, cpu); nq = txring_txq(ring); __netif_tx_lock(nq, cpu); @@ -6699,7 +6699,7 @@ static int igc_xdp_xmit(struct net_device *dev, int num_frames, if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) return -EINVAL; - ring = igc_xdp_get_tx_ring(adapter, cpu); + ring = igc_get_tx_ring(adapter, cpu); nq = txring_txq(ring); __netif_tx_lock(nq, cpu); -- 2.34.1
[Intel-wired-lan] [PATCH iwl-next v4 3/9] igc: Optimize the TX packet buffer utilization
Packet buffers (RX + TX) total 64KB. Neither RX or TX buffers can be larger than 34KB. So divide the buffer equally, 32KB for each. Co-developed-by: Vinicius Costa Gomes Signed-off-by: Vinicius Costa Gomes Signed-off-by: Faizal Rahim --- drivers/net/ethernet/intel/igc/igc_defines.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index 8e449904aa7d..516ef70c98e9 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -400,7 +400,8 @@ #define I225_TXPBSIZE_DEFAULT 0x0414 /* TXPBSIZE default */ #define IGC_RXPBS_CFG_TS_EN0x8000 /* Timestamp in Rx buffer */ -#define IGC_TXPBSIZE_TSN 0x04145145 /* 5k bytes buffer for each queue */ + /* 7KB bytes buffer for each tx queue (total 4 queues) + 4KB for BMC*/ +#define IGC_TXPBSIZE_TSN 0x041c71c7 #define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */ #define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */ -- 2.34.1
Re: [Intel-wired-lan] [PATCH] ixgbe: remove self assignment
On Sun, Feb 09, 2025 at 11:47:24PM -0500, Ethan Carter Edwards wrote: > Variable self assignment does not have any effect. > > Addresses-Coverity-ID: 1641823 ("Self assignment") > Fixes: 46761fd52a886 ("ixgbe: Add support for E610 FW Admin Command > Interface") > Signed-off-by: Ethan Carter Edwards > --- > drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c | 1 - > 1 file changed, 1 deletion(-) > > diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c > b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c > index > 683c668672d65535fca3b2fe6f58a9deda1188fa..6b0bce92476c3c5ec3cf7ab79864b394b592c6d4 > 100644 > --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c > +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c > @@ -145,7 +145,6 @@ static int ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw, > if ((hicr & IXGBE_PF_HICR_SV)) { > for (i = 0; i < IXGBE_ACI_DESC_SIZE_IN_DWORDS; i++) { > raw_desc[i] = IXGBE_READ_REG(hw, IXGBE_PF_HIDA(i)); > - raw_desc[i] = raw_desc[i]; > } > } > Thanks for the patch. This change is already in progress [1] (I hope, waiting for v3). [1] https://lore.kernel.org/netdev/20250115034117.172999-1-dheeraj.linux...@gmail.com/ Thanks, Michal > > --- > base-commit: a64dcfb451e254085a7daee5fe51bf22959d52d3 > change-id: 20250209-e610-self-85eac1f0e338 > > Best regards, > -- > Ethan Carter Edwards
Re: [Intel-wired-lan] [iwl-next v1 1/4] ixgbe: add MDD support
On Fri, Feb 07, 2025 at 03:07:49PM +, Simon Horman wrote: > On Fri, Feb 07, 2025 at 11:43:40AM +0100, Michal Swiatkowski wrote: > > From: Paul Greenwalt > > > > Add malicious driver detection. Support enabling MDD, disabling MDD, > > handling a MDD event, and restoring a MDD VF. > > > > Reviewed-by: Przemek Kitszel > > Reviewed-by: Jedrzej Jagielski > > Reviewed-by: Marcin Szycik > > Signed-off-by: Paul Greenwalt > > Signed-off-by: Michal Swiatkowski > > ... > > > diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c > > b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c > > ... > > > +/** > > + * ixgbe_handle_mdd_x550 - handle malicious driver detection event > > + * @hw: pointer to hardware structure > > + * @vf_bitmap: output vf bitmap of malicious vfs > > + */ > > +void ixgbe_handle_mdd_x550(struct ixgbe_hw *hw, unsigned long *vf_bitmap) > > +{ > > + u32 i, j, reg, q, div, vf, wqbr; > > + > > + /* figure out pool size for mapping to vf's */ > > + reg = IXGBE_READ_REG(hw, IXGBE_MRQC); > > + switch (reg & IXGBE_MRQC_MRQE_MASK) { > > + case IXGBE_MRQC_VMDQRT8TCEN: > > + div = IXGBE_16VFS_QUEUES; > > + break; > > + case IXGBE_MRQC_VMDQRSS32EN: > > + case IXGBE_MRQC_VMDQRT4TCEN: > > + div = IXGBE_32VFS_QUEUES; > > + break; > > + default: > > + div = IXGBE_64VFS_QUEUES; > > + break; > > + } > > + > > + /* Read WQBR_TX and WQBR_RX and check for malicious queues */ > > + for (i = 0; i < IXGBE_QUEUES_REG_AMOUNT; i++) { > > + wqbr = IXGBE_READ_REG(hw, IXGBE_WQBR_TX(i)) | > > + IXGBE_READ_REG(hw, IXGBE_WQBR_RX(i)); > > + if (!wqbr) > > + continue; > > + > > + /* Get malicious queue */ > > + for_each_set_bit(j, (unsigned long *)&wqbr, > > +IXGBE_QUEUES_PER_REG) { > > The type of wqbr is a u32, that is it is 32-bits wide. > Above it's address is cast to unsigned long *. > But, unsigned long may be 64-bits wide, e.g. on x86_64. > > GCC 14.2.0 EXTRA_CFLAGS=-Warray-bounds builds report this as: > > In file included from ./include/linux/bitmap.h:11, > from ./include/linux/cpumask.h:12, > from ./arch/x86/include/asm/paravirt.h:21, > from ./arch/x86/include/asm/cpuid.h:71, > from ./arch/x86/include/asm/processor.h:19, > from ./arch/x86/include/asm/cpufeature.h:5, > from ./arch/x86/include/asm/thread_info.h:59, > from ./include/linux/thread_info.h:60, > from ./include/linux/uio.h:9, > from ./include/linux/socket.h:8, > from ./include/uapi/linux/if.h:25, > from ./include/linux/mii.h:12, > from ./include/uapi/linux/mdio.h:15, > from ./include/linux/mdio.h:9, > from drivers/net/ethernet/intel/ixgbe/ixgbe_type.h:8, > from drivers/net/ethernet/intel/ixgbe/ixgbe_x540.h:7, > from drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c:4: > In function ‘find_next_bit’, > inlined from ‘ixgbe_handle_mdd_x550’ at > drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c:3907:3: > ./include/linux/find.h:65:23: error: array subscript ‘long unsigned int[0]’ > is partly outside array bounds of ‘u32[1]’ {aka ‘unsigned int[1]’} > [-Werror=array-bounds=] >65 | val = *addr & GENMASK(size - 1, offset); > | ^ > > I think this can be addressed by changing the type of wqmbr to unsigned long. Thanks for catching that, I will fix. > > > + /* Get queue from bitmask */ > > + q = j + (i * IXGBE_QUEUES_PER_REG); > > + /* Map queue to vf */ > > + vf = q / div; > > + set_bit(vf, vf_bitmap); > > + } > > + } > > +} > > + > > #define X550_COMMON_MAC \ > > .init_hw= &ixgbe_init_hw_generic, \ > > .start_hw = &ixgbe_start_hw_X540, \ > > ...
Re: [Intel-wired-lan] [iwl-next v1 3/4] ixgbe: add Tx hang detection unhandled MDD
On Fri, Feb 07, 2025 at 02:57:10PM +, Simon Horman wrote: > On Fri, Feb 07, 2025 at 11:43:42AM +0100, Michal Swiatkowski wrote: > > From: Slawomir Mrozowicz > > > > Add Tx Hang detection due to an unhandled MDD Event. > > > > Previously, a malicious VF could disable the entire port causing > > TX to hang on the E610 card. > > Those events that caused PF to freeze were not detected > > as an MDD event and usually required a Tx Hang watchdog timer > > to catch the suspension, and perform a physical function reset. > > > > Implement flows in the affected PF driver in such a way to check > > the cause of the hang, detect it as an MDD event and log an > > entry of the malicious VF that caused the Hang. > > > > The PF blocks the malicious VF, if it continues to be the source > > of several MDD events. > > > > Reviewed-by: Przemek Kitszel > > Reviewed-by: Marcin Szycik > > Signed-off-by: Slawomir Mrozowicz > > Co-developed-by: Michal Swiatkowski > > Signed-off-by: Michal Swiatkowski > > ... > > > diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h > > b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h > > index aa3b498558bc..e07b56625595 100644 > > --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h > > +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h > > @@ -1044,6 +1044,7 @@ struct ixgbe_nvm_version { > > #define IXGBE_GCR_EXT_VT_MODE_160x0001 > > #define IXGBE_GCR_EXT_VT_MODE_320x0002 > > #define IXGBE_GCR_EXT_VT_MODE_640x0003 > > +#define IXGBE_GCR_EXT_VT_MODE_MASK 0x0003 > > nit: For consistency I think spaces should be used to indent 0x0003 > Will fix, I wondered if I should follow normal style or be consistent. > > #define IXGBE_GCR_EXT_SRIOV (IXGBE_GCR_EXT_MSIX_EN | \ > > IXGBE_GCR_EXT_VT_MODE_64) > > > > ... > > > diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c > > b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c > > ... > > > +static u32 ixgbe_poll_tx_icache(struct ixgbe_hw *hw, u16 queue, u16 idx) > > +{ > > + IXGBE_WRITE_REG(hw, IXGBE_TXDESCIC, queue * idx); > > + return IXGBE_READ_REG(hw, IXGBE_TXDESCIC); > > +} > > + > > +/** > > + * ixgbe_check_illegal_queue - search for queue with illegal packet > > + * @adapter: structure containing ring specific data > > + * @queue: queue index > > + * > > + * Check if tx descriptor connected with input queue > > + * contains illegal packet. > > + * > > + * Returns: true if queue contain illegal packet. > > + */ > > +static bool ixgbe_check_illegal_queue(struct ixgbe_adapter *adapter, > > + u16 queue) > > +{ > > + u32 hdr_len_reg, mss_len_reg, type_reg; > > + struct ixgbe_hw *hw = &adapter->hw; > > + u32 mss_len, header_len, reg; > > + > > + for (u16 i = 0; i < IXGBE_MAX_TX_DESCRIPTORS; i++) { > > + /* HW will clear bit IXGBE_TXDESCIC_READY when address > > +* is written to address field. HW will set this bit > > +* when iCache read is done, and data is ready at TIC_DWx. > > +* Set descriptor address. > > +*/ > > + read_poll_timeout(ixgbe_poll_tx_icache, reg, > > + !(reg & IXGBE_TXDESCIC_READY), 0, 0, false, > > + hw, queue, i); > > + > > + /* read tx descriptor access registers */ > > + hdr_len_reg = IXGBE_READ_REG(hw, > > IXGBE_TIC_DW2(IXGBE_VLAN_MACIP_LENS_REG)); > > + type_reg = IXGBE_READ_REG(hw, > > IXGBE_TIC_DW2(IXGBE_TYPE_TUCMD_MLHL)); > > + mss_len_reg = IXGBE_READ_REG(hw, > > IXGBE_TIC_DW2(IXGBE_MSS_L4LEN_IDX)); > > + > > + /* check if Advanced Context Descriptor */ > > + if (FIELD_GET(IXGBE_ADVTXD_DTYP_MASK, type_reg) != > > + IXGBE_ADVTXD_DTYP_CTXT) > > + continue; > > + > > + /* check for illegal MSS and Header length */ > > + mss_len = FIELD_GET(IXGBE_ADVTXD_MSS_MASK, mss_len_reg); > > + header_len = FIELD_GET(IXGBE_ADVTXD_HEADER_LEN_MASK, > > + hdr_len_reg); > > + if ((mss_len + header_len) > SZ_16K) { > > + e_warn(probe, > > + "mss len + header len too long\n"); > > nit: The above two lines can be a single line. > Will fix > > + return true; > > + } > > + } > > + > > + return false; > > +} > > + > > +/** > > + * ixgbe_handle_mdd_event - handle mdd event > > + * @adapter: structure containing ring specific data > > + * @tx_ring: tx descriptor ring to handle > > + * > > + * Reset VF driver if malicious vf detected or > > + * illegal packet in an any queue detected. > > + */ > > +static void ixgbe_handle_mdd_event(struct ixgbe_adapter *adapter, > > + struct ixgbe_ring *tx_ring) > > +{ > > + u16 vf, q; > > + > > + if (adapter->vfinfo && ixgbe_check_mdd_event(adapter)) { >
Re: [Intel-wired-lan] [PATCH iwl-next v1 01/13] ixgbe: add initial devlink support
On Mon, Feb 03, 2025 at 04:03:16PM +0100, Jedrzej Jagielski wrote: > Add an initial support for devlink interface to ixgbe driver. > > Similarly to i40e driver the implementation doesn't enable > devlink to manage device-wide configuration. Devlink instance > is created for each physical function of PCIe device. > > Create separate directory for devlink related ixgbe files > and use naming scheme similar to the one used in the ice driver. > > Add a stub for Documentation, to be extended by further patches. > > Reviewed-by: Mateusz Polchlopek > Signed-off-by: Jedrzej Jagielski ... > +/** > + * ixgbe_devlink_register_port - Register devlink port > + * @adapter: pointer to the device adapter structure > + * > + * Create and register a devlink_port for this physical function. > + * > + * Return: 0 on success, error code on failure. > + */ > +int ixgbe_devlink_register_port(struct ixgbe_adapter *adapter) > +{ > + struct devlink_port *devlink_port = &adapter->devlink_port; > + struct devlink *devlink = adapter->devlink; > + struct device *dev = &adapter->pdev->dev; > + struct devlink_port_attrs attrs = {}; > + int err; > + > + attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; > + attrs.phys.port_number = adapter->hw.bus.func; > + ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id); > + > + devlink_port_attrs_set(devlink_port, &attrs); > + > + err = devl_port_register(devlink, devlink_port, 0); > + if (err) { > + dev_err(dev, > + "devlink port registration failed, err %d\n", > + err); nit: I think we can fit this onto one 80 column-wide line (just!). dev_err(dev, "devlink port registration failed, err %d\n", err); > + } > + > + return err; > +} ...
Re: [Intel-wired-lan] [PATCH iwl-next v1 02/13] ixgbe: add handler for devlink .info_get()
On Mon, Feb 03, 2025 at 04:03:17PM +0100, Jedrzej Jagielski wrote: > Provide devlink .info_get() callback implementation to allow the > driver to report detailed version information. The following info > is reported: > > "serial_number" -> The PCI DSN of the adapter > "fw.bundle_id" -> Unique identifier for the combined flash image > "fw.undi" -> Version of the Option ROM containing the UEFI driver > "board.id" -> The PBA ID string > > Reviewed-by: Mateusz Polchlopek > Signed-off-by: Jedrzej Jagielski ... > diff --git a/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c > b/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c ... > +static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter, > +struct ixgbe_info_ctx *ctx) > +{ > + struct ixgbe_hw *hw = &adapter->hw; > + struct ixgbe_nvm_version nvm_ver; > + > + ixgbe_get_oem_prod_version(hw, &nvm_ver); > + if (nvm_ver.oem_valid) { > + snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x", > + nvm_ver.oem_major, nvm_ver.oem_minor, > + nvm_ver.oem_release); > + > + return; > + } > + > + ixgbe_get_orom_version(hw, &nvm_ver); > + if (nvm_ver.or_valid) > + snprintf(ctx->buf, sizeof(ctx->buf), "%d.%d.%d", > + nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch); Hi Jedrzej, If neither of the conditions above are met then it seems that ctx->buf will contain whatever string was present when the function was called. Is something like the following needed here? ctx->buf[0] = '\0'; > +} > + > +static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter, > +struct ixgbe_info_ctx *ctx) > +{ > + struct ixgbe_hw *hw = &adapter->hw; > + struct ixgbe_nvm_version nvm_ver; > + > + ixgbe_get_oem_prod_version(hw, &nvm_ver); > + /* No ETRACK version for OEM */ > + if (nvm_ver.oem_valid) > + return; Likewise, here. > + > + ixgbe_get_etk_id(hw, &nvm_ver); > + snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id); > +} > + > +static int ixgbe_devlink_info_get(struct devlink *devlink, > + struct devlink_info_req *req, > + struct netlink_ext_ack *extack) > +{ > + struct ixgbe_devlink_priv *devlink_private = devlink_priv(devlink); > + struct ixgbe_adapter *adapter = devlink_private->adapter; > + struct ixgbe_hw *hw = &adapter->hw; > + struct ixgbe_info_ctx *ctx; > + int err; > + > + ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); > + if (!ctx) > + return -ENOMEM; > + > + ixgbe_info_get_dsn(adapter, ctx); > + err = devlink_info_serial_number_put(req, ctx->buf); > + if (err) > + goto free_ctx; > + > + ixgbe_info_nvm_ver(adapter, ctx); > + err = ixgbe_devlink_info_put(req, IXGBE_DL_VERSION_RUNNING, > + DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, > + ctx->buf); > + if (err) > + goto free_ctx; > + > + ixgbe_info_eetrack(adapter, ctx); > + err = ixgbe_devlink_info_put(req, IXGBE_DL_VERSION_RUNNING, > + DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, > + ctx->buf); > + if (err) > + goto free_ctx; > + > + err = ixgbe_read_pba_string_generic(hw, ctx->buf, sizeof(ctx->buf)); > + if (err) > + goto free_ctx; > + > + err = ixgbe_devlink_info_put(req, IXGBE_DL_VERSION_FIXED, > + DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, > + ctx->buf); > +free_ctx: > + kfree(ctx); > + return err; > +} ...