Skip to content

Commit

Permalink
Merge branch 'net-stmmac-Improvements-and-Selftests'
Browse files Browse the repository at this point in the history
Jose Abreu says:

====================
net: stmmac: Improvements and Selftests

[ Thanks to the introducion of selftests this series ended up being a misc
of improvements and the selftests additions per-se. ]

This introduces selftests support in stmmac driver. We add 9 basic sanity
checks and MAC loopback support for all cores within the driver. This way
more tests can easily be added in the future and can be run in virtually
any MAC/GMAC/QoS/XGMAC platform.

Having this we can find regressions and missing features in the driver
while at the same time we can check if the IP is correctly working.

We have been using this for some time now and I do have more tests to
submit in the feature. My experience is that although writing the tests
adds more development time, the gain results are obvious.

I let this feature optional within the driver under a Kconfig option.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed May 24, 2019
2 parents 33a74bf + a976ca7 commit 2294249
Show file tree
Hide file tree
Showing 21 changed files with 1,029 additions and 23 deletions.
9 changes: 9 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ config STMMAC_ETH

if STMMAC_ETH

config STMMAC_SELFTESTS
bool "Support for STMMAC Selftests"
depends on STMMAC_ETH
default n
---help---
This adds support for STMMAC Selftests using ethtool. Enable this
feature if you are facing problems with your HW and submit the test
results to the netdev Mailing List.

config STMMAC_PLATFORM
tristate "STMMAC Platform bus support"
depends on STMMAC_ETH
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \
$(stmmac-y)

stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o

# Ordering matters. Generic driver must be last.
obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
obj-$(CONFIG_DWMAC_ANARION) += dwmac-anarion.o
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/stmicro/stmmac/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ struct mac_device_info {
const struct stmmac_mode_ops *mode;
const struct stmmac_hwtimestamp *ptp;
const struct stmmac_tc_ops *tc;
const struct stmmac_mmc_ops *mmc;
struct mii_regs mii; /* MII register Addresses */
struct mac_link link;
void __iomem *pcsr; /* vpointer to device CSRs */
Expand Down
13 changes: 13 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,18 @@ static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv)
regulator_disable(gmac->regulator);
}

static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable)
{
u32 value = readl(ioaddr + EMAC_BASIC_CTL0);

if (enable)
value |= EMAC_LOOPBACK;
else
value &= ~EMAC_LOOPBACK;

writel(value, ioaddr + EMAC_BASIC_CTL0);
}

static const struct stmmac_ops sun8i_dwmac_ops = {
.core_init = sun8i_dwmac_core_init,
.set_mac = sun8i_dwmac_set_mac,
Expand All @@ -995,6 +1007,7 @@ static const struct stmmac_ops sun8i_dwmac_ops = {
.flow_ctrl = sun8i_dwmac_flow_ctrl,
.set_umac_addr = sun8i_dwmac_set_umac_addr,
.get_umac_addr = sun8i_dwmac_get_umac_addr,
.set_mac_loopback = sun8i_dwmac_set_mac_loopback,
};

static struct mac_device_info *sun8i_dwmac_setup(void *ppriv)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ enum inter_frame_gap {
#define GMAC_FRAME_FILTER_DAIF 0x00000008 /* DA Inverse Filtering */
#define GMAC_FRAME_FILTER_PM 0x00000010 /* Pass all multicast */
#define GMAC_FRAME_FILTER_DBF 0x00000020 /* Disable Broadcast frames */
#define GMAC_FRAME_FILTER_PCF 0x00000080 /* Pass Control frames */
#define GMAC_FRAME_FILTER_SAIF 0x00000100 /* Inverse Filtering */
#define GMAC_FRAME_FILTER_SAF 0x00000200 /* Source Address Filter */
#define GMAC_FRAME_FILTER_HPF 0x00000400 /* Hash or perfect Filter */
Expand Down
22 changes: 21 additions & 1 deletion drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ static void dwmac1000_set_filter(struct mac_device_info *hw,
memset(mc_filter, 0, sizeof(mc_filter));

if (dev->flags & IFF_PROMISC) {
value = GMAC_FRAME_FILTER_PR;
value = GMAC_FRAME_FILTER_PR | GMAC_FRAME_FILTER_PCF;
} else if (dev->flags & IFF_ALLMULTI) {
value = GMAC_FRAME_FILTER_PM; /* pass all multi */
} else if (!netdev_mc_empty(dev)) {
Expand All @@ -198,6 +198,7 @@ static void dwmac1000_set_filter(struct mac_device_info *hw,
}
}

value |= GMAC_FRAME_FILTER_HPF;
dwmac1000_set_mchash(ioaddr, mc_filter, mcbitslog2);

/* Handle multiple unicast addresses (perfect filtering) */
Expand All @@ -216,6 +217,12 @@ static void dwmac1000_set_filter(struct mac_device_info *hw,
GMAC_ADDR_LOW(reg));
reg++;
}

while (reg <= perfect_addr_number) {
writel(0, ioaddr + GMAC_ADDR_HIGH(reg));
writel(0, ioaddr + GMAC_ADDR_LOW(reg));
reg++;
}
}

#ifdef FRAME_FILTER_DEBUG
Expand Down Expand Up @@ -499,6 +506,18 @@ static void dwmac1000_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x,
x->mac_gmii_rx_proto_engine++;
}

static void dwmac1000_set_mac_loopback(void __iomem *ioaddr, bool enable)
{
u32 value = readl(ioaddr + GMAC_CONTROL);

if (enable)
value |= GMAC_CONTROL_LM;
else
value &= ~GMAC_CONTROL_LM;

writel(value, ioaddr + GMAC_CONTROL);
}

const struct stmmac_ops dwmac1000_ops = {
.core_init = dwmac1000_core_init,
.set_mac = stmmac_set_mac,
Expand All @@ -518,6 +537,7 @@ const struct stmmac_ops dwmac1000_ops = {
.pcs_ctrl_ane = dwmac1000_ctrl_ane,
.pcs_rane = dwmac1000_rane,
.pcs_get_adv_lp = dwmac1000_get_adv_lp,
.set_mac_loopback = dwmac1000_set_mac_loopback,
};

int dwmac1000_setup(struct stmmac_priv *priv)
Expand Down
13 changes: 13 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,18 @@ static void dwmac100_pmt(struct mac_device_info *hw, unsigned long mode)
return;
}

static void dwmac100_set_mac_loopback(void __iomem *ioaddr, bool enable)
{
u32 value = readl(ioaddr + MAC_CONTROL);

if (enable)
value |= MAC_CONTROL_OM;
else
value &= ~MAC_CONTROL_OM;

writel(value, ioaddr + MAC_CONTROL);
}

