summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
diff options
context:
space:
mode:
authorVince Bridgers <vbridgers2013@gmail.com>2014-07-31 15:49:17 -0500
committerDavid S. Miller <davem@davemloft.net>2014-07-31 14:13:29 -0700
commit3b57de958e2aa39abe020eb31bf19000d5899389 (patch)
tree518b93e036b1a4d6c345f3d72d466ffd5b92771d /drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
parentea6856e35240c5accf0936de920f2d8c9afee444 (diff)
net: stmmac: Support devicetree configs for mcast and ucast filter entries
This patch adds and modifies code to support multiple Multicast and Unicast Synopsys MAC filter configurations. The default configuration is defined to support legacy driver behavior, which is 64 Multicast bins. The Unicast filter code previously assumed all controllers support 32 or 16 Unicast addresses based on controller version number, but this has been corrected to support a default of 1 Unicast address. The filter configuration may be specified through the devicetree using a Synopsys specific device tree entry. This information was verified with Synopsys through Synopsys Support Case #8000684337 and shared with the maintainer. Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c')
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c66
1 files changed, 50 insertions, 16 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index cdcbad1f1ac0..d8ef18786a1c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -97,12 +97,41 @@ static void dwmac1000_get_umac_addr(struct mac_device_info *hw,
GMAC_ADDR_LOW(reg_n));
}
-static void dwmac1000_set_filter(struct net_device *dev)
+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));
@@ -120,10 +149,14 @@ static void dwmac1000_set_filter(struct net_device *dev)
value = GMAC_FRAME_FILTER_HMC;
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.
@@ -132,15 +165,12 @@ static void dwmac1000_set_filter(struct net_device *dev)
}
}
- writel(mc_filter[0], ioaddr + GMAC_HASH_LOW);
- writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH);
-
- perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES;
+ 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 {
@@ -160,10 +190,6 @@ static void dwmac1000_set_filter(struct net_device *dev)
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));
}
@@ -382,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);
@@ -392,6 +419,13 @@ struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
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;