diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt index a2acd2b26baf78c8aafc3948d7dc7cb012c09db5..9b03c57563a49d2145fb47c2a5086ff71506fe3f 100644 --- a/Documentation/devicetree/bindings/net/stmmac.txt +++ b/Documentation/devicetree/bindings/net/stmmac.txt @@ -25,6 +25,10 @@ Required properties: - snps,force_sf_dma_mode Force DMA to use the Store and Forward mode for both tx and rx. This flag is ignored if force_thresh_dma_mode is set. +- snps,multicast-filter-bins: Number of multicast filter hash bins + supported by this device instance +- snps,perfect-filter-entries: Number of perfect filter entries supported + by this device instance Optional properties: - resets: Should contain a phandle to the STMMAC reset signal, if any @@ -47,6 +51,8 @@ Examples: mac-address = [000000000000]; /* Filled in by U-Boot */ max-frame-size = <3800>; phy-mode = "gmii"; + snps,multicast-filter-bins = <256>; + snps,perfect-filter-entries = <128>; clocks = <&clock>; clock-names = "stmmaceth">; }; diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi index 4676f25e87a7e4e4c79023db4c289be156e2ea85..70fdd20648118d27807447b4213ff3fc9962e791 100644 --- a/arch/arm/boot/dts/socfpga.dtsi +++ b/arch/arm/boot/dts/socfpga.dtsi @@ -486,6 +486,8 @@ clock-names = "stmmaceth"; resets = <&rst EMAC0_RESET>; reset-names = "stmmaceth"; + snps,multicast-filter-bins = <256>; + snps,perfect-filter-entries = <128>; status = "disabled"; }; @@ -500,6 +502,8 @@ clock-names = "stmmaceth"; resets = <&rst EMAC1_RESET>; reset-names = "stmmaceth"; + snps,multicast-filter-bins = <256>; + snps,perfect-filter-entries = <128>; status = "disabled"; }; diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 74610f3aca9e5bc8670c49f4a25901c4b4575136..de507c32036c75331e393ad5b013890ffffb9d1b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -368,34 +368,36 @@ struct stmmac_dma_ops { void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt); }; +struct mac_device_info; + struct stmmac_ops { /* MAC core initialization */ - void (*core_init) (void __iomem *ioaddr, int mtu); + void (*core_init)(struct mac_device_info *hw, int mtu); /* Enable and verify that the IPC module is supported */ - int (*rx_ipc) (void __iomem *ioaddr); + int (*rx_ipc)(struct mac_device_info *hw); /* Dump MAC registers */ - void (*dump_regs) (void __iomem *ioaddr); + void (*dump_regs)(struct mac_device_info *hw); /* Handle extra events on specific interrupts hw dependent */ - int (*host_irq_status) (void __iomem *ioaddr, - struct stmmac_extra_stats *x); + int (*host_irq_status)(struct mac_device_info *hw, + struct stmmac_extra_stats *x); /* Multicast filter setting */ - void (*set_filter) (struct net_device *dev, int id); + void (*set_filter)(struct mac_device_info *hw, struct net_device *dev); /* Flow control setting */ - void (*flow_ctrl) (void __iomem *ioaddr, unsigned int duplex, - unsigned int fc, unsigned int pause_time); + void (*flow_ctrl)(struct mac_device_info *hw, unsigned int duplex, + unsigned int fc, unsigned int pause_time); /* Set power management mode (e.g. magic frame) */ - void (*pmt) (void __iomem *ioaddr, unsigned long mode); + void (*pmt)(struct mac_device_info *hw, unsigned long mode); /* Set/Get Unicast MAC addresses */ - void (*set_umac_addr) (void __iomem *ioaddr, unsigned char *addr, - unsigned int reg_n); - void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr, - unsigned int reg_n); - void (*set_eee_mode) (void __iomem *ioaddr); - void (*reset_eee_mode) (void __iomem *ioaddr); - void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw); - void (*set_eee_pls) (void __iomem *ioaddr, int link); - void (*ctrl_ane) (void __iomem *ioaddr, bool restart); - void (*get_adv) (void __iomem *ioaddr, struct rgmii_adv *adv); + void (*set_umac_addr)(struct mac_device_info *hw, unsigned char *addr, + unsigned int reg_n); + void (*get_umac_addr)(struct mac_device_info *hw, unsigned char *addr, + unsigned int reg_n); + void (*set_eee_mode)(struct mac_device_info *hw); + void (*reset_eee_mode)(struct mac_device_info *hw); + void (*set_eee_timer)(struct mac_device_info *hw, int ls, int tw); + void (*set_eee_pls)(struct mac_device_info *hw, int link); + void (*ctrl_ane)(struct mac_device_info *hw, bool restart); + void (*get_adv)(struct mac_device_info *hw, struct rgmii_adv *adv); }; struct stmmac_hwtimestamp { @@ -439,9 +441,14 @@ struct mac_device_info { struct mii_regs mii; /* MII register Addresses */ struct mac_link link; unsigned int synopsys_uid; + void __iomem *pcsr; /* vpointer to device CSRs */ + int multicast_filter_bins; + int unicast_filter_entries; + int mcast_bits_log2; }; -struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr); +struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins, + int perfect_uc_entries); struct mac_device_info *dwmac100_setup(void __iomem *ioaddr); void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6], diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h index f37d90f114f5272eab8448b1166e984dad470553..71b5419256c138e335c77aab87cf37784ff79037 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h @@ -87,7 +87,7 @@ enum power_event { (reg * 8)) #define GMAC_ADDR_LOW(reg) (((reg > 15) ? 0x00000804 : 0x00000044) + \ (reg * 8)) -#define GMAC_MAX_PERFECT_ADDRESSES 32 +#define GMAC_MAX_PERFECT_ADDRESSES 1 /* PCS registers (AN/TBI/SGMII/RGMII) offset */ #define GMAC_AN_CTRL 0x000000c0 /* AN control */ @@ -261,6 +261,7 @@ enum rtc_control { #define GMAC_MMC_RX_INTR 0x104 #define GMAC_MMC_TX_INTR 0x108 #define GMAC_MMC_RX_CSUM_OFFLOAD 0x208 +#define GMAC_EXTHASH_BASE 0x500 extern const struct stmmac_dma_ops dwmac1000_dma_ops; #endif /* __DWMAC1000_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index 9d3748361a1e585b3ca4c06b8a761395d01f8979..d8ef18786a1cadae60f5d550269a0036a3f24661 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -32,8 +32,9 @@ #include #include "dwmac1000.h" -static void dwmac1000_core_init(void __iomem *ioaddr, int mtu) +static void dwmac1000_core_init(struct mac_device_info *hw, int mtu) { + void __iomem *ioaddr = hw->pcsr; u32 value = readl(ioaddr + GMAC_CONTROL); value |= GMAC_CORE_INIT; if (mtu > 1500) @@ -52,8 +53,9 @@ static void dwmac1000_core_init(void __iomem *ioaddr, int mtu) #endif } -static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr) +static int dwmac1000_rx_ipc_enable(struct mac_device_info *hw) { + void __iomem *ioaddr = hw->pcsr; u32 value = readl(ioaddr + GMAC_CONTROL); value |= GMAC_CONTROL_IPC; @@ -64,8 +66,9 @@ static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr) return !!(value & GMAC_CONTROL_IPC); } -static void dwmac1000_dump_regs(void __iomem *ioaddr) +static void dwmac1000_dump_regs(struct mac_device_info *hw) { + void __iomem *ioaddr = hw->pcsr; int i; pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr); @@ -76,69 +79,98 @@ static void dwmac1000_dump_regs(void __iomem *ioaddr) } } -static void dwmac1000_set_umac_addr(void __iomem *ioaddr, unsigned char *addr, +static void dwmac1000_set_umac_addr(struct mac_device_info *hw, + unsigned char *addr, unsigned int reg_n) { + void __iomem *ioaddr = hw->pcsr; stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), GMAC_ADDR_LOW(reg_n)); } -static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr, +static void dwmac1000_get_umac_addr(struct mac_device_info *hw, + unsigned char *addr, unsigned int reg_n) { + void __iomem *ioaddr = hw->pcsr; stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), GMAC_ADDR_LOW(reg_n)); } -static void dwmac1000_set_filter(struct net_device *dev, int id) +static void dwmac1000_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits, + int mcbitslog2) +{ + int numhashregs, regs; + + switch (mcbitslog2) { + case 6: + writel(mcfilterbits[0], ioaddr + GMAC_HASH_LOW); + writel(mcfilterbits[1], ioaddr + GMAC_HASH_HIGH); + return; + break; + case 7: + numhashregs = 4; + break; + case 8: + numhashregs = 8; + break; + default: + pr_debug("STMMAC: err in setting mulitcast filter\n"); + return; + break; + } + for (regs = 0; regs < numhashregs; regs++) + writel(mcfilterbits[regs], + ioaddr + GMAC_EXTHASH_BASE + regs * 4); +} + +static void dwmac1000_set_filter(struct mac_device_info *hw, + struct net_device *dev) { void __iomem *ioaddr = (void __iomem *)dev->base_addr; unsigned int value = 0; - unsigned int perfect_addr_number; + unsigned int perfect_addr_number = hw->unicast_filter_entries; + u32 mc_filter[2]; + int mcbitslog2 = hw->mcast_bits_log2; pr_debug("%s: # mcasts %d, # unicast %d\n", __func__, netdev_mc_count(dev), netdev_uc_count(dev)); - if (dev->flags & IFF_PROMISC) + memset(mc_filter, 0, sizeof(mc_filter)); + + if (dev->flags & IFF_PROMISC) { value = GMAC_FRAME_FILTER_PR; - else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE) - || (dev->flags & IFF_ALLMULTI)) { + } else if (dev->flags & IFF_ALLMULTI) { value = GMAC_FRAME_FILTER_PM; /* pass all multi */ - writel(0xffffffff, ioaddr + GMAC_HASH_HIGH); - writel(0xffffffff, ioaddr + GMAC_HASH_LOW); } else if (!netdev_mc_empty(dev)) { - u32 mc_filter[2]; struct netdev_hw_addr *ha; /* Hash filter for multicast */ value = GMAC_FRAME_FILTER_HMC; - memset(mc_filter, 0, sizeof(mc_filter)); netdev_for_each_mc_addr(ha, dev) { - /* The upper 6 bits of the calculated CRC are used to - * index the contens of the hash table + /* The upper n bits of the calculated CRC are used to + * index the contents of the hash table. The number of + * bits used depends on the hardware configuration + * selected at core configuration time. */ - int bit_nr = bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26; + int bit_nr = bitrev32(~crc32_le(~0, ha->addr, + ETH_ALEN)) >> + (32 - mcbitslog2); /* The most significant bit determines the register to * use (H/L) while the other 5 bits determine the bit * within the register. */ mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); } - writel(mc_filter[0], ioaddr + GMAC_HASH_LOW); - writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH); } - /* Extra 16 regs are available in cores newer than the 3.40. */ - if (id > DWMAC_CORE_3_40) - perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES; - else - perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES / 2; + dwmac1000_set_mchash(ioaddr, mc_filter, mcbitslog2); /* Handle multiple unicast addresses (perfect filtering) */ if (netdev_uc_count(dev) > perfect_addr_number) - /* Switch to promiscuous mode if more than 16 addrs - * are required + /* Switch to promiscuous mode if more than unicast + * addresses are requested than supported by hardware. */ value |= GMAC_FRAME_FILTER_PR; else { @@ -146,7 +178,9 @@ static void dwmac1000_set_filter(struct net_device *dev, int id) struct netdev_hw_addr *ha; netdev_for_each_uc_addr(ha, dev) { - dwmac1000_set_umac_addr(ioaddr, ha->addr, reg); + stmmac_get_mac_addr(ioaddr, ha->addr, + GMAC_ADDR_HIGH(reg), + GMAC_ADDR_LOW(reg)); reg++; } } @@ -156,15 +190,13 @@ static void dwmac1000_set_filter(struct net_device *dev, int id) value |= GMAC_FRAME_FILTER_RA; #endif writel(value, ioaddr + GMAC_FRAME_FILTER); - - pr_debug("\tFilter: 0x%08x\n\tHash: HI 0x%08x, LO 0x%08x\n", - readl(ioaddr + GMAC_FRAME_FILTER), - readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW)); } -static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex, + +static void dwmac1000_flow_ctrl(struct mac_device_info *hw, unsigned int duplex, unsigned int fc, unsigned int pause_time) { + void __iomem *ioaddr = hw->pcsr; unsigned int flow = 0; pr_debug("GMAC Flow-Control:\n"); @@ -185,8 +217,9 @@ static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex, writel(flow, ioaddr + GMAC_FLOW_CTRL); } -static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode) +static void dwmac1000_pmt(struct mac_device_info *hw, unsigned long mode) { + void __iomem *ioaddr = hw->pcsr; unsigned int pmt = 0; if (mode & WAKE_MAGIC) { @@ -201,9 +234,10 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode) writel(pmt, ioaddr + GMAC_PMT); } -static int dwmac1000_irq_status(void __iomem *ioaddr, +static int dwmac1000_irq_status(struct mac_device_info *hw, struct stmmac_extra_stats *x) { + void __iomem *ioaddr = hw->pcsr; u32 intr_status = readl(ioaddr + GMAC_INT_STATUS); int ret = 0; @@ -268,8 +302,9 @@ static int dwmac1000_irq_status(void __iomem *ioaddr, return ret; } -static void dwmac1000_set_eee_mode(void __iomem *ioaddr) +static void dwmac1000_set_eee_mode(struct mac_device_info *hw) { + void __iomem *ioaddr = hw->pcsr; u32 value; /* Enable the link status receive on RGMII, SGMII ore SMII @@ -281,8 +316,9 @@ static void dwmac1000_set_eee_mode(void __iomem *ioaddr) writel(value, ioaddr + LPI_CTRL_STATUS); } -static void dwmac1000_reset_eee_mode(void __iomem *ioaddr) +static void dwmac1000_reset_eee_mode(struct mac_device_info *hw) { + void __iomem *ioaddr = hw->pcsr; u32 value; value = readl(ioaddr + LPI_CTRL_STATUS); @@ -290,8 +326,9 @@ static void dwmac1000_reset_eee_mode(void __iomem *ioaddr) writel(value, ioaddr + LPI_CTRL_STATUS); } -static void dwmac1000_set_eee_pls(void __iomem *ioaddr, int link) +static void dwmac1000_set_eee_pls(struct mac_device_info *hw, int link) { + void __iomem *ioaddr = hw->pcsr; u32 value; value = readl(ioaddr + LPI_CTRL_STATUS); @@ -304,8 +341,9 @@ static void dwmac1000_set_eee_pls(void __iomem *ioaddr, int link) writel(value, ioaddr + LPI_CTRL_STATUS); } -static void dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw) +static void dwmac1000_set_eee_timer(struct mac_device_info *hw, int ls, int tw) { + void __iomem *ioaddr = hw->pcsr; int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16); /* Program the timers in the LPI timer control register: @@ -318,8 +356,9 @@ static void dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw) writel(value, ioaddr + LPI_TIMER_CTRL); } -static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool restart) +static void dwmac1000_ctrl_ane(struct mac_device_info *hw, bool restart) { + void __iomem *ioaddr = hw->pcsr; /* auto negotiation enable and External Loopback enable */ u32 value = GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_ELE; @@ -329,8 +368,9 @@ static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool restart) writel(value, ioaddr + GMAC_AN_CTRL); } -static void dwmac1000_get_adv(void __iomem *ioaddr, struct rgmii_adv *adv) +static void dwmac1000_get_adv(struct mac_device_info *hw, struct rgmii_adv *adv) { + void __iomem *ioaddr = hw->pcsr; u32 value = readl(ioaddr + GMAC_ANE_ADV); if (value & GMAC_ANE_FD) @@ -368,7 +408,8 @@ static const struct stmmac_ops dwmac1000_ops = { .get_adv = dwmac1000_get_adv, }; -struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr) +struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins, + int perfect_uc_entries) { struct mac_device_info *mac; u32 hwid = readl(ioaddr + GMAC_VERSION); @@ -377,6 +418,14 @@ struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr) if (!mac) return NULL; + mac->pcsr = ioaddr; + mac->multicast_filter_bins = mcbins; + mac->unicast_filter_entries = perfect_uc_entries; + mac->mcast_bits_log2 = 0; + + if (mac->multicast_filter_bins) + mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + mac->mac = &dwmac1000_ops; mac->dma = &dwmac1000_dma_ops; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c index 2ff767bcfdd09c42b83f8cff431dbe122ec054fc..f8dd773f246caa1ecbcdfb451ef2c3fe8ff72395 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c @@ -32,8 +32,9 @@ #include #include "dwmac100.h" -static void dwmac100_core_init(void __iomem *ioaddr, int mtu) +static void dwmac100_core_init(struct mac_device_info *hw, int mtu) { + void __iomem *ioaddr = hw->pcsr; u32 value = readl(ioaddr + MAC_CONTROL); writel((value | MAC_CORE_INIT), ioaddr + MAC_CONTROL); @@ -43,8 +44,9 @@ static void dwmac100_core_init(void __iomem *ioaddr, int mtu) #endif } -static void dwmac100_dump_mac_regs(void __iomem *ioaddr) +static void dwmac100_dump_mac_regs(struct mac_device_info *hw) { + void __iomem *ioaddr = hw->pcsr; pr_info("\t----------------------------------------------\n" "\t DWMAC 100 CSR (base addr = 0x%p)\n" "\t----------------------------------------------\n", ioaddr); @@ -66,30 +68,35 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr) readl(ioaddr + MAC_VLAN2)); } -static int dwmac100_rx_ipc_enable(void __iomem *ioaddr) +static int dwmac100_rx_ipc_enable(struct mac_device_info *hw) { return 0; } -static int dwmac100_irq_status(void __iomem *ioaddr, +static int dwmac100_irq_status(struct mac_device_info *hw, struct stmmac_extra_stats *x) { return 0; } -static void dwmac100_set_umac_addr(void __iomem *ioaddr, unsigned char *addr, +static void dwmac100_set_umac_addr(struct mac_device_info *hw, + unsigned char *addr, unsigned int reg_n) { + void __iomem *ioaddr = hw->pcsr; stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW); } -static void dwmac100_get_umac_addr(void __iomem *ioaddr, unsigned char *addr, +static void dwmac100_get_umac_addr(struct mac_device_info *hw, + unsigned char *addr, unsigned int reg_n) { + void __iomem *ioaddr = hw->pcsr; stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW); } -static void dwmac100_set_filter(struct net_device *dev, int id) +static void dwmac100_set_filter(struct mac_device_info *hw, + struct net_device *dev) { void __iomem *ioaddr = (void __iomem *)dev->base_addr; u32 value = readl(ioaddr + MAC_CONTROL); @@ -137,9 +144,10 @@ static void dwmac100_set_filter(struct net_device *dev, int id) writel(value, ioaddr + MAC_CONTROL); } -static void dwmac100_flow_ctrl(void __iomem *ioaddr, unsigned int duplex, +static void dwmac100_flow_ctrl(struct mac_device_info *hw, unsigned int duplex, unsigned int fc, unsigned int pause_time) { + void __iomem *ioaddr = hw->pcsr; unsigned int flow = MAC_FLOW_CTRL_ENABLE; if (duplex) @@ -148,7 +156,7 @@ static void dwmac100_flow_ctrl(void __iomem *ioaddr, unsigned int duplex, } /* No PMT module supported on ST boards with this Eth chip. */ -static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode) +static void dwmac100_pmt(struct mac_device_info *hw, unsigned long mode) { return; } @@ -175,6 +183,7 @@ struct mac_device_info *dwmac100_setup(void __iomem *ioaddr) pr_info("\tDWMAC100\n"); + mac->pcsr = ioaddr; mac->mac = &dwmac100_ops; mac->dma = &dwmac100_dma_ops; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index c62e67f3c2f0692f85b39c42a69de3fc5ed37b22..9af50bae4dde67c543c15e0344f90ac9d53fd2b8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -262,7 +262,7 @@ static int stmmac_ethtool_getsettings(struct net_device *dev, /* Get and convert ADV/LP_ADV from the HW AN registers */ if (priv->hw->mac->get_adv) - priv->hw->mac->get_adv(priv->ioaddr, &adv); + priv->hw->mac->get_adv(priv->hw, &adv); else return -EOPNOTSUPP; /* should never happen indeed */ @@ -350,7 +350,7 @@ static int stmmac_ethtool_setsettings(struct net_device *dev, spin_lock(&priv->lock); if (priv->hw->mac->ctrl_ane) - priv->hw->mac->ctrl_ane(priv->ioaddr, 1); + priv->hw->mac->ctrl_ane(priv->hw, 1); spin_unlock(&priv->lock); } @@ -464,7 +464,7 @@ stmmac_set_pauseparam(struct net_device *netdev, if (netif_running(netdev)) ret = phy_start_aneg(phy); } else - priv->hw->mac->flow_ctrl(priv->ioaddr, phy->duplex, + priv->hw->mac->flow_ctrl(priv->hw, phy->duplex, priv->flow_ctrl, priv->pause); return ret; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 18315f34938bd98e16403cfd244c09288205903e..08addd65372818f48075b585eeb1d36ab682025b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -233,7 +233,7 @@ static void stmmac_enable_eee_mode(struct stmmac_priv *priv) /* Check and enter in LPI mode */ if ((priv->dirty_tx == priv->cur_tx) && (priv->tx_path_in_lpi_mode == false)) - priv->hw->mac->set_eee_mode(priv->ioaddr); + priv->hw->mac->set_eee_mode(priv->hw); } /** @@ -244,7 +244,7 @@ static void stmmac_enable_eee_mode(struct stmmac_priv *priv) */ void stmmac_disable_eee_mode(struct stmmac_priv *priv) { - priv->hw->mac->reset_eee_mode(priv->ioaddr); + priv->hw->mac->reset_eee_mode(priv->hw); del_timer_sync(&priv->eee_ctrl_timer); priv->tx_path_in_lpi_mode = false; } @@ -298,7 +298,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv) if (priv->eee_active) { pr_debug("stmmac: disable EEE\n"); del_timer_sync(&priv->eee_ctrl_timer); - priv->hw->mac->set_eee_timer(priv->ioaddr, 0, + priv->hw->mac->set_eee_timer(priv->hw, 0, tx_lpi_timer); } priv->eee_active = 0; @@ -313,12 +313,12 @@ bool stmmac_eee_init(struct stmmac_priv *priv) priv->eee_ctrl_timer.expires = STMMAC_LPI_T(eee_timer); add_timer(&priv->eee_ctrl_timer); - priv->hw->mac->set_eee_timer(priv->ioaddr, + priv->hw->mac->set_eee_timer(priv->hw, STMMAC_DEFAULT_LIT_LS, tx_lpi_timer); } else /* Set HW EEE according to the speed */ - priv->hw->mac->set_eee_pls(priv->ioaddr, + priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link); pr_debug("stmmac: Energy-Efficient Ethernet initialized\n"); @@ -693,7 +693,7 @@ static void stmmac_adjust_link(struct net_device *dev) } /* Flow Control operation */ if (phydev->pause) - priv->hw->mac->flow_ctrl(priv->ioaddr, phydev->duplex, + priv->hw->mac->flow_ctrl(priv->hw, phydev->duplex, fc, pause_time); if (phydev->speed != priv->speed) { @@ -1531,8 +1531,7 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv) static void stmmac_check_ether_addr(struct stmmac_priv *priv) { if (!is_valid_ether_addr(priv->dev->dev_addr)) { - priv->hw->mac->get_umac_addr((void __iomem *) - priv->dev->base_addr, + priv->hw->mac->get_umac_addr(priv->hw, priv->dev->dev_addr, 0); if (!is_valid_ether_addr(priv->dev->dev_addr)) eth_hw_addr_random(priv->dev); @@ -1629,14 +1628,14 @@ static int stmmac_hw_setup(struct net_device *dev) } /* Copy the MAC addr into the HW */ - priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0); + priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0); /* If required, perform hw setup of the bus. */ if (priv->plat->bus_setup) priv->plat->bus_setup(priv->ioaddr); /* Initialize the MAC Core */ - priv->hw->mac->core_init(priv->ioaddr, dev->mtu); + priv->hw->mac->core_init(priv->hw, dev->mtu); /* Enable the MAC Rx/Tx */ stmmac_set_mac(priv->ioaddr, true); @@ -1662,7 +1661,7 @@ static int stmmac_hw_setup(struct net_device *dev) /* Dump DMA/MAC registers */ if (netif_msg_hw(priv)) { - priv->hw->mac->dump_regs(priv->ioaddr); + priv->hw->mac->dump_regs(priv->hw); priv->hw->dma->dump_regs(priv->ioaddr); } priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; @@ -1677,7 +1676,7 @@ static int stmmac_hw_setup(struct net_device *dev) } if (priv->pcs && priv->hw->mac->ctrl_ane) - priv->hw->mac->ctrl_ane(priv->ioaddr, 0); + priv->hw->mac->ctrl_ane(priv->hw, 0); return 0; } @@ -2226,7 +2225,7 @@ static void stmmac_set_rx_mode(struct net_device *dev) struct stmmac_priv *priv = netdev_priv(dev); spin_lock(&priv->lock); - priv->hw->mac->set_filter(dev, priv->synopsys_id); + priv->hw->mac->set_filter(priv->hw, dev); spin_unlock(&priv->lock); } @@ -2316,8 +2315,7 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) /* To handle GMAC own interrupts */ if (priv->plat->has_gmac) { - int status = priv->hw->mac->host_irq_status((void __iomem *) - dev->base_addr, + int status = priv->hw->mac->host_irq_status(priv->hw, &priv->xstats); if (unlikely(status)) { /* For LPI we need to save the tx status */ @@ -2600,7 +2598,9 @@ static int stmmac_hw_init(struct stmmac_priv *priv) /* Identify the MAC HW device */ if (priv->plat->has_gmac) { priv->dev->priv_flags |= IFF_UNICAST_FLT; - mac = dwmac1000_setup(priv->ioaddr); + mac = dwmac1000_setup(priv->ioaddr, + priv->plat->multicast_filter_bins, + priv->plat->unicast_filter_entries); } else { mac = dwmac100_setup(priv->ioaddr); } @@ -2649,7 +2649,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv) /* To use alternate (extended) or normal descriptor structures */ stmmac_selec_desc_mode(priv); - ret = priv->hw->mac->rx_ipc(priv->ioaddr); + ret = priv->hw->mac->rx_ipc(priv->hw); if (!ret) { pr_warn(" RX IPC Checksum Offload not configured.\n"); priv->plat->rx_coe = STMMAC_RX_COE_NONE; @@ -2869,7 +2869,7 @@ int stmmac_suspend(struct net_device *ndev) /* Enable Power down mode by programming the PMT regs */ if (device_may_wakeup(priv->device)) { - priv->hw->mac->pmt(priv->ioaddr, priv->wolopts); + priv->hw->mac->pmt(priv->hw, priv->wolopts); priv->irq_wake = 1; } else { stmmac_set_mac(priv->ioaddr, false); @@ -2902,7 +2902,7 @@ int stmmac_resume(struct net_device *ndev) * from another devices (e.g. serial console). */ if (device_may_wakeup(priv->device)) { - priv->hw->mac->pmt(priv->ioaddr, 0); + priv->hw->mac->pmt(priv->hw, 0); priv->irq_wake = 0; } else { pinctrl_pm_select_default_state(priv->device); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index ea7a65be1f9af4208748d808128a344bfdb74377..bb524a932be48b6a0fa2e096eab0a2bb7732314d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -52,6 +52,59 @@ static const struct of_device_id stmmac_dt_ids[] = { MODULE_DEVICE_TABLE(of, stmmac_dt_ids); #ifdef CONFIG_OF + +/* This function validates the number of Multicast filtering bins specified + * by the configuration through the device tree. The Synopsys GMAC supports + * 64 bins, 128 bins, or 256 bins. "bins" refer to the division of CRC + * number space. 64 bins correspond to 6 bits of the CRC, 128 corresponds + * to 7 bits, and 256 refers to 8 bits of the CRC. Any other setting is + * invalid and will cause the filtering algorithm to use Multicast + * promiscuous mode. + */ +static int dwmac1000_validate_mcast_bins(int mcast_bins) +{ + int x = mcast_bins; + + switch (x) { + case HASH_TABLE_SIZE: + case 128: + case 256: + break; + default: + x = 0; + pr_info("Hash table entries set to unexpected value %d", + mcast_bins); + break; + } + return x; +} + +/* This function validates the number of Unicast address entries supported + * by a particular Synopsys 10/100/1000 controller. The Synopsys controller + * supports 1, 32, 64, or 128 Unicast filter entries for it's Unicast filter + * logic. This function validates a valid, supported configuration is + * selected, and defaults to 1 Unicast address if an unsupported + * configuration is selected. + */ +static int dwmac1000_validate_ucast_entries(int ucast_entries) +{ + int x = ucast_entries; + + switch (x) { + case 1: + case 32: + case 64: + case 128: + break; + default: + x = 1; + pr_info("Unicast table entries set to unexpected value %d\n", + ucast_entries); + break; + } + return x; +} + static int stmmac_probe_config_dt(struct platform_device *pdev, struct plat_stmmacenet_data *plat, const char **mac) @@ -115,6 +168,12 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, */ plat->maxmtu = JUMBO_LEN; + /* Set default value for multicast hash bins */ + plat->multicast_filter_bins = HASH_TABLE_SIZE; + + /* Set default value for unicast filter entries */ + plat->unicast_filter_entries = 1; + /* * Currently only the properties needed on SPEAr600 * are provided. All other properties should be added @@ -131,6 +190,14 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, * are clearly MTUs */ of_property_read_u32(np, "max-frame-size", &plat->maxmtu); + of_property_read_u32(np, "snps,multicast-filter-bins", + &plat->multicast_filter_bins); + of_property_read_u32(np, "snps,perfect-filter-entries", + &plat->unicast_filter_entries); + plat->unicast_filter_entries = dwmac1000_validate_ucast_entries( + plat->unicast_filter_entries); + plat->multicast_filter_bins = dwmac1000_validate_mcast_bins( + plat->multicast_filter_bins); plat->has_gmac = 1; plat->pmt = 1; } diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 6f27d4f957bd3846e12871b9a7da4a99739d49a4..cd63851b57f2804c4321cba8ec5c1b2b5637d935 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -112,6 +112,8 @@ struct plat_stmmacenet_data { int riwt_off; int max_speed; int maxmtu; + int multicast_filter_bins; + int unicast_filter_entries; void (*fix_mac_speed)(void *priv, unsigned int speed); void (*bus_setup)(void __iomem *ioaddr); void *(*setup)(struct platform_device *pdev);