lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Tue, 4 Feb 2014 10:57:50 +0100 From: Giuseppe CAVALLARO <peppe.cavallaro@...com> To: Vince Bridgers <vbridgers2013@...il.com>, <devicetree@...r.kernel.org>, <netdev@...r.kernel.org> Cc: <robh+dt@...nel.org>, <pawel.moll@....com>, <mark.rutland@....com>, <ijc+devicetree@...lion.org.uk>, <galak@...eaurora.org>, <dinguyen@...era.com>, <rayagond@...avyalabs.com> Subject: Re: [PATCH net-next 2/2] stmmac: add extended set multicast filter & devicetree options On 1/31/2014 9:15 PM, Vince Bridgers wrote: > The synopsys EMAC can be configured for different numbers of multicast hash > bins and perfect filter entries at device creation time and there's no way > to query this configuration information at runtime. As a result, a devicetree > parameter is required in order for the driver to program these filters > correctly for a particular device instance. This patch extends the current > driver by providing a different multicast filter programming function if > different than the currently supported 64 multicast hash bins and 32 > perfect unicast addresses. This patch is required to correct multicast > filtering for the Altera Cyclone V SOC. > > Signed-off-by: Vince Bridgers <vbridgers2013@...il.com> > --- > drivers/net/ethernet/stmicro/stmmac/common.h | 42 +++-- > drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 5 +- > .../net/ethernet/stmicro/stmmac/dwmac1000_core.c | 161 +++++++++++++++++--- > .../net/ethernet/stmicro/stmmac/dwmac100_core.c | 29 ++-- > .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 6 +- > drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 36 ++--- > .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 51 +++++++ > include/linux/stmmac.h | 2 + > 8 files changed, 261 insertions(+), 71 deletions(-) > > diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h > index 7834a39..ca07afe 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/common.h > +++ b/drivers/net/ethernet/stmicro/stmmac/common.h > @@ -294,6 +294,8 @@ struct dma_features { > > #define JUMBO_LEN 9000 > > +#define GMAC_MAX_PERFECT_ADDRESSES 32 > + > struct stmmac_desc_ops { > /* DMA RX descriptor ring initialization */ > void (*init_rx_desc) (struct dma_desc *p, int disable_rx_ic, int mode, > @@ -368,34 +370,37 @@ 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, > + 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, > + 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, > + void (*set_umac_addr)(struct mac_device_info *hw, unsigned char *addr, > unsigned int reg_n); > - void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr, > + void (*get_umac_addr)(struct mac_device_info *hw, 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_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 { > @@ -447,9 +452,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 f37d90f..40b8533 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h > @@ -87,7 +87,6 @@ enum power_event { > (reg * 8)) > #define GMAC_ADDR_LOW(reg) (((reg > 15) ? 0x00000804 : 0x00000044) + \ > (reg * 8)) > -#define GMAC_MAX_PERFECT_ADDRESSES 32 > > /* PCS registers (AN/TBI/SGMII/RGMII) offset */ > #define GMAC_AN_CTRL 0x000000c0 /* AN control */ > @@ -130,6 +129,8 @@ enum power_event { > #define GMAC_CONTROL_2K 0x08000000 /* IEEE 802.3as 2K packets */ > #define GMAC_CONTROL_TC 0x01000000 /* Transmit Conf. in RGMII/SGMII */ > #define GMAC_CONTROL_WD 0x00800000 /* Disable Watchdog on receive */ > + > +/* GMAC Configuration defines */ > #define GMAC_CONTROL_JD 0x00400000 /* Jabber disable */ > #define GMAC_CONTROL_BE 0x00200000 /* Frame Burst Enable */ > #define GMAC_CONTROL_JE 0x00100000 /* Jumbo frame */ > @@ -262,5 +263,7 @@ enum rtc_control { > #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 b3e148e..44db9fb 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c > @@ -26,14 +26,15 @@ > Author: Giuseppe Cavallaro <peppe.cavallaro@...com> > *******************************************************************************/ > > +#include <linux/io.h> > #include <linux/crc32.h> > -#include <linux/slab.h> > #include <linux/ethtool.h> > -#include <asm/io.h> > +#include <linux/slab.h> > #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,21 +79,113 @@ 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) > { > - stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), > + stmmac_set_mac_addr(hw->pcsr, 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) > { > - stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), > + stmmac_get_mac_addr(hw->pcsr, 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_extmchash(void __iomem *ioaddr, u32 *mcfilterbits, > + int numhashregs) > +{ > + int regs; > + for (regs = 0; regs < numhashregs; regs++) > + writel(mcfilterbits[regs], > + ioaddr + GMAC_EXTHASH_BASE + regs * 4); > +} > + > +static void dwmac1000_set_filterex(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; > + u32 mc_filter[8]; > + > + pr_debug("%s: # mcasts %d, # unicast %d\n", __func__, > + netdev_mc_count(dev), netdev_uc_count(dev)); > + > + if (dev->flags & IFF_PROMISC) { > + value = GMAC_FRAME_FILTER_PR; > + } else if (dev->flags & IFF_ALLMULTI) { > + value = GMAC_FRAME_FILTER_PM; /* pass all multi */ > + } else if (!netdev_mc_empty(dev)) { > + struct netdev_hw_addr *ha; > + > + memset(mc_filter, 0, sizeof(mc_filter)); > + > + /* Hash filter for multicast */ > + value = GMAC_FRAME_FILTER_HMC; > + > + netdev_for_each_mc_addr(ha, dev) { > + /* The upper n bits of the calculated CRC are used to > + * index the contents of the hash table depending > + * on the particular core's multicast hash size > + * configured through Synopsys Core Consultant > + */ > + int bit_nr = bitrev32(~crc32_le(~0, ha->addr, > + ETH_ALEN)) >> > + (32 - hw->mcast_bits_log2); > + > + /* 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); > + } > + if (hw->mcast_bits_log2 == 6) { > + writel(mc_filter[0], ioaddr + GMAC_HASH_LOW); > + writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH); > + } else if (hw->mcast_bits_log2 == 7) { > + dwmac1000_set_extmchash(ioaddr, mc_filter, 4); > + } else if (hw->mcast_bits_log2 == 8) { > + dwmac1000_set_extmchash(ioaddr, mc_filter, 8); > + } else { > + pr_debug("STMMAC: err in setting mulitcast filter\n"); > + } > + } > + > + /* Extra 16 regs are available in cores newer than the 3.40. */ > + if (hw->synopsys_uid > DWMAC_CORE_3_40) > + perfect_addr_number = hw->unicast_filter_entries; > + else > + perfect_addr_number = hw->unicast_filter_entries / 2; can you check if this is safe enough? I mean if we pass a setting that could generate problems in case of old Synopsys chips. > + > + /* 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 > + */ > + value |= GMAC_FRAME_FILTER_PR; > + else { > + int reg = 1; > + struct netdev_hw_addr *ha; > + > + netdev_for_each_uc_addr(ha, dev) { > + dwmac1000_set_umac_addr(hw, ha->addr, reg); > + reg++; > + } > + } > + > +#ifdef FRAME_FILTER_DEBUG > + /* Enable Receive all mode (to debug filtering_fail errors) */ > + value |= GMAC_FRAME_FILTER_RA; > +#endif > + writel(value, ioaddr + GMAC_FRAME_FILTER); > +} > + > +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; > @@ -130,7 +225,7 @@ static void dwmac1000_set_filter(struct net_device *dev, int id) > } > > /* Extra 16 regs are available in cores newer than the 3.40. */ > - if (id > DWMAC_CORE_3_40) > + if (hw->synopsys_uid > DWMAC_CORE_3_40) > perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES; > else > perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES / 2; > @@ -146,7 +241,7 @@ 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); > + dwmac1000_set_umac_addr(hw, ha->addr, reg); > reg++; > } > } > @@ -162,9 +257,10 @@ static void dwmac1000_set_filter(struct net_device *dev, int id) > 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 +281,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 +298,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 +366,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 +380,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 +390,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 +405,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 +420,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; > u32 value; > > value = readl(ioaddr + GMAC_AN_CTRL); > @@ -332,8 +435,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) > @@ -353,7 +457,7 @@ static void dwmac1000_get_adv(void __iomem *ioaddr, struct rgmii_adv *adv) > adv->lp_pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT; > } > > -static const struct stmmac_ops dwmac1000_ops = { > +static struct stmmac_ops dwmac1000_ops = { > .core_init = dwmac1000_core_init, > .rx_ipc = dwmac1000_rx_ipc_enable, > .dump_regs = dwmac1000_dump_regs, > @@ -371,7 +475,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); > @@ -380,6 +485,16 @@ 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); > + > + if (mac->mcast_bits_log2 != 64) > + dwmac1000_ops.set_filter = dwmac1000_set_filterex; > + > 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 2ff767b..3ee3ab5 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c > @@ -28,12 +28,13 @@ > Author: Giuseppe Cavallaro <peppe.cavallaro@...com> > *******************************************************************************/ > > -#include <linux/crc32.h> > #include <asm/io.h> > +#include <linux/crc32.h> > #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 c5f9cb8..e679fa6 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 */ > > @@ -352,7 +352,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); > } > > @@ -471,7 +471,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); > spin_unlock(&priv->lock); > return ret; > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c > index d93aa87..aaa14b2 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,12 +298,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, > priv->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_info("stmmac: Energy-Efficient Ethernet initialized\n"); > @@ -678,7 +678,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) { > @@ -1519,8 +1519,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); > @@ -1617,14 +1616,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); > @@ -1650,7 +1649,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; > @@ -1665,7 +1664,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; > } > @@ -2244,7 +2243,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); > } > > @@ -2334,8 +2333,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 */ > @@ -2619,7 +2617,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); > } > @@ -2668,7 +2668,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; > @@ -2888,7 +2888,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); > @@ -2917,7 +2917,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 5884a7d..4502cde 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c > @@ -43,6 +43,42 @@ static const struct of_device_id stmmac_dt_ids[] = { > }; > MODULE_DEVICE_TABLE(of, stmmac_dt_ids); > > + > +static int stmmac_validate_mcast_bins(int mcast_bins) > +{ > + int x = mcast_bins; > + switch (x) { > + case 0: > + case HASH_TABLE_SIZE: > + case 128: > + case 256: > + break; > + default: > + x = HASH_TABLE_SIZE; > + pr_info("Hash table entries set to unexpected value %d", > + mcast_bins); > + break; > + } > + return x; > +} > + > +static int stmmac_validate_ucast_entries(int ucast_entries) > +{ > + int x = ucast_entries; > + switch (x) { > + case 32: > + case 64: > + case 128: > + break; > + default: > + x = 32; > + pr_info("Unicast table entries set to unexpected value %d\n", > + ucast_entries); > + break; > + } > + return x; > +} > + > #ifdef CONFIG_OF > static int stmmac_probe_config_dt(struct platform_device *pdev, > struct plat_stmmacenet_data *plat, > @@ -107,6 +143,13 @@ 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 = GMAC_MAX_PERFECT_ADDRESSES; > + > + > /* > * Currently only the properties needed on SPEAr600 > * are provided. All other properties should be added > @@ -123,6 +166,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 = stmmac_validate_ucast_entries( > + plat->unicast_filter_entries); > + plat->multicast_filter_bins = stmmac_validate_mcast_bins( > + plat->multicast_filter_bins); Can this validation be done in main? > plat->has_gmac = 1; > plat->pmt = 1; > } > diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h > index 6f27d4f..cd63851 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); > -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists