diff options
Diffstat (limited to 'drivers/net/ethernet/stmicro')
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 22 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 119 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 29 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 17 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/hwif.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 25 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c | 114 |
12 files changed, 318 insertions, 51 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c index 79f2ee37afed..cea7a0c7ce68 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c @@ -130,6 +130,31 @@ static void mt2712_delay_ps2stage(struct mediatek_dwmac_plat_data *plat) } } +static void mt2712_delay_stage2ps(struct mediatek_dwmac_plat_data *plat) +{ + struct mac_delay_struct *mac_delay = &plat->mac_delay; + + switch (plat->phy_mode) { + case PHY_INTERFACE_MODE_MII: + case PHY_INTERFACE_MODE_RMII: + /* 550ps per stage for MII/RMII */ + mac_delay->tx_delay *= 550; + mac_delay->rx_delay *= 550; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_TXID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: + /* 170ps per stage for RGMII */ + mac_delay->tx_delay *= 170; + mac_delay->rx_delay *= 170; + break; + default: + dev_err(plat->dev, "phy interface not supported\n"); + break; + } +} + static int mt2712_set_delay(struct mediatek_dwmac_plat_data *plat) { struct mac_delay_struct *mac_delay = &plat->mac_delay; @@ -199,6 +224,8 @@ static int mt2712_set_delay(struct mediatek_dwmac_plat_data *plat) regmap_write(plat->peri_regmap, PERI_ETH_DLY, delay_val); regmap_write(plat->peri_regmap, PERI_ETH_DLY_FINE, fine_val); + mt2712_delay_stage2ps(plat); + return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index 3d69da112625..d0356fbd1e43 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -130,7 +130,6 @@ static void dwmac1000_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits, writel(mcfilterbits[0], ioaddr + GMAC_HASH_LOW); writel(mcfilterbits[1], ioaddr + GMAC_HASH_HIGH); return; - break; case 7: numhashregs = 4; break; @@ -140,7 +139,6 @@ static void dwmac1000_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits, default: pr_debug("STMMAC: err in setting multicast filter\n"); return; - break; } for (regs = 0; regs < numhashregs; regs++) writel(mcfilterbits[regs], diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h index 89a3420eba42..07e97f45755d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h @@ -43,6 +43,10 @@ #define GMAC_ARP_ADDR 0x00000210 #define GMAC_ADDR_HIGH(reg) (0x300 + reg * 8) #define GMAC_ADDR_LOW(reg) (0x304 + reg * 8) +#define GMAC_L3L4_CTRL(reg) (0x900 + (reg) * 0x30) +#define GMAC_L4_ADDR(reg) (0x904 + (reg) * 0x30) +#define GMAC_L3_ADDR0(reg) (0x910 + (reg) * 0x30) +#define GMAC_L3_ADDR1(reg) (0x914 + (reg) * 0x30) /* RX Queues Routing */ #define GMAC_RXQCTRL_AVCPQ_MASK GENMASK(2, 0) @@ -67,6 +71,7 @@ #define GMAC_PACKET_FILTER_PCF BIT(7) #define GMAC_PACKET_FILTER_HPF BIT(10) #define GMAC_PACKET_FILTER_VTFE BIT(16) +#define GMAC_PACKET_FILTER_IPFE BIT(20) #define GMAC_MAX_PERFECT_ADDRESSES 128 @@ -202,9 +207,11 @@ enum power_event { #define GMAC_HW_FEAT_MIISEL BIT(0) /* MAC HW features1 bitmap */ +#define GMAC_HW_FEAT_L3L4FNUM GENMASK(30, 27) #define GMAC_HW_HASH_TB_SZ GENMASK(25, 24) #define GMAC_HW_FEAT_AVSEL BIT(20) #define GMAC_HW_TSOEN BIT(18) +#define GMAC_HW_ADDR64 GENMASK(15, 14) #define GMAC_HW_TXFIFOSIZE GENMASK(10, 6) #define GMAC_HW_RXFIFOSIZE GENMASK(4, 0) @@ -227,6 +234,21 @@ enum power_event { #define GMAC_HI_DCS_SHIFT 16 #define GMAC_HI_REG_AE BIT(31) +/* L3/L4 Filters regs */ +#define GMAC_L4DPIM0 BIT(21) +#define GMAC_L4DPM0 BIT(20) +#define GMAC_L4SPIM0 BIT(19) +#define GMAC_L4SPM0 BIT(18) +#define GMAC_L4PEN0 BIT(16) +#define GMAC_L3DAIM0 BIT(5) +#define GMAC_L3DAM0 BIT(4) +#define GMAC_L3SAIM0 BIT(3) +#define GMAC_L3SAM0 BIT(2) +#define GMAC_L3PEN0 BIT(0) +#define GMAC_L4DP0 GENMASK(31, 16) +#define GMAC_L4DP0_SHIFT 16 +#define GMAC_L4SP0 GENMASK(15, 0) + /* MTL registers */ #define MTL_OPERATION_MODE 0x00000c00 #define MTL_FRPE BIT(15) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index 5a7b0aca1d31..bec929daf703 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -733,7 +733,7 @@ static void dwmac4_set_mac_loopback(void __iomem *ioaddr, bool enable) } static void dwmac4_update_vlan_hash(struct mac_device_info *hw, u32 hash, - bool is_double) + u16 perfect_match, bool is_double) { void __iomem *ioaddr = hw->pcsr; @@ -748,6 +748,16 @@ static void dwmac4_update_vlan_hash(struct mac_device_info *hw, u32 hash, } writel(value, ioaddr + GMAC_VLAN_TAG); + } else if (perfect_match) { + u32 value = GMAC_VLAN_ETV; + + if (is_double) { + value |= GMAC_VLAN_EDVLP; + value |= GMAC_VLAN_ESVL; + value |= GMAC_VLAN_DOVLTC; + } + + writel(value | perfect_match, ioaddr + GMAC_VLAN_TAG); } else { u32 value = readl(ioaddr + GMAC_VLAN_TAG); @@ -799,6 +809,106 @@ static void dwmac4_set_arp_offload(struct mac_device_info *hw, bool en, writel(value, ioaddr + GMAC_CONFIG); } +static int dwmac4_config_l3_filter(struct mac_device_info *hw, u32 filter_no, + bool en, bool ipv6, bool sa, bool inv, + u32 match) +{ + void __iomem *ioaddr = hw->pcsr; + u32 value; + + value = readl(ioaddr + GMAC_PACKET_FILTER); + value |= GMAC_PACKET_FILTER_IPFE; + writel(value, ioaddr + GMAC_PACKET_FILTER); + + value = readl(ioaddr + GMAC_L3L4_CTRL(filter_no)); + + /* For IPv6 not both SA/DA filters can be active */ + if (ipv6) { + value |= GMAC_L3PEN0; + value &= ~(GMAC_L3SAM0 | GMAC_L3SAIM0); + value &= ~(GMAC_L3DAM0 | GMAC_L3DAIM0); + if (sa) { + value |= GMAC_L3SAM0; + if (inv) + value |= GMAC_L3SAIM0; + } else { + value |= GMAC_L3DAM0; + if (inv) + value |= GMAC_L3DAIM0; + } + } else { + value &= ~GMAC_L3PEN0; + if (sa) { + value |= GMAC_L3SAM0; + if (inv) + value |= GMAC_L3SAIM0; + } else { + value |= GMAC_L3DAM0; + if (inv) + value |= GMAC_L3DAIM0; + } + } + + writel(value, ioaddr + GMAC_L3L4_CTRL(filter_no)); + + if (sa) { + writel(match, ioaddr + GMAC_L3_ADDR0(filter_no)); + } else { + writel(match, ioaddr + GMAC_L3_ADDR1(filter_no)); + } + + if (!en) + writel(0, ioaddr + GMAC_L3L4_CTRL(filter_no)); + + return 0; +} + +static int dwmac4_config_l4_filter(struct mac_device_info *hw, u32 filter_no, + bool en, bool udp, bool sa, bool inv, + u32 match) +{ + void __iomem *ioaddr = hw->pcsr; + u32 value; + + value = readl(ioaddr + GMAC_PACKET_FILTER); + value |= GMAC_PACKET_FILTER_IPFE; + writel(value, ioaddr + GMAC_PACKET_FILTER); + + value = readl(ioaddr + GMAC_L3L4_CTRL(filter_no)); + if (udp) { + value |= GMAC_L4PEN0; + } else { + value &= ~GMAC_L4PEN0; + } + + value &= ~(GMAC_L4SPM0 | GMAC_L4SPIM0); + value &= ~(GMAC_L4DPM0 | GMAC_L4DPIM0); + if (sa) { + value |= GMAC_L4SPM0; + if (inv) + value |= GMAC_L4SPIM0; + } else { + value |= GMAC_L4DPM0; + if (inv) + value |= GMAC_L4DPIM0; + } + + writel(value, ioaddr + GMAC_L3L4_CTRL(filter_no)); + + if (sa) { + value = match & GMAC_L4SP0; + } else { + value = (match << GMAC_L4DP0_SHIFT) & GMAC_L4DP0; + } + + writel(value, ioaddr + GMAC_L4_ADDR(filter_no)); + + if (!en) + writel(0, ioaddr + GMAC_L3L4_CTRL(filter_no)); + + return 0; +} + const struct stmmac_ops dwmac4_ops = { .core_init = dwmac4_core_init, .set_mac = stmmac_set_mac, @@ -828,11 +938,14 @@ const struct stmmac_ops dwmac4_ops = { .pcs_get_adv_lp = dwmac4_get_adv_lp, .debug = dwmac4_debug, .set_filter = dwmac4_set_filter, + .flex_pps_config = dwmac5_flex_pps_config, .set_mac_loopback = dwmac4_set_mac_loopback, .update_vlan_hash = dwmac4_update_vlan_hash, .sarc_configure = dwmac4_sarc_configure, .enable_vlan = dwmac4_enable_vlan, .set_arp_offload = dwmac4_set_arp_offload, + .config_l3_filter = dwmac4_config_l3_filter, + .config_l4_filter = dwmac4_config_l4_filter, }; const struct stmmac_ops dwmac410_ops = { @@ -869,6 +982,8 @@ const struct stmmac_ops dwmac410_ops = { .sarc_configure = dwmac4_sarc_configure, .enable_vlan = dwmac4_enable_vlan, .set_arp_offload = dwmac4_set_arp_offload, + .config_l3_filter = dwmac4_config_l3_filter, + .config_l4_filter = dwmac4_config_l4_filter, }; const struct stmmac_ops dwmac510_ops = { @@ -910,6 +1025,8 @@ const struct stmmac_ops dwmac510_ops = { .sarc_configure = dwmac4_sarc_configure, .enable_vlan = dwmac4_enable_vlan, .set_arp_offload = dwmac4_set_arp_offload, + .config_l3_filter = dwmac4_config_l3_filter, + .config_l4_filter = dwmac4_config_l4_filter, }; int dwmac4_setup(struct stmmac_priv *priv) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c index 15eb1abba91d..707ab5eba8da 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c @@ -431,8 +431,8 @@ static void dwmac4_get_addr(struct dma_desc *p, unsigned int *addr) static void dwmac4_set_addr(struct dma_desc *p, dma_addr_t addr) { - p->des0 = cpu_to_le32(addr); - p->des1 = 0; + p->des0 = cpu_to_le32(lower_32_bits(addr)); + p->des1 = cpu_to_le32(upper_32_bits(addr)); } static void dwmac4_clear(struct dma_desc *p) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c index 68c157979b94..b24c89572745 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c @@ -79,6 +79,10 @@ static void dwmac4_dma_init_rx_chan(void __iomem *ioaddr, value = value | (rxpbl << DMA_BUS_MODE_RPBL_SHIFT); writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan)); + if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) && likely(dma_cfg->eame)) + writel(upper_32_bits(dma_rx_phy), + ioaddr + DMA_CHAN_RX_BASE_ADDR_HI(chan)); + writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RX_BASE_ADDR(chan)); } @@ -97,6 +101,10 @@ static void dwmac4_dma_init_tx_chan(void __iomem *ioaddr, writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan)); + if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) && likely(dma_cfg->eame)) + writel(upper_32_bits(dma_tx_phy), + ioaddr + DMA_CHAN_TX_BASE_ADDR_HI(chan)); + writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan)); } @@ -132,6 +140,9 @@ static void dwmac4_dma_init(void __iomem *ioaddr, if (dma_cfg->aal) value |= DMA_SYS_BUS_AAL; + if (dma_cfg->eame) + value |= DMA_SYS_BUS_EAME; + writel(value, ioaddr + DMA_SYS_BUS_MODE); } @@ -353,9 +364,27 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr, /* MAC HW feature1 */ hw_cap = readl(ioaddr + GMAC_HW_FEATURE1); + dma_cap->l3l4fnum = (hw_cap & GMAC_HW_FEAT_L3L4FNUM) >> 27; dma_cap->hash_tb_sz = (hw_cap & GMAC_HW_HASH_TB_SZ) >> 24; dma_cap->av = (hw_cap & GMAC_HW_FEAT_AVSEL) >> 20; dma_cap->tsoen = (hw_cap & GMAC_HW_TSOEN) >> 18; + + dma_cap->addr64 = (hw_cap & GMAC_HW_ADDR64) >> 14; + switch (dma_cap->addr64) { + case 0: + dma_cap->addr64 = 32; + break; + case 1: + dma_cap->addr64 = 40; + break; + case 2: + dma_cap->addr64 = 48; + break; + default: + dma_cap->addr64 = 32; + break; + } + /* RX and TX FIFO sizes are encoded as log2(n / 128). Undo that by * shifting and store the sizes in bytes. */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h index b66da0237d2a..5299fa1001a3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h @@ -65,6 +65,7 @@ #define DMA_SYS_BUS_MB BIT(14) #define DMA_AXI_1KBBE BIT(13) #define DMA_SYS_BUS_AAL BIT(12) +#define DMA_SYS_BUS_EAME BIT(11) #define DMA_AXI_BLEN256 BIT(7) #define DMA_AXI_BLEN128 BIT(6) #define DMA_AXI_BLEN64 BIT(5) @@ -91,7 +92,9 @@ #define DMA_CHAN_CONTROL(x) DMA_CHANX_BASE_ADDR(x) #define DMA_CHAN_TX_CONTROL(x) (DMA_CHANX_BASE_ADDR(x) + 0x4) #define DMA_CHAN_RX_CONTROL(x) (DMA_CHANX_BASE_ADDR(x) + 0x8) +#define DMA_CHAN_TX_BASE_ADDR_HI(x) (DMA_CHANX_BASE_ADDR(x) + 0x10) #define DMA_CHAN_TX_BASE_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x14) +#define DMA_CHAN_RX_BASE_ADDR_HI(x) (DMA_CHANX_BASE_ADDR(x) + 0x18) #define DMA_CHAN_RX_BASE_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x1c) #define DMA_CHAN_TX_END_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x20) #define DMA_CHAN_RX_END_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x28) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 5031398e612c..5cda360d5d07 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -555,7 +555,7 @@ static int dwxgmac2_rss_configure(struct mac_device_info *hw, } static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash, - bool is_double) + u16 perfect_match, bool is_double) { void __iomem *ioaddr = hw->pcsr; @@ -576,6 +576,21 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash, } writel(value, ioaddr + XGMAC_VLAN_TAG); + } else if (perfect_match) { + u32 value = readl(ioaddr + XGMAC_PACKET_FILTER); + + value |= XGMAC_FILTER_VTFE; + + writel(value, ioaddr + XGMAC_PACKET_FILTER); + + value = XGMAC_VLAN_ETV; + if (is_double) { + value |= XGMAC_VLAN_EDVLP; + value |= XGMAC_VLAN_ESVL; + value |= XGMAC_VLAN_DOVLTC; + } + + writel(value | perfect_match, ioaddr + XGMAC_VLAN_TAG); } else { u32 value = readl(ioaddr + XGMAC_PACKET_FILTER); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index 965cbe3e6f51..7cc331996cd8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -27,7 +27,10 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr, if (dma_cfg->aal) value |= XGMAC_AAL; - writel(value | XGMAC_EAME, ioaddr + XGMAC_DMA_SYSBUS_MODE); + if (dma_cfg->eame) + value |= XGMAC_EAME; + + writel(value, ioaddr + XGMAC_DMA_SYSBUS_MODE); } static void dwxgmac2_dma_init_chan(void __iomem *ioaddr, diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index ddb851d99618..1303d1e9a18f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -357,7 +357,7 @@ struct stmmac_ops { struct stmmac_rss *cfg, u32 num_rxq); /* VLAN */ void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash, - bool is_double); + u16 perfect_match, bool is_double); void (*enable_vlan)(struct mac_device_info *hw, u32 type); /* TX Timestamp */ int (*get_mac_tx_timestamp)(struct mac_device_info *hw, u64 *ts); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 3dfd04e0506a..28705dbe5801 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -4207,15 +4207,25 @@ static u32 stmmac_vid_crc32_le(__le16 vid_le) static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double) { u32 crc, hash = 0; - u16 vid; + int count = 0; + u16 vid = 0; for_each_set_bit(vid, priv->active_vlans, VLAN_N_VID) { __le16 vid_le = cpu_to_le16(vid); crc = bitrev32(~stmmac_vid_crc32_le(vid_le)) >> 28; hash |= (1 << crc); + count++; + } + + if (!priv->dma_cap.vlhash) { + if (count > 2) /* VID = 0 always passes filter */ + return -EOPNOTSUPP; + + vid = cpu_to_le16(vid); + hash = 0; } - return stmmac_update_vlan_hash(priv, priv->hw, hash, is_double); + return stmmac_update_vlan_hash(priv, priv->hw, hash, vid, is_double); } static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid) @@ -4224,8 +4234,6 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid bool is_double = false; int ret; - if (!priv->dma_cap.vlhash) - return -EOPNOTSUPP; if (be16_to_cpu(proto) == ETH_P_8021AD) is_double = true; @@ -4244,8 +4252,6 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi struct stmmac_priv *priv = netdev_priv(ndev); bool is_double = false; - if (!priv->dma_cap.vlhash) - return -EOPNOTSUPP; if (be16_to_cpu(proto) == ETH_P_8021AD) is_double = true; @@ -4515,6 +4521,13 @@ int stmmac_dvr_probe(struct device *device, if (!ret) { dev_info(priv->device, "Using %d bits DMA width\n", priv->dma_cap.addr64); + + /* + * If more than 32 bits can be addressed, make sure to + * enable enhanced addressing mode. + */ + if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT)) + priv->plat->dma_cfg->eame = true; } else { ret = dma_set_mask_and_coherent(device, DMA_BIT_MASK(32)); if (ret) { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index e4ac3c401432..0b5db52149bc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c @@ -823,16 +823,13 @@ out: return 0; } -static int stmmac_test_vlanfilt(struct stmmac_priv *priv) +static int __stmmac_test_vlanfilt(struct stmmac_priv *priv) { struct stmmac_packet_attrs attr = { }; struct stmmac_test_priv *tpriv; struct sk_buff *skb = NULL; int ret = 0, i; - if (!priv->dma_cap.vlhash) - return -EOPNOTSUPP; - tpriv = kzalloc(sizeof(*tpriv), GFP_KERNEL); if (!tpriv) return -ENOMEM; @@ -898,16 +895,32 @@ cleanup: return ret; } -static int stmmac_test_dvlanfilt(struct stmmac_priv *priv) +static int stmmac_test_vlanfilt(struct stmmac_priv *priv) +{ + if (!priv->dma_cap.vlhash) + return -EOPNOTSUPP; + + return __stmmac_test_vlanfilt(priv); +} + +static int stmmac_test_vlanfilt_perfect(struct stmmac_priv *priv) +{ + int ret, prev_cap = priv->dma_cap.vlhash; + + priv->dma_cap.vlhash = 0; + ret = __stmmac_test_vlanfilt(priv); + priv->dma_cap.vlhash = prev_cap; + + return ret; +} + +static int __stmmac_test_dvlanfilt(struct stmmac_priv *priv) { struct stmmac_packet_attrs attr = { }; struct stmmac_test_priv *tpriv; struct sk_buff *skb = NULL; int ret = 0, i; - if (!priv->dma_cap.vlhash) - return -EOPNOTSUPP; - tpriv = kzalloc(sizeof(*tpriv), GFP_KERNEL); if (!tpriv) return -ENOMEM; @@ -974,6 +987,25 @@ cleanup: return ret; } +static int stmmac_test_dvlanfilt(struct stmmac_priv *priv) +{ + if (!priv->dma_cap.vlhash) + return -EOPNOTSUPP; + + return __stmmac_test_dvlanfilt(priv); +} + +static int stmmac_test_dvlanfilt_perfect(struct stmmac_priv *priv) +{ + int ret, prev_cap = priv->dma_cap.vlhash; + + priv->dma_cap.vlhash = 0; + ret = __stmmac_test_dvlanfilt(priv); + priv->dma_cap.vlhash = prev_cap; + + return ret; +} + #ifdef CONFIG_NET_CLS_ACT static int stmmac_test_rxp(struct stmmac_priv *priv) { @@ -1648,119 +1680,127 @@ static const struct stmmac_test { int (*fn)(struct stmmac_priv *priv); } stmmac_selftests[] = { { - .name = "MAC Loopback ", + .name = "MAC Loopback ", .lb = STMMAC_LOOPBACK_MAC, .fn = stmmac_test_mac_loopback, }, { - .name = "PHY Loopback ", + .name = "PHY Loopback ", .lb = STMMAC_LOOPBACK_NONE, /* Test will handle it */ .fn = stmmac_test_phy_loopback, }, { - .name = "MMC Counters ", + .name = "MMC Counters ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_mmc, }, { - .name = "EEE ", + .name = "EEE ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_eee, }, { - .name = "Hash Filter MC ", + .name = "Hash Filter MC ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_hfilt, }, { - .name = "Perfect Filter UC ", + .name = "Perfect Filter UC ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_pfilt, }, { - .name = "MC Filter ", + .name = "MC Filter ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_mcfilt, }, { - .name = "UC Filter ", + .name = "UC Filter ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_ucfilt, }, { - .name = "Flow Control ", + .name = "Flow Control ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_flowctrl, }, { - .name = "RSS ", + .name = "RSS ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_rss, }, { - .name = "VLAN Filtering ", + .name = "VLAN Filtering ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_vlanfilt, }, { - .name = "Double VLAN Filtering", + .name = "VLAN Filtering (perf) ", + .lb = STMMAC_LOOPBACK_PHY, + .fn = stmmac_test_vlanfilt_perfect, + }, { + .name = "Double VLAN Filter ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_dvlanfilt, }, { - .name = "Flexible RX Parser ", + .name = "Double VLAN Filter (perf) ", + .lb = STMMAC_LOOPBACK_PHY, + .fn = stmmac_test_dvlanfilt_perfect, + }, { + .name = "Flexible RX Parser ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_rxp, }, { - .name = "SA Insertion (desc) ", + .name = "SA Insertion (desc) ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_desc_sai, }, { - .name = "SA Replacement (desc)", + .name = "SA Replacement (desc) ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_desc_sar, }, { - .name = "SA Insertion (reg) ", + .name = "SA Insertion (reg) ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_reg_sai, }, { - .name = "SA Replacement (reg)", + .name = "SA Replacement (reg) ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_reg_sar, }, { - .name = "VLAN TX Insertion ", + .name = "VLAN TX Insertion ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_vlanoff, }, { - .name = "SVLAN TX Insertion ", + .name = "SVLAN TX Insertion ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_svlanoff, }, { - .name = "L3 DA Filtering ", + .name = "L3 DA Filtering ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_l3filt_da, }, { - .name = "L3 SA Filtering ", + .name = "L3 SA Filtering ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_l3filt_sa, }, { - .name = "L4 DA TCP Filtering ", + .name = "L4 DA TCP Filtering ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_l4filt_da_tcp, }, { - .name = "L4 SA TCP Filtering ", + .name = "L4 SA TCP Filtering ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_l4filt_sa_tcp, }, { - .name = "L4 DA UDP Filtering ", + .name = "L4 DA UDP Filtering ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_l4filt_da_udp, }, { - .name = "L4 SA UDP Filtering ", + .name = "L4 SA UDP Filtering ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_l4filt_sa_udp, }, { - .name = "ARP Offload ", + .name = "ARP Offload ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_arpoffload, }, { - .name = "Jumbo Frame ", + .name = "Jumbo Frame ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_jumbo, }, { - .name = "Multichannel Jumbo ", + .name = "Multichannel Jumbo ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_mjumbo, }, { - .name = "Split Header ", + .name = "Split Header ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_sph, }, |