const struct stmmac_ops dwmac100_ops = {
.core_init = dwmac100_core_init,
.set_mac = stmmac_set_mac,
Expand All @@ -171,6 +183,7 @@ const struct stmmac_ops dwmac100_ops = {
.pmt = dwmac100_pmt,
.set_umac_addr = dwmac100_set_umac_addr,
.get_umac_addr = dwmac100_get_umac_addr,
.set_mac_loopback = dwmac100_set_mac_loopback,
};

int dwmac100_setup(struct stmmac_priv *priv)
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwmac4.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
#define GMAC_PACKET_FILTER_PR BIT(0)
#define GMAC_PACKET_FILTER_HMC BIT(2)
#define GMAC_PACKET_FILTER_PM BIT(4)
#define GMAC_PACKET_FILTER_PCF BIT(7)
#define GMAC_PACKET_FILTER_HPF BIT(10)

#define GMAC_MAX_PERFECT_ADDRESSES 128

Expand Down Expand Up @@ -160,6 +162,7 @@ enum power_event {
#define GMAC_CONFIG_PS BIT(15)
#define GMAC_CONFIG_FES BIT(14)
#define GMAC_CONFIG_DM BIT(13)
#define GMAC_CONFIG_LM BIT(12)
#define GMAC_CONFIG_DCRS BIT(9)
#define GMAC_CONFIG_TE BIT(1)
#define GMAC_CONFIG_RE BIT(0)
Expand Down
29 changes: 26 additions & 3 deletions drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
unsigned int value = 0;

if (dev->flags & IFF_PROMISC) {
value = GMAC_PACKET_FILTER_PR;
value = GMAC_PACKET_FILTER_PR | GMAC_PACKET_FILTER_PCF;
} else if ((dev->flags & IFF_ALLMULTI) ||
(netdev_mc_count(dev) > HASH_TABLE_SIZE)) {
/* Pass all multi */
Expand Down Expand Up @@ -440,20 +440,28 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
writel(mc_filter[1], ioaddr + GMAC_HASH_TAB_32_63);
}

value |= GMAC_PACKET_FILTER_HPF;

/* Handle multiple unicast addresses */
if (netdev_uc_count(dev) > GMAC_MAX_PERFECT_ADDRESSES) {
/* Switch to promiscuous mode if more than 128 addrs
* are required
*/
value |= GMAC_PACKET_FILTER_PR;
} else if (!netdev_uc_empty(dev)) {
int reg = 1;
} else {
struct netdev_hw_addr *ha;
int reg = 1;

netdev_for_each_uc_addr(ha, dev) {
dwmac4_set_umac_addr(hw, ha->addr, reg);
reg++;
}

while (reg <= GMAC_MAX_PERFECT_ADDRESSES) {
writel(0, ioaddr + GMAC_ADDR_HIGH(reg));
writel(0, ioaddr + GMAC_ADDR_LOW(reg));
reg++;
}
}

writel(value, ioaddr + GMAC_PACKET_FILTER);
Expand Down Expand Up @@ -703,6 +711,18 @@ static void dwmac4_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x,
x->mac_gmii_rx_proto_engine++;
}

static void dwmac4_set_mac_loopback(void __iomem *ioaddr, bool enable)
{
u32 value = readl(ioaddr + GMAC_CONFIG);

if (enable)
value |= GMAC_CONFIG_LM;
else
value &= ~GMAC_CONFIG_LM;

writel(value, ioaddr + GMAC_CONFIG);
}

const struct stmmac_ops dwmac4_ops = {
.core_init = dwmac4_core_init,
.set_mac = stmmac_set_mac,
Expand Down Expand Up @@ -732,6 +752,7 @@ const struct stmmac_ops dwmac4_ops = {
.pcs_get_adv_lp = dwmac4_get_adv_lp,
.debug = dwmac4_debug,
.set_filter = dwmac4_set_filter,
.set_mac_loopback = dwmac4_set_mac_loopback,
};

const struct stmmac_ops dwmac410_ops = {
Expand Down Expand Up @@ -763,6 +784,7 @@ const struct stmmac_ops dwmac410_ops = {
.pcs_get_adv_lp = dwmac4_get_adv_lp,
.debug = dwmac4_debug,
.set_filter = dwmac4_set_filter,
.set_mac_loopback = dwmac4_set_mac_loopback,
};

const struct stmmac_ops dwmac510_ops = {
Expand Down Expand Up @@ -799,6 +821,7 @@ const struct stmmac_ops dwmac510_ops = {
.safety_feat_dump = dwmac5_safety_feat_dump,
.rxp_config = dwmac5_rxp_config,
.flex_pps_config = dwmac5_flex_pps_config,
.set_mac_loopback = dwmac4_set_mac_loopback,
};

int dwmac4_setup(struct stmmac_priv *priv)
Expand Down
4 changes: 0 additions & 4 deletions drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ void dwmac4_dma_stop_rx(void __iomem *ioaddr, u32 chan)

value &= ~DMA_CONTROL_SR;
writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan));

value = readl(ioaddr + GMAC_CONFIG);
value &= ~GMAC_CONFIG_RE;
writel(value, ioaddr + GMAC_CONFIG);
}

void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len, u32 chan)
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#define XGMAC_CONFIG_GPSL GENMASK(29, 16)
#define XGMAC_CONFIG_GPSL_SHIFT 16
#define XGMAC_CONFIG_S2KP BIT(11)
#define XGMAC_CONFIG_LM BIT(10)
#define XGMAC_CONFIG_IPC BIT(9)
#define XGMAC_CONFIG_JE BIT(8)
#define XGMAC_CONFIG_WD BIT(7)
Expand All @@ -39,6 +40,7 @@
#define XGMAC_CORE_INIT_RX 0
#define XGMAC_PACKET_FILTER 0x00000008
#define XGMAC_FILTER_RA BIT(31)
#define XGMAC_FILTER_PCF BIT(7)
#define XGMAC_FILTER_PM BIT(4)
#define XGMAC_FILTER_HMC BIT(2)
#define XGMAC_FILTER_PR BIT(0)
Expand Down
15 changes: 14 additions & 1 deletion drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,
u32 value = XGMAC_FILTER_RA;

if (dev->flags & IFF_PROMISC) {
value |= XGMAC_FILTER_PR;
value |= XGMAC_FILTER_PR | XGMAC_FILTER_PCF;
} else if ((dev->flags & IFF_ALLMULTI) ||
(netdev_mc_count(dev) > HASH_TABLE_SIZE)) {
value |= XGMAC_FILTER_PM;
Expand All @@ -321,6 +321,18 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,
writel(value, ioaddr + XGMAC_PACKET_FILTER);
}

