mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 14:04:27 -04:00
Merge branch 'net-stmmac-more-selftest-related-fixes'
Maxime Chevallier says: ==================== net: stmmac: More selftest related fixes This series addresses some (but not all) issues found while running the ethtool selftest on various stmmac platforms. As a reminder, ethtool selftest are run with 'ethtool -t ethX', and for stmmac the goal is to test hardware features and bugs from the IP integration in the platform. I've been running this on : - Altera CycloneV (dwmac-socfpga, dwmac1000 IP, v3.70a) - NXP imx8mp (dwmac-imx, dwmac4, v5.10a) - Allwinner H2S (dwmac-sun8i, dwmac1000) - Amlogic S905X3 (dwmac-meson8b, dwmac1000, v3.70a) - STM32mp157a (dwmac-stm32, dwmac4, v4.20a) - SiFive JH7110 (dwmac-starfive, dwmac4, v5.20) Here's the results before this series, noting that some bugs were already fixed, some are ongoing (cf. the IP proto patch here [1]) [1] : https://lore.kernel.org/netdev/20260825211748.360935-1-maxime.chevallier@bootlin.com/ Tests are OK if return is 0 or -95 (-EOPNOTSUPP), tests are KO otherwise Test imx socfpga sun8i meson8b stm32 starfive MAC Loopback 0 0 0 0 0 0 MMC Counters 0 0 -95 -22 0 -22 EEE -95 -95 -95 -95 -95 -95 Hash Filter MC 0 0 -95 0 0 0 Perfect Filter UC 0 0 0 0 0 0 MC Filter 0 0 -95 0 0 0 UC Filter 0 0 -95 -22 0 0 Flow Control -110 0 -110 0 0 -110 RSS -95 -95 -95 -95 -95 -95 VLAN Filtering -110 -95 -95 -95 -110 -110 VLAN Filtering (perf) -110 -95 -95 -95 -110 -110 Double VLAN Filter -110 -95 -95 -95 -110 -110 Double VLAN Filter (perf) -110 -95 -95 -95 -110 -110 Flexible RX Parser 0 -95 -95 -95 -95 -95 SA Insertion (desc) 0 -95 -95 -95 0 0 SA Replacement (desc) 0 -95 -95 -95 0 0 SA Insertion (reg 0 -95 -95 -95 0 0 SA Replacement (reg) 0 -95 -95 -95 0 0 VLAN TX Insertion -110 -95 -95 -95 -110 -110 SVLAN TX Insertion -110 -95 -95 -95 -110 -95 L3 DA Filtering 0 -95 -95 -95 -95 -95 L3 SA Filtering 0 -95 -95 -95 -95 -95 L4 DA TCP Filtering 0 -95 -95 -95 -95 -95 L4 SA TCP Filtering 0 -95 -95 -95 -95 -95 L4 DA UDP Filtering 0 -95 -95 -95 -95 -95 L4 SA UDP Filtering 0 -95 -95 -95 -95 -95 ARP Offload -95 -95 -95 -95 -110 -110 Jumbo Frame 0 0 0 0 0 0 Multichannel Jumbo 0 -95 -95 -95 -95 -95 Split Header -95 -95 -95 -95 -95 -95 TBS (ETF Scheduler) -95 -95 -95 -95 -95 -95 So, only sogfpga is all OK (in all fairness, it doesn't support much) Several issues : - MMC test failing on starfive and meson8b, solved by patch 1 MMC counters maintained by the MAC are optional, which one is implemented depends on how the IP is synthesized. On starfive and meson8b, the counter used by the selftest to validate the MMC counters feature isn't implemented. Solved by adding other counters in the validation step, kinda fragile as this doesn't guarantee this will work on all platforms. - Flow control test failing on starfive, imx8mp, sun8i, solved by patch 6 Turns out these platforms actually never emit any Pause frame, as they don't have enough room in their per-queue RX Fifo. They do correctly process RX Pause frames. The fix isn't to change the advertised pauseparams, as the pause negotiation process based on MAC capabilities doesn't allow us to say we "just" support RX pause, so let's just not run the Pause tests if the RX fifo is too small. - UC filter failing on meson8b, fixed by patches 2,3,4 and 5 This one is quite the rabbit hole, and is a combination of multiple issues. - Unicast filtering uses the same filter (perfect filter) to allow the primary MAC address and the secondary addresses (dev->uc) to flow through the interface. That means if we have say 64 slots in the perfect filter, only 63 can be used for the dev->uc list, as the first entry stores the MAC address. If the filter is full, we switch to UC promisc mode, were we let all UC frames flow. There's an off-by-one error in dwmac1000, dwmac4 and dwxgmac2. - The selftest itself needs an empty slot in the filter, so it has to check that sizeof(dev->uc) is $number_of_slots - 2 (one for primary MAC, one for the test). There's an off-by-two error in the selftest. - This leads to an interesting finding (not addressed by this series) : The size of the perfect filter isn't reported by the HW, so it comes from firmware (snps,perfect-filter-entries). A lot of platforms don't specify that in DT (e.g. imx8mp doesn't, it has 128 entries but the driver thinks there's only 1...). I've reached out to Synopsys to see if there's some sane default we could use on dwmac4, if anyone has a dwmac4 databook I'd appreciate if you could look this up, as I don't have access to them, I'm not a vendor... Otherwise, we'll have to patch all the .dtsi if we want to avoid going in UC promisc as soon as we add an entry in dev->uc. After this series, socfpga, starfive and sun8i are all OK :) Some issues are still out there, the VLAN filtering and tagging fails on imx8mp and stm32 (so, dwmac4) butI haven't got there yet. ARP offload doesn't work on stm32mp157a and starfive JH7110 either. ==================== Link: https://patch.msgid.link/20260826140500.616466-1-maxime.chevallier@bootlin.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -194,7 +194,7 @@ static void dwmac1000_set_filter(struct mac_device_info *hw,
|
||||
dwmac1000_set_mchash(ioaddr, mc_filter, mcbitslog2);
|
||||
|
||||
/* Handle multiple unicast addresses (perfect filtering) */
|
||||
if (netdev_uc_count(dev) > perfect_addr_number)
|
||||
if (netdev_uc_count(dev) + 1 > perfect_addr_number)
|
||||
/* Switch to promiscuous mode if more than unicast
|
||||
* addresses are requested than supported by hardware.
|
||||
*/
|
||||
|
||||
@@ -521,7 +521,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
|
||||
value |= GMAC_PACKET_FILTER_HPF;
|
||||
|
||||
/* Handle multiple unicast addresses */
|
||||
if (netdev_uc_count(dev) > hw->unicast_filter_entries) {
|
||||
if (netdev_uc_count(dev) + 1 > hw->unicast_filter_entries) {
|
||||
/* Switch to promiscuous mode if more than 128 addrs
|
||||
* are required
|
||||
*/
|
||||
|
||||
@@ -532,7 +532,7 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,
|
||||
dwxgmac2_set_mchash(ioaddr, mc_filter, mcbitslog2);
|
||||
|
||||
/* Handle multiple unicast addresses */
|
||||
if (netdev_uc_count(dev) > hw->unicast_filter_entries) {
|
||||
if (netdev_uc_count(dev) + 1 > hw->unicast_filter_entries) {
|
||||
value |= XGMAC_FILTER_PR;
|
||||
} else {
|
||||
struct netdev_hw_addr *ha;
|
||||
|
||||
@@ -395,11 +395,17 @@ static int stmmac_test_mmc(struct stmmac_priv *priv)
|
||||
stmmac_mmc_read(priv, priv->mmcaddr, &final);
|
||||
|
||||
/*
|
||||
* The number of MMC counters available depends on HW configuration
|
||||
* so we just use this one to validate the feature. I hope there is
|
||||
* not a version without this counter.
|
||||
* The number of MMC counters available depends on HW configuration,
|
||||
* and there doesn't seem to be a way to enumerate the implemented
|
||||
* counters.
|
||||
*
|
||||
* Let's check a hand-picked set of counters, knowing that :
|
||||
* - Starfive JH7110 doesn't implement mmc_tx_framecount_g
|
||||
* - Amlogic SM1 doesn't implement any mmc_tx_*
|
||||
*
|
||||
*/
|
||||
if (final.mmc_tx_framecount_g <= initial.mmc_tx_framecount_g)
|
||||
if (final.mmc_tx_framecount_g <= initial.mmc_tx_framecount_g &&
|
||||
final.mmc_rx_framecount_gb <= initial.mmc_rx_framecount_gb)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -473,6 +479,21 @@ static int stmmac_filter_check(struct stmmac_priv *priv)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int stmmac_uc_filter_check(struct stmmac_priv *priv)
|
||||
{
|
||||
/* For tests involving the UC filter, we need at least one empty
|
||||
* slot in the UC filter. The UC filters contains netdev_uc_count() + 1
|
||||
* entries: The dev->uc list + one entry for the HW address.
|
||||
*
|
||||
* Having an empty slot therefore means netdev_uc_count() + 2 entries
|
||||
* can fit in the filter
|
||||
*/
|
||||
if (netdev_uc_count(priv->dev) + 2 > priv->hw->unicast_filter_entries)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool stmmac_hash_check(struct stmmac_priv *priv, unsigned char *addr)
|
||||
{
|
||||
int mc_offset = 32 - priv->hw->mcast_bits_log2;
|
||||
@@ -564,7 +585,7 @@ static int stmmac_test_pfilt(struct stmmac_priv *priv)
|
||||
|
||||
if (stmmac_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
|
||||
if (stmmac_uc_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
while (--tries) {
|
||||
@@ -608,7 +629,7 @@ static int stmmac_test_mcfilt(struct stmmac_priv *priv)
|
||||
|
||||
if (stmmac_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
|
||||
if (stmmac_uc_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins)
|
||||
return -EOPNOTSUPP;
|
||||
@@ -654,7 +675,7 @@ static int stmmac_test_ucfilt(struct stmmac_priv *priv)
|
||||
|
||||
if (stmmac_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
|
||||
if (stmmac_uc_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins)
|
||||
return -EOPNOTSUPP;
|
||||
@@ -718,12 +739,24 @@ static int stmmac_test_flowctrl(struct stmmac_priv *priv)
|
||||
u32 rx_cnt = priv->plat->rx_queues_to_use;
|
||||
struct mac_device_info *mac = priv->hw;
|
||||
struct stmmac_test_priv *tpriv;
|
||||
unsigned int rx_fifo_size;
|
||||
unsigned int pkt_count;
|
||||
int i, ret = 0;
|
||||
|
||||
if (!(mac->link.caps & MAC_SYM_PAUSE))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rx_fifo_size = priv->plat->rx_fifo_size;
|
||||
if (!rx_fifo_size)
|
||||
rx_fifo_size = priv->dma_cap.rx_fifo_size;
|
||||
|
||||
/* No pause frame is emitted if we don't have at least 4096 bytes per
|
||||
* queue, except on dwmac100.
|
||||
*/
|
||||
if (priv->plat->core_type != DWMAC_CORE_MAC100 &&
|
||||
rx_fifo_size / priv->plat->rx_queues_to_use < 4096)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
tpriv = kzalloc_obj(*tpriv);
|
||||
if (!tpriv)
|
||||
return -ENOMEM;
|
||||
@@ -737,9 +770,7 @@ static int stmmac_test_flowctrl(struct stmmac_priv *priv)
|
||||
dev_add_pack(&tpriv->pt);
|
||||
|
||||
/* Compute minimum number of packets to make FIFO full */
|
||||
pkt_count = priv->plat->rx_fifo_size;
|
||||
if (!pkt_count)
|
||||
pkt_count = priv->dma_cap.rx_fifo_size;
|
||||
pkt_count = rx_fifo_size;
|
||||
pkt_count /= 1400;
|
||||
pkt_count *= 2;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user