static void dwxgmac2_set_mac_loopback(void __iomem *ioaddr, bool enable)
{
u32 value = readl(ioaddr + XGMAC_RX_CONFIG);

if (enable)
value |= XGMAC_CONFIG_LM;
else
value &= ~XGMAC_CONFIG_LM;

writel(value, ioaddr + XGMAC_RX_CONFIG);
}

const struct stmmac_ops dwxgmac210_ops = {
.core_init = dwxgmac2_core_init,
.set_mac = dwxgmac2_set_mac,
Expand Down Expand Up @@ -350,6 +362,7 @@ const struct stmmac_ops dwxgmac210_ops = {
.pcs_get_adv_lp = NULL,
.debug = NULL,
.set_filter = dwxgmac2_set_filter,
.set_mac_loopback = dwxgmac2_set_mac_loopback,
};

int dwxgmac2_setup(struct stmmac_priv *priv)
Expand Down
4 changes: 0 additions & 4 deletions drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,6 @@ static void dwxgmac2_dma_stop_rx(void __iomem *ioaddr, u32 chan)
value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
value &= ~XGMAC_RXST;
writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));

value = readl(ioaddr + XGMAC_RX_CONFIG);
value &= ~XGMAC_CONFIG_RE;
writel(value, ioaddr + XGMAC_RX_CONFIG);
}

static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/hwif.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ static const struct stmmac_hwif_entry {
const void *hwtimestamp;
const void *mode;
const void *tc;
const void *mmc;
int (*setup)(struct stmmac_priv *priv);
int (*quirks)(struct stmmac_priv *priv);
} stmmac_hw[] = {
Expand All @@ -100,6 +101,7 @@ static const struct stmmac_hwif_entry {
.hwtimestamp = &stmmac_ptp,
.mode = NULL,
.tc = NULL,
.mmc = &dwmac_mmc_ops,
.setup = dwmac100_setup,
.quirks = stmmac_dwmac1_quirks,
}, {
Expand All @@ -117,6 +119,7 @@ static const struct stmmac_hwif_entry {
.hwtimestamp = &stmmac_ptp,
.mode = NULL,
.tc = NULL,
.mmc = &dwmac_mmc_ops,
.setup = dwmac1000_setup,
.quirks = stmmac_dwmac1_quirks,
}, {
Expand All @@ -134,6 +137,7 @@ static const struct stmmac_hwif_entry {
.hwtimestamp = &stmmac_ptp,
.mode = NULL,
.tc = &dwmac510_tc_ops,
.mmc = &dwmac_mmc_ops,
.setup = dwmac4_setup,
.quirks = stmmac_dwmac4_quirks,
}, {
Expand All @@ -151,6 +155,7 @@ static const struct stmmac_hwif_entry {
.hwtimestamp = &stmmac_ptp,
.mode = &dwmac4_ring_mode_ops,
.tc = &dwmac510_tc_ops,
.mmc = &dwmac_mmc_ops,
.setup = dwmac4_setup,
.quirks = NULL,
}, {
Expand All @@ -168,6 +173,7 @@ static const struct stmmac_hwif_entry {
.hwtimestamp = &stmmac_ptp,
.mode = &dwmac4_ring_mode_ops,
.tc = &dwmac510_tc_ops,
.mmc = &dwmac_mmc_ops,
.setup = dwmac4_setup,
.quirks = NULL,
}, {
Expand All @@ -185,6 +191,7 @@ static const struct stmmac_hwif_entry {
.hwtimestamp = &stmmac_ptp,
.mode = &dwmac4_ring_mode_ops,
.tc = &dwmac510_tc_ops,
.mmc = &dwmac_mmc_ops,
.setup = dwmac4_setup,
.quirks = NULL,
}, {
Expand All @@ -202,6 +209,7 @@ static const struct stmmac_hwif_entry {
.hwtimestamp = &stmmac_ptp,
.mode = NULL,
.tc = &dwmac510_tc_ops,
.mmc = NULL,
.setup = dwxgmac2_setup,
.quirks = NULL,
},
Expand Down Expand Up @@ -267,6 +275,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
mac->ptp = mac->ptp ? : entry->hwtimestamp;
mac->mode = mac->mode ? : entry->mode;
mac->tc = mac->tc ? : entry->tc;
mac->mmc = mac->mmc ? : entry->mmc;

priv->hw = mac;
priv->ptpaddr = priv->ioaddr + entry->regs.ptp_off;
Expand Down
Loading

0 comments on commit 2294249

Please sign in to comment.