Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] net:phy:dp83640: Initialize PTP clocks at device init.
From: Richard Cochran @ 2014-02-04  8:04 UTC (permalink / raw)
  To: Stefan Sørensen; +Cc: netdev
In-Reply-To: <1391438218-21994-1-git-send-email-stefan.sorensen@spectralink.com>

On Mon, Feb 03, 2014 at 03:36:58PM +0100, Stefan Sørensen wrote:
> The trigger and events functionality can be useful even if packet
> timestamping is not used, but the required PTP clock is only enabled
> when packet timestamping is started. This patch moves the clock enable
> to when the interface is configured.

I looked in the code and in the docs, and I can't find any reason not
to enable the clock earlier.

Acked-by: Richard Cochran <richardcochran@gmail.com>

^ permalink raw reply

* Re: [PATCH v3 0/5] can: sja1000: cleanups and new OF property
From: Andreas Larsson @ 2014-02-04  8:19 UTC (permalink / raw)
  To: Marc Kleine-Budde, Florian Vaussard, Wolfgang Grandegger
  Cc: linux-can, netdev, sparclinux, linux-kernel
In-Reply-To: <52EBAA28.1070307@gaisler.com>

On 2014-01-31 14:50, Andreas Larsson wrote:
> On 2014-01-31 14:40, Marc Kleine-Budde wrote:
>> On 01/31/2014 02:34 PM, Florian Vaussard wrote:
>>> Hello,
>>>
>>> (could someone with a SJA1000 on SPARC perform a functional test
>>> to see if interrupts are working? it would be great :-)
>>>
>>> Changes since v2:
>>> - Dropped patch 1 "can: sja1000: remove unused defines"
>>> - Addressed Marc's comments on patch 4 and 6 (now 3 and 5)
>>>
>>> Changes since v1:
>>> - Merge sja1000_of_platform.c into sja1000_platform.c (patch 4)
>>>
>>> The first part of this series performs serveral small cleanups
>>> (patches 1 and 2).
>>>
>>> Patch 3 merges sja1000_of_platform.c into sja1000_platform.c.
>>> Changes are pretty conservatives (mostly copy/paste/move). IRQ
>>> is treated differently in the OF and non-OF versions, thus this
>>> is where the fused version differs the most.
>>>
>>> The final part introduces the 'reg-io-width' binding (already used
>>> by some other drivers) to perform a similar job as what was done
>>> with IORESOURCE_MEM_XXBIT. This is needed on my system to correctly
>>> take into account the aliasing of the address bus.
>>>
>>> All patches were tested using OF boot on my OMAP3 system with a
>>> memory-mapped SJA1000. Thus, the non-OF path is not tested, as
>>> I do not have a platform data at hand.
>>
>> Nice, looks good now. I'll give Andreas some time to test on sparc and
>> then apply the patches.
>
>
> I am on it. I will dig up some hardware for this on Monday to test it.

Works splendidly. You can add:

Tested-by: Andreas Larsson <andreas@gaisler.com>

Cheers,
Andreas Larsson

^ permalink raw reply

* Re: [PATCH v3 0/5] can: sja1000: cleanups and new OF property
From: Marc Kleine-Budde @ 2014-02-04  8:28 UTC (permalink / raw)
  To: Andreas Larsson, Florian Vaussard, Wolfgang Grandegger
  Cc: linux-can, netdev, sparclinux, linux-kernel
In-Reply-To: <52F0A29C.9000604@gaisler.com>

[-- Attachment #1: Type: text/plain, Size: 436 bytes --]

On 02/04/2014 09:19 AM, Andreas Larsson wrote:

> Works splendidly. You can add:
> 
> Tested-by: Andreas Larsson <andreas@gaisler.com>

Thanks,

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 242 bytes --]

^ permalink raw reply

* Re: TI CPSW Ethernet Tx performance regression
From: Mugunthan V N @ 2014-02-04  8:46 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: netdev, Ben Hutchings
In-Reply-To: <CAGVrzcY5jm+1+B1eqn4Li8K6ovDHCfKwuddqXHgLy_gFNs1KuA@mail.gmail.com>

Hi

On Tuesday 04 February 2014 12:54 AM, Florian Fainelli wrote:
> Ok,the priv pointer when we enter the interrupt handler could point to
> e.g: slave 0, so we need to get it re-assigned to the second slave
> using cpsw_get_slave_priv(). How do you ensure that "priv" at the
> beginning of the interrupt handler does not already point to slave 1?
> In that case, is not there a chance to starve slave 0, or at least
> cause an excessive latency by exiting the interrupt handler for slave
> 1, and then re-entering it for slave 0?

devm_request_irq is called with slave 0 priv, so at the beginning of the
interrupt it is always slave 0 priv irrespective whether the slave 0
interface is up or not.

Regards
Mugunthan V N

^ permalink raw reply

* [PATCH] dp83640: Support a configurable number of periodic outputs
From: Stefan Sørensen @ 2014-02-04  8:52 UTC (permalink / raw)
  To: richardcochran, netdev; +Cc: Stefan Sørensen

The driver is currently limited to a single periodic output.
This patch makes the number of peridodic output dynamic by
dropping the gpio_tab module parameter and adding cal_gpio,
perout_gpio_tab and extts_gpio_tabs parameters.

Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
---
 drivers/net/phy/dp83640.c | 70 ++++++++++++++++++++---------------------------
 1 file changed, 30 insertions(+), 40 deletions(-)

diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 547725f..0a54c79 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -38,15 +38,11 @@
 #define LAYER4		0x02
 #define LAYER2		0x01
 #define MAX_RXTS	64
-#define N_EXT_TS	6
 #define PSF_PTPVER	2
 #define PSF_EVNT	0x4000
 #define PSF_RX		0x2000
 #define PSF_TX		0x1000
-#define EXT_EVENT	1
-#define CAL_EVENT	7
-#define CAL_TRIGGER	7
-#define PER_TRIGGER	6
+#define N_EXT		8
 
 #define MII_DP83640_MICR 0x11
 #define MII_DP83640_MISR 0x12
@@ -148,30 +144,23 @@ struct dp83640_clock {
 
 /* globals */
 
-enum {
-	CALIBRATE_GPIO,
-	PEROUT_GPIO,
-	EXTTS0_GPIO,
-	EXTTS1_GPIO,
-	EXTTS2_GPIO,
-	EXTTS3_GPIO,
-	EXTTS4_GPIO,
-	EXTTS5_GPIO,
-	GPIO_TABLE_SIZE
-};
-
 static int chosen_phy = -1;
-static ushort gpio_tab[GPIO_TABLE_SIZE] = {
-	1, 2, 3, 4, 8, 9, 10, 11
-};
+static int cal_gpio = 1;
+static int perout_gpio_tab[N_EXT] = {2};
+static int n_perout = 1;
+static int extts_gpio_tab[N_EXT] = {3, 4, 8, 9, 10, 11};
+static int n_extts = 6;
 
 module_param(chosen_phy, int, 0444);
-module_param_array(gpio_tab, ushort, NULL, 0444);
+module_param(cal_gpio, int, 0444);
+module_param_array(perout_gpio_tab, int, &n_perout, 0444);
+module_param_array(extts_gpio_tab, int, &n_extts, 0444);
 
 MODULE_PARM_DESC(chosen_phy, \
 	"The address of the PHY to use for the ancillary clock features");
-MODULE_PARM_DESC(gpio_tab, \
-	"Which GPIO line to use for which purpose: cal,perout,extts1,...,extts6");
+MODULE_PARM_DESC(cal_gpio, "Which GPIO line to use for calibration");
+MODULE_PARM_DESC(perout_gpio_tab, "Which GPIO lines to use for periodic output");
+MODULE_PARM_DESC(extts_gpio_tab, "Which GPIO lines to use for external timestamping");
 
 /* a list of clocks and a mutex to protect it */
 static LIST_HEAD(phyter_clocks);
@@ -267,15 +256,16 @@ static u64 phy2txts(struct phy_txts *p)
 }
 
 static void periodic_output(struct dp83640_clock *clock,
-			    struct ptp_clock_request *clkreq, bool on)
+			    struct ptp_clock_request *clkreq,
+			    int index, bool on)
 {
 	struct dp83640_private *dp83640 = clock->chosen;
 	struct phy_device *phydev = dp83640->phydev;
 	u32 sec, nsec, period;
 	u16 gpio, ptp_trig, trigger, val;
 
-	gpio = on ? gpio_tab[PEROUT_GPIO] : 0;
-	trigger = PER_TRIGGER;
+	gpio = on ? perout_gpio_tab[index] : 0;
+	trigger = n_extts + index;
 
 	ptp_trig = TRIG_WR |
 		(trigger & TRIG_CSEL_MASK) << TRIG_CSEL_SHIFT |
@@ -430,12 +420,12 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
 	switch (rq->type) {
 	case PTP_CLK_REQ_EXTTS:
 		index = rq->extts.index;
-		if (index < 0 || index >= N_EXT_TS)
+		if (index < 0 || index >= n_extts)
 			return -EINVAL;
-		event_num = EXT_EVENT + index;
+		event_num = index;
 		evnt = EVNT_WR | (event_num & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
 		if (on) {
-			gpio_num = gpio_tab[EXTTS0_GPIO + index];
+			gpio_num = extts_gpio_tab[index];
 			evnt |= (gpio_num & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
 			evnt |= EVNT_RISE;
 		}
@@ -443,9 +433,10 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
 		return 0;
 
 	case PTP_CLK_REQ_PEROUT:
-		if (rq->perout.index != 0)
+		index = rq->perout.index;
+		if (index < 0 || index >= n_perout)
 			return -EINVAL;
-		periodic_output(clock, rq, on);
+		periodic_output(clock, rq, index, on);
 		return 0;
 
 	default:
@@ -538,10 +529,9 @@ static void recalibrate(struct dp83640_clock *clock)
 	struct list_head *this;
 	struct dp83640_private *tmp;
 	struct phy_device *master = clock->chosen->phydev;
-	u16 cal_gpio, cfg0, evnt, ptp_trig, trigger, val;
+	u16 cfg0, evnt, ptp_trig, trigger, val;
 
-	trigger = CAL_TRIGGER;
-	cal_gpio = gpio_tab[CALIBRATE_GPIO];
+	trigger = n_extts + n_perout;
 
 	mutex_lock(&clock->extreg_lock);
 
@@ -564,7 +554,7 @@ static void recalibrate(struct dp83640_clock *clock)
 	 * enable an event timestamp
 	 */
 	evnt = EVNT_WR | EVNT_RISE | EVNT_SINGLE;
-	evnt |= (CAL_EVENT & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
+	evnt |= (trigger & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
 	evnt |= (cal_gpio & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
 
 	list_for_each(this, &clock->phylist) {
@@ -642,7 +632,7 @@ static void recalibrate(struct dp83640_clock *clock)
 
 static inline u16 exts_chan_to_edata(int ch)
 {
-	return 1 << ((ch + EXT_EVENT) * 2);
+	return 1 << ((ch) * 2);
 }
 
 static int decode_evnt(struct dp83640_private *dp83640,
@@ -676,14 +666,14 @@ static int decode_evnt(struct dp83640_private *dp83640,
 		parsed = words + 2;
 	} else {
 		parsed = words + 1;
-		i = ((ests >> EVNT_NUM_SHIFT) & EVNT_NUM_MASK) - EXT_EVENT;
+		i = ((ests >> EVNT_NUM_SHIFT) & EVNT_NUM_MASK);
 		ext_status = exts_chan_to_edata(i);
 	}
 
 	event.type = PTP_CLOCK_EXTTS;
 	event.timestamp = phy2txts(&dp83640->edata);
 
-	for (i = 0; i < N_EXT_TS; i++) {
+	for (i = 0; i < n_extts; i++) {
 		if (ext_status & exts_chan_to_edata(i)) {
 			event.index = i;
 			ptp_clock_event(dp83640->clock->ptp_clock, &event);
@@ -889,8 +879,8 @@ static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus)
 	sprintf(clock->caps.name, "dp83640 timer");
 	clock->caps.max_adj	= 1953124;
 	clock->caps.n_alarm	= 0;
-	clock->caps.n_ext_ts	= N_EXT_TS;
-	clock->caps.n_per_out	= 1;
+	clock->caps.n_ext_ts	= n_extts;
+	clock->caps.n_per_out	= n_perout;
 	clock->caps.pps		= 0;
 	clock->caps.adjfreq	= ptp_dp83640_adjfreq;
 	clock->caps.adjtime	= ptp_dp83640_adjtime;
-- 
1.8.5.3

^ permalink raw reply related

* Re: [PATCH nf v2] ipvs: fix AF assignment in ip_vs_conn_new()
From: Simon Horman @ 2014-02-04  9:08 UTC (permalink / raw)
  To: Julian Anastasov
  Cc: Michal Kubecek, netfilter-devel, netdev, lvs-devel, Wensong Zhang,
	Pablo Neira Ayuso, Patrick McHardy, Jozsef Kadlecsik,
	David S. Miller
In-Reply-To: <alpine.LFD.2.11.1401301022170.1644@ja.home.ssi.bg>

On Thu, Jan 30, 2014 at 10:29:22AM +0200, Julian Anastasov wrote:
> 
> 	Hello,
> 
> On Thu, 30 Jan 2014, Michal Kubecek wrote:
> 
> > If a fwmark is passed to ip_vs_conn_new(), it is passed in
> > vaddr, not daddr. Therefore we should set AF to AF_UNSPEC in
> > vaddr assignment (like we do in ip_vs_ct_in_get()), otherwise we
> > may copy only first 4 bytes of an IPv6 address into cp->daddr.
> > 
> > v2: fix messed up {d,v}addr and p->{d,v}addr, add info about the
> > outcome (thanks to Julian Anastasov)
> > 
> > Signed-off-by: Bogdano Arendartchuk <barendartchuk@suse.com>
> > Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
> 
> Acked-by: Julian Anastasov <ja@ssi.bg>
> 
> 	Looks like problem comes from
> commit be8be9eccbf2d908a7e56b3f7a71105cd88da06b
> "ipvs: Fix IPv4 FWMARK virtual services" (2.6.30).

Thanks, I'll queue this up.

> 
> > ---
> >  net/netfilter/ipvs/ip_vs_conn.c | 8 ++++----
> >  1 file changed, 4 insertions(+), 4 deletions(-)
> > 
> > diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
> > index 59a1a85..a8eb0a8 100644
> > --- a/net/netfilter/ipvs/ip_vs_conn.c
> > +++ b/net/netfilter/ipvs/ip_vs_conn.c
> > @@ -871,11 +871,11 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
> >  	cp->protocol	   = p->protocol;
> >  	ip_vs_addr_set(p->af, &cp->caddr, p->caddr);
> >  	cp->cport	   = p->cport;
> > -	ip_vs_addr_set(p->af, &cp->vaddr, p->vaddr);
> > -	cp->vport	   = p->vport;
> > -	/* proto should only be IPPROTO_IP if d_addr is a fwmark */
> > +	/* proto should only be IPPROTO_IP if p->vaddr is a fwmark */
> >  	ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
> > -		       &cp->daddr, daddr);
> > +		       &cp->vaddr, p->vaddr);
> > +	cp->vport	   = p->vport;
> > +	ip_vs_addr_set(p->af, &cp->daddr, daddr);
> >  	cp->dport          = dport;
> >  	cp->flags	   = flags;
> >  	cp->fwmark         = fwmark;
> > -- 
> > 1.8.1.4
> 
> Regards
> 
> --
> Julian Anastasov <ja@ssi.bg>
> 

^ permalink raw reply

* Re: [PATCH] dp83640: Support a configurable number of periodic outputs
From: Richard Cochran @ 2014-02-04  9:29 UTC (permalink / raw)
  To: Stefan Sørensen; +Cc: netdev
In-Reply-To: <1391503942-694-1-git-send-email-stefan.sorensen@spectralink.com>

On Tue, Feb 04, 2014 at 09:52:22AM +0100, Stefan Sørensen wrote:
> The driver is currently limited to a single periodic output.
> This patch makes the number of peridodic output dynamic by
> dropping the gpio_tab module parameter and adding cal_gpio,
> perout_gpio_tab and extts_gpio_tabs parameters.

...

>  module_param(chosen_phy, int, 0444);
> -module_param_array(gpio_tab, ushort, NULL, 0444);
> +module_param(cal_gpio, int, 0444);
> +module_param_array(perout_gpio_tab, int, &n_perout, 0444);
> +module_param_array(extts_gpio_tab, int, &n_extts, 0444);
>  
>  MODULE_PARM_DESC(chosen_phy, \
>  	"The address of the PHY to use for the ancillary clock features");
> -MODULE_PARM_DESC(gpio_tab, \
> -	"Which GPIO line to use for which purpose: cal,perout,extts1,...,extts6");
> +MODULE_PARM_DESC(cal_gpio, "Which GPIO line to use for calibration");
> +MODULE_PARM_DESC(perout_gpio_tab, "Which GPIO lines to use for periodic output");
> +MODULE_PARM_DESC(extts_gpio_tab, "Which GPIO lines to use for external timestamping");

Modules parameters are surely easiest (for the developer), but perhaps
the time has come for the "right way."

Currently there is no interface for configuring the GPIOs used by PHC
devices, and last year I was going to add the GPIOs to the igb
driver. The conclusion of the discussion was that module parameters
are bad for this, but ethtool is good.

  http://www.spinics.net/lists/netdev/msg237692.html

[ I did not follow through to come up with an ethtool way of configuring
  the igb pins. ]

Even though it is more work, I think the way forward is to invent a
way to let the user configure this kind of thing via ethtool. Would
you care to take a stab at this?

Thanks,
Richard

^ permalink raw reply

* Re: [PATCH net-next 2/2] stmmac: add extended set multicast filter & devicetree options
From: Giuseppe CAVALLARO @ 2014-02-04  9:57 UTC (permalink / raw)
  To: Vince Bridgers, devicetree, netdev
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
	dinguyen, rayagond
In-Reply-To: <1391199356-27226-3-git-send-email-vbridgers2013@gmail.com>

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@gmail.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@st.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@st.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);
>

^ permalink raw reply

* Re: [PATCH net-next 1/2] dts: Add bindings for multicast hash bins and perfect filter entries
From: Giuseppe CAVALLARO @ 2014-02-04  9:58 UTC (permalink / raw)
  To: Vince Bridgers, devicetree, netdev
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
	dinguyen, rayagond
In-Reply-To: <1391199356-27226-2-git-send-email-vbridgers2013@gmail.com>

Hello Vince

On 1/31/2014 9:15 PM, Vince Bridgers wrote:
> This change adds bindings for the number of multicast hash bins and perfect
> filter entries supported by the Synopsys EMAC. The Synopsys EMAC core is
> configurable at device creation time, and can be configured for a different
> number of multicast hash bins and a different number of perfect filter entries.
> The device does not provide a way to query these parameters, therefore
> parameters are required. The Altera Cyclone V SOC has support for 256
> multicast hash bins and 128 perfect filter entries, and is different than
> what's currently provided in the stmmac driver.
>

thanks a lot for these patches, I have just added some comment for the
patch #2

peppe

> Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
> ---
>   Documentation/devicetree/bindings/net/stmmac.txt |    6 ++++++
>   1 file changed, 6 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
> index 9d92d42..dbf7498 100644
> --- a/Documentation/devicetree/bindings/net/stmmac.txt
> +++ b/Documentation/devicetree/bindings/net/stmmac.txt
> @@ -34,6 +34,10 @@ Optional properties:
>   	reset phandle is given
>   - max-frame-size:	Maximum Transfer Unit (IEEE defined MTU), rather
>   			than the maximum frame size.
> +- 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
>
>   Examples:
>
> @@ -46,4 +50,6 @@ 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>;
>   	};
>

^ permalink raw reply

* [PATCH] rtnetlink: fix oops in rtnl_link_get_slave_info_data_size
From: Fernando Luis Vázquez Cao @ 2014-02-04 10:35 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: dev-yBygre7rU0TnMu66kgdUjQ, netdev-u79uwXL29TY76Z2rM5mHXA,
	David S. Miller

We should check whether rtnetlink link operations
are defined before calling get_slave_size().

Without this, the following oops can occur when
adding a tap device to OVS.

[   87.839553] BUG: unable to handle kernel NULL pointer dereference at 00000000000000a8
[   87.839595] IP: [<ffffffff813d47c0>] if_nlmsg_size+0xf0/0x220
[...]
[   87.840651] Call Trace:
[   87.840664]  [<ffffffff813d694b>] ? rtmsg_ifinfo+0x2b/0x100
[   87.840688]  [<ffffffff813c8340>] ? __netdev_adjacent_dev_insert+0x150/0x1a0
[   87.840718]  [<ffffffff813d6a50>] ? rtnetlink_event+0x30/0x40
[   87.840742]  [<ffffffff814b4144>] ? notifier_call_chain+0x44/0x70
[   87.840768]  [<ffffffff813c8946>] ? __netdev_upper_dev_link+0x3c6/0x3f0
[   87.840798]  [<ffffffffa0678d6c>] ? netdev_create+0xcc/0x160 [openvswitch]
[   87.840828]  [<ffffffffa06781ea>] ? ovs_vport_add+0x4a/0xd0 [openvswitch]
[   87.840857]  [<ffffffffa0670139>] ? new_vport+0x9/0x50 [openvswitch]
[   87.840884]  [<ffffffffa067279e>] ? ovs_vport_cmd_new+0x11e/0x210 [openvswitch]
[   87.840915]  [<ffffffff813f3efa>] ? genl_family_rcv_msg+0x19a/0x360
[   87.840941]  [<ffffffff813f40c0>] ? genl_family_rcv_msg+0x360/0x360
[   87.840967]  [<ffffffff813f4139>] ? genl_rcv_msg+0x79/0xc0
[   87.840991]  [<ffffffff813b6cf9>] ? __kmalloc_reserve.isra.25+0x29/0x80
[   87.841018]  [<ffffffff813f2389>] ? netlink_rcv_skb+0xa9/0xc0
[   87.841042]  [<ffffffff813f27cf>] ? genl_rcv+0x1f/0x30
[   87.841064]  [<ffffffff813f1988>] ? netlink_unicast+0xe8/0x1e0
[   87.841088]  [<ffffffff813f1d9a>] ? netlink_sendmsg+0x31a/0x750
[   87.841113]  [<ffffffff813aee96>] ? sock_sendmsg+0x86/0xc0
[   87.841136]  [<ffffffff813c960d>] ? __netdev_update_features+0x4d/0x200
[   87.841163]  [<ffffffff813ca94e>] ? ethtool_get_value+0x2e/0x50
[   87.841188]  [<ffffffff813af269>] ? ___sys_sendmsg+0x359/0x370
[   87.841212]  [<ffffffff813da686>] ? dev_ioctl+0x1a6/0x5c0
[   87.841236]  [<ffffffff8109c210>] ? autoremove_wake_function+0x30/0x30
[   87.841264]  [<ffffffff813ac59d>] ? sock_do_ioctl+0x3d/0x50
[   87.841288]  [<ffffffff813aca68>] ? sock_ioctl+0x1e8/0x2c0
[   87.841312]  [<ffffffff811934bf>] ? do_vfs_ioctl+0x2cf/0x4b0
[   87.841335]  [<ffffffff813afeb9>] ? __sys_sendmsg+0x39/0x70
[   87.841362]  [<ffffffff814b86f9>] ? system_call_fastpath+0x16/0x1b
[   87.841386] Code: c0 74 10 48 89 ef ff d0 83 c0 07 83 e0 fc 48 98 49 01 c7 48 89 ef e8 d0 d6 fe ff 48 85 c0 0f 84 df 00 00 00 48 8b 90 08 07 00 00 <48> 8b 8a a8 00 00 00 31 d2 48 85 c9 74 0c 48 89 ee 48 89 c7 ff 
[   87.841529] RIP  [<ffffffff813d47c0>] if_nlmsg_size+0xf0/0x220
[   87.841555]  RSP <ffff880221aa5950>
[   87.841569] CR2: 00000000000000a8
[   87.851442] ---[ end trace e42ab217691b4fc2 ]---

Signed-off-by: Fernando Luis Vazquez Cao <fernando-gVGce1chcLdL9jVzuh4AOg@public.gmane.org>
---

diff -urNp linux-3.14-rc1-orig/net/core/rtnetlink.c linux-3.14-rc1/net/core/rtnetlink.c
--- linux-3.14-rc1-orig/net/core/rtnetlink.c	2014-02-04 19:13:08.849827354 +0900
+++ linux-3.14-rc1/net/core/rtnetlink.c	2014-02-04 19:04:20.130714042 +0900
@@ -374,7 +374,7 @@ static size_t rtnl_link_get_slave_info_d
 	if (!master_dev)
 		return 0;
 	ops = master_dev->rtnl_link_ops;
-	if (!ops->get_slave_size)
+	if (!ops || !ops->get_slave_size)
 		return 0;
 	/* IFLA_INFO_SLAVE_DATA + nested data */
 	return nla_total_size(sizeof(struct nlattr)) +

^ permalink raw reply

* Re: [PATCH] net:cpsw: Pass unhandled ioctl's on to generic phy ioctl
From: Ben Hutchings @ 2014-02-04 10:50 UTC (permalink / raw)
  To: Stefan Sørensen; +Cc: mugunthanvnm, davem, netdev
In-Reply-To: <1391500242-10554-1-git-send-email-stefan.sorensen@spectralink.com>

[-- Attachment #1: Type: text/plain, Size: 1436 bytes --]

On Tue, 2014-02-04 at 08:50 +0100, Stefan Sørensen wrote:
> This patch allows the use of a generic timestamping phy connected
> to the cpsw if CPTS support is not enabled.

What if CPTS support is enabled in the driver, but this particular
machine doesn't have it and uses a timestamping PHY instead?

> Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
> ---
>  drivers/net/ethernet/ti/cpsw.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index bde63e3..a03cfb3 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
> @@ -1486,12 +1486,12 @@ static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
>  #endif
>  	case SIOCGMIIPHY:
>  		data->phy_id = priv->slaves[slave_no].phy->addr;

It looks like this existing code is broken, as the phy pointer can be
NULL!

> -		break;
> -	default:
> -		return -ENOTSUPP;
> +		return 0;
>  	}
>  
> -	return 0;
> +	if (!priv->slaves[slave_no].phy)
> +		return -EINVAL;
> +	return phy_mii_ioctl(priv->slaves[slave_no].phy, req, cmd);

This presumably also enables SIOC{G,S}MIIREG, but you didn't mention
that.

Ben.

>  }
>  
>  static void cpsw_ndo_tx_timeout(struct net_device *ndev)

-- 
Ben Hutchings
One of the nice things about standards is that there are so many of them.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply

* Re: [PATCH] dp83640: Support a configurable number of periodic outputs
From: Ben Hutchings @ 2014-02-04 10:53 UTC (permalink / raw)
  To: Richard Cochran; +Cc: Stefan Sørensen, netdev
In-Reply-To: <20140204092939.GA9862@netboy>

[-- Attachment #1: Type: text/plain, Size: 2192 bytes --]

On Tue, 2014-02-04 at 10:29 +0100, Richard Cochran wrote:
> On Tue, Feb 04, 2014 at 09:52:22AM +0100, Stefan Sørensen wrote:
> > The driver is currently limited to a single periodic output.
> > This patch makes the number of peridodic output dynamic by
> > dropping the gpio_tab module parameter and adding cal_gpio,
> > perout_gpio_tab and extts_gpio_tabs parameters.
> 
> ...
> 
> >  module_param(chosen_phy, int, 0444);
> > -module_param_array(gpio_tab, ushort, NULL, 0444);
> > +module_param(cal_gpio, int, 0444);
> > +module_param_array(perout_gpio_tab, int, &n_perout, 0444);
> > +module_param_array(extts_gpio_tab, int, &n_extts, 0444);
> >  
> >  MODULE_PARM_DESC(chosen_phy, \
> >  	"The address of the PHY to use for the ancillary clock features");
> > -MODULE_PARM_DESC(gpio_tab, \
> > -	"Which GPIO line to use for which purpose: cal,perout,extts1,...,extts6");
> > +MODULE_PARM_DESC(cal_gpio, "Which GPIO line to use for calibration");
> > +MODULE_PARM_DESC(perout_gpio_tab, "Which GPIO lines to use for periodic output");
> > +MODULE_PARM_DESC(extts_gpio_tab, "Which GPIO lines to use for external timestamping");
> 
> Modules parameters are surely easiest (for the developer), but perhaps
> the time has come for the "right way."
> 
> Currently there is no interface for configuring the GPIOs used by PHC
> devices, and last year I was going to add the GPIOs to the igb
> driver. The conclusion of the discussion was that module parameters
> are bad for this, but ethtool is good.
> 
>   http://www.spinics.net/lists/netdev/msg237692.html
> 
> [ I did not follow through to come up with an ethtool way of configuring
>   the igb pins. ]
> 
> Even though it is more work, I think the way forward is to invent a
> way to let the user configure this kind of thing via ethtool. Would
> you care to take a stab at this?

It seems to me that this is board configuration, not user configuration,
so it should be defined in DT or ACPI or whatever.

Are there boards which expose multiple GPIOs for users to plug together
PPS signals?

Ben.

-- 
Ben Hutchings
One of the nice things about standards is that there are so many of them.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply

* [PATCH net] 6lowpan: add missing fragment list spinlock
From: Alexander Aring @ 2014-02-04 10:57 UTC (permalink / raw)
  To: alex.bluesman.smirnov
  Cc: dbaryshkov, davem, linux-zigbee-devel, netdev, Alexander Aring

This patch adds a missing spinlock hold in the timer expire function.
The timer expire function will occur after specific timeout for
fragmented 6lowpan packets which are still in the fragment list.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
Some little note:

Currently I working on patches for net-next to use the inet_frag api
for 6lowpan fragmentation. This api is also used in ipv4 and ipv6.
The upcomming patch series fix also some other in the current 6lowpan
fragmentation handling, I will send them soon.

This patch is for net and fix one of the main race condition in the
current fragmentation api of 6lowpan. Maybe there are some 6lowpan users
which use some older kernels.

 net/ieee802154/6lowpan.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 48b25c0..757079d 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -197,7 +197,9 @@ static void lowpan_fragment_timer_expired(unsigned long entry_addr)
 
 	pr_debug("timer expired for frame with tag %d\n", entry->tag);
 
+	spin_lock_bh(&flist_lock);
 	list_del(&entry->list);
+	spin_unlock_bh(&flist_lock);
 	dev_kfree_skb(entry->skb);
 	kfree(entry);
 }
-- 
1.8.5.3

^ permalink raw reply related

* Re: [PATCH] rtnetlink: fix oops in rtnl_link_get_slave_info_data_size
From: Jiri Pirko @ 2014-02-04 10:59 UTC (permalink / raw)
  To: Fernando Luis Vázquez Cao
  Cc: dev-yBygre7rU0TnMu66kgdUjQ, netdev-u79uwXL29TY76Z2rM5mHXA,
	David S. Miller
In-Reply-To: <1391510102.6282.9.camel@nexus>

Tue, Feb 04, 2014 at 11:35:02AM CET, fernando_b1-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org wrote:
>We should check whether rtnetlink link operations
>are defined before calling get_slave_size().
>
>Without this, the following oops can occur when
>adding a tap device to OVS.
>
>[   87.839553] BUG: unable to handle kernel NULL pointer dereference at 00000000000000a8
>[   87.839595] IP: [<ffffffff813d47c0>] if_nlmsg_size+0xf0/0x220
>[...]
>[   87.840651] Call Trace:
>[   87.840664]  [<ffffffff813d694b>] ? rtmsg_ifinfo+0x2b/0x100
>[   87.840688]  [<ffffffff813c8340>] ? __netdev_adjacent_dev_insert+0x150/0x1a0
>[   87.840718]  [<ffffffff813d6a50>] ? rtnetlink_event+0x30/0x40
>[   87.840742]  [<ffffffff814b4144>] ? notifier_call_chain+0x44/0x70
>[   87.840768]  [<ffffffff813c8946>] ? __netdev_upper_dev_link+0x3c6/0x3f0
>[   87.840798]  [<ffffffffa0678d6c>] ? netdev_create+0xcc/0x160 [openvswitch]
>[   87.840828]  [<ffffffffa06781ea>] ? ovs_vport_add+0x4a/0xd0 [openvswitch]
>[   87.840857]  [<ffffffffa0670139>] ? new_vport+0x9/0x50 [openvswitch]
>[   87.840884]  [<ffffffffa067279e>] ? ovs_vport_cmd_new+0x11e/0x210 [openvswitch]
>[   87.840915]  [<ffffffff813f3efa>] ? genl_family_rcv_msg+0x19a/0x360
>[   87.840941]  [<ffffffff813f40c0>] ? genl_family_rcv_msg+0x360/0x360
>[   87.840967]  [<ffffffff813f4139>] ? genl_rcv_msg+0x79/0xc0
>[   87.840991]  [<ffffffff813b6cf9>] ? __kmalloc_reserve.isra.25+0x29/0x80
>[   87.841018]  [<ffffffff813f2389>] ? netlink_rcv_skb+0xa9/0xc0
>[   87.841042]  [<ffffffff813f27cf>] ? genl_rcv+0x1f/0x30
>[   87.841064]  [<ffffffff813f1988>] ? netlink_unicast+0xe8/0x1e0
>[   87.841088]  [<ffffffff813f1d9a>] ? netlink_sendmsg+0x31a/0x750
>[   87.841113]  [<ffffffff813aee96>] ? sock_sendmsg+0x86/0xc0
>[   87.841136]  [<ffffffff813c960d>] ? __netdev_update_features+0x4d/0x200
>[   87.841163]  [<ffffffff813ca94e>] ? ethtool_get_value+0x2e/0x50
>[   87.841188]  [<ffffffff813af269>] ? ___sys_sendmsg+0x359/0x370
>[   87.841212]  [<ffffffff813da686>] ? dev_ioctl+0x1a6/0x5c0
>[   87.841236]  [<ffffffff8109c210>] ? autoremove_wake_function+0x30/0x30
>[   87.841264]  [<ffffffff813ac59d>] ? sock_do_ioctl+0x3d/0x50
>[   87.841288]  [<ffffffff813aca68>] ? sock_ioctl+0x1e8/0x2c0
>[   87.841312]  [<ffffffff811934bf>] ? do_vfs_ioctl+0x2cf/0x4b0
>[   87.841335]  [<ffffffff813afeb9>] ? __sys_sendmsg+0x39/0x70
>[   87.841362]  [<ffffffff814b86f9>] ? system_call_fastpath+0x16/0x1b
>[   87.841386] Code: c0 74 10 48 89 ef ff d0 83 c0 07 83 e0 fc 48 98 49 01 c7 48 89 ef e8 d0 d6 fe ff 48 85 c0 0f 84 df 00 00 00 48 8b 90 08 07 00 00 <48> 8b 8a a8 00 00 00 31 d2 48 85 c9 74 0c 48 89 ee 48 89 c7 ff 
>[   87.841529] RIP  [<ffffffff813d47c0>] if_nlmsg_size+0xf0/0x220
>[   87.841555]  RSP <ffff880221aa5950>
>[   87.841569] CR2: 00000000000000a8
>[   87.851442] ---[ end trace e42ab217691b4fc2 ]---
>
>Signed-off-by: Fernando Luis Vazquez Cao <fernando-gVGce1chcLdL9jVzuh4AOg@public.gmane.org>
>---
>
>diff -urNp linux-3.14-rc1-orig/net/core/rtnetlink.c linux-3.14-rc1/net/core/rtnetlink.c
>--- linux-3.14-rc1-orig/net/core/rtnetlink.c	2014-02-04 19:13:08.849827354 +0900
>+++ linux-3.14-rc1/net/core/rtnetlink.c	2014-02-04 19:04:20.130714042 +0900
>@@ -374,7 +374,7 @@ static size_t rtnl_link_get_slave_info_d
> 	if (!master_dev)
> 		return 0;
> 	ops = master_dev->rtnl_link_ops;
>-	if (!ops->get_slave_size)
>+	if (!ops || !ops->get_slave_size)
> 		return 0;
> 	/* IFLA_INFO_SLAVE_DATA + nested data */
> 	return nla_total_size(sizeof(struct nlattr)) +
>
>


Oops.

Acked-by: Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>

^ permalink raw reply

* Re: [PATCH RFC v3 0/12] vti4: prepare namespace and interfamily support.
From: Christophe Gouault @ 2014-02-04 11:05 UTC (permalink / raw)
  To: Steffen Klassert; +Cc: netdev, Saurabh Mohan
In-Reply-To: <20140130095610.GR31491@secunet.com>

On 01/30/2014 10:56 AM, Steffen Klassert wrote:
> On Wed, Jan 29, 2014 at 11:55:40AM +0100, Christophe Gouault wrote:
> [...]
>> => there is no check that the forward vti security policy was
>> enforced.
>>
>
> Yes, that's true and this is a real problem. If we want to support
> namespace transitions with vti, we can't know if a packet is going
> to be forwarded or locally received in the other namespace. This means
> that we don't know if we should enforce a input or a forward policy.
>
> All we can do here, is to enforce a input policy before we do the
> namespace transition in the receive path. The patch below (on top
> of the vti patchset) should do this.

Hi Steffen, and thank you for the patch.

I tested it within a single netns, then with cross-netns. Both work as
follows:

- all the vti SPs and SAs must be created in the "outer" netns.
- only outbound and inbound vti policies are taken into account, not
   forward vti policies.

in output:

- a global SPD lookup is performed before entering the vti
   interface (in the inner netns). It can be bypassed by adding a policy
   such as:

    ip xfrm policy add dir out mark 0 dev vti1

- then a vti SPD lookup is performed with the vti interface (in the
   outer netns).

in input:

- a global inbound policy check is done (in the outer netns)
   on the IPsec packet by the vti interface.
- then the packet is decrypted.
- then a vti inbound policy check is done on the decrypted packet
   (in the outer netns).
- then the packet device is set to the vti interface and its netns
   is changed to the inner netns.
- finally, a global inbound/forward policy check is done on the
   plaintext packet (without security context), as if it has just arrived
   in plaintext from the network.

> But this has the implication that forward policies do not make
> much sense in combination with vti. This is a bit contrary to
> traditional xfrm processing. But on the other hand, we receive
> plaintext packets from the vti device so we should not check
> for any IPsec processing that happened before we received the
> packets via the vti device.

Unfortunately, the inbound/forward policy checks do not take the inbound
interface into account (__xfrm_decode_session does not properly fill in
the iif field of the flowi), so in the last global policy check, there
is no way of differentiating a plaintext packet directly received from
the network from a plaintext packet that was processed by a vti interface.

Intuitively, I would like to do the same as in output: add a policy that
accepts packets received via a vti interface, and only check more
closely other packets directly received from the network.

Best Regards,
Christophe.

^ permalink raw reply

* [PATCH net,stable] net: qmi_wwan: add Netgear Aircard 340U
From: Bjørn Mork @ 2014-02-04 12:04 UTC (permalink / raw)
  To: netdev; +Cc: linux-usb, Bjørn Mork

This device was mentioned in an OpenWRT forum.  Seems to have a "standard"
Sierra Wireless ifnumber to function layout:
 0: qcdm
 2: nmea
 3: modem
 8: qmi
 9: storage

Signed-off-by: Bjørn Mork <bjorn@mork.no>
---
 drivers/net/usb/qmi_wwan.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 23bdd5b9274d..ef4a45aea5aa 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -723,6 +723,7 @@ static const struct usb_device_id products[] = {
 	{QMI_FIXED_INTF(0x1199, 0x68a2, 8)},	/* Sierra Wireless MC7710 in QMI mode */
 	{QMI_FIXED_INTF(0x1199, 0x68a2, 19)},	/* Sierra Wireless MC7710 in QMI mode */
 	{QMI_FIXED_INTF(0x1199, 0x901c, 8)},    /* Sierra Wireless EM7700 */
+	{QMI_FIXED_INTF(0x1199, 0x9051, 8)},	/* Netgear AirCard 340U */
 	{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},	/* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
 	{QMI_FIXED_INTF(0x2357, 0x0201, 4)},	/* TP-LINK HSUPA Modem MA180 */
 	{QMI_FIXED_INTF(0x2357, 0x9000, 4)},	/* TP-LINK MA260 */
-- 
1.9.rc1

^ permalink raw reply related

* Re: [PATCH v3 0/5] can: sja1000: cleanups and new OF property
From: Florian Vaussard @ 2014-02-04 12:13 UTC (permalink / raw)
  To: Andreas Larsson, Marc Kleine-Budde, Wolfgang Grandegger
  Cc: linux-can, netdev, sparclinux, linux-kernel
In-Reply-To: <52F0A29C.9000604@gaisler.com>

On 02/04/2014 09:19 AM, Andreas Larsson wrote:
> On 2014-01-31 14:50, Andreas Larsson wrote:
>> On 2014-01-31 14:40, Marc Kleine-Budde wrote:
>>> On 01/31/2014 02:34 PM, Florian Vaussard wrote:
>>>> Hello,
>>>>
>>>> (could someone with a SJA1000 on SPARC perform a functional test
>>>> to see if interrupts are working? it would be great :-)
>>>>
>>>> Changes since v2:
>>>> - Dropped patch 1 "can: sja1000: remove unused defines"
>>>> - Addressed Marc's comments on patch 4 and 6 (now 3 and 5)
>>>>
>>>> Changes since v1:
>>>> - Merge sja1000_of_platform.c into sja1000_platform.c (patch 4)
>>>>
>>>> The first part of this series performs serveral small cleanups
>>>> (patches 1 and 2).
>>>>
>>>> Patch 3 merges sja1000_of_platform.c into sja1000_platform.c.
>>>> Changes are pretty conservatives (mostly copy/paste/move). IRQ
>>>> is treated differently in the OF and non-OF versions, thus this
>>>> is where the fused version differs the most.
>>>>
>>>> The final part introduces the 'reg-io-width' binding (already used
>>>> by some other drivers) to perform a similar job as what was done
>>>> with IORESOURCE_MEM_XXBIT. This is needed on my system to correctly
>>>> take into account the aliasing of the address bus.
>>>>
>>>> All patches were tested using OF boot on my OMAP3 system with a
>>>> memory-mapped SJA1000. Thus, the non-OF path is not tested, as
>>>> I do not have a platform data at hand.
>>>
>>> Nice, looks good now. I'll give Andreas some time to test on sparc and
>>> then apply the patches.
>>
>>
>> I am on it. I will dig up some hardware for this on Monday to test it.
> 
> Works splendidly. You can add:
> 
> Tested-by: Andreas Larsson <andreas@gaisler.com>
> 

Waohhh, great :D Thank you!

Regards,
Florian

^ permalink raw reply

* [GIT PULL nf] IPVS Fixes for v3.14
From: Simon Horman @ 2014-02-04 12:34 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: lvs-devel, netdev, netfilter-devel, Wensong Zhang,
	Julian Anastasov, Simon Horman

Hi Pablo,

please consider the following fixes for IPVS for v3.14.

It consists of a fix for AF assingment by Michal Kubecek.

I believe this problem is present all the way back to v2.6.30, however, the
change only applies as far back as v3.10.  Please let me know if you would
like me to make some patches for older -stable versions.


The following changes since commit d922e1cb1ea17ac7f0a5c3c2be98d4bd80d055b8:

  net: Document promote_secondaries (2014-01-27 20:39:21 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs.git tags/ipvs-fixes-for-v3.14

for you to fetch changes up to 2a971354e74f3837d14b9c8d7f7983b0c9c330e4:

  ipvs: fix AF assignment in ip_vs_conn_new() (2014-02-04 21:13:47 +0900)

----------------------------------------------------------------
IPVS Fixes for v3.14

Correction AF assignment by Michal Kubecek.
This resolves a problem whereby only the first 4 bytes of an IPv6
destination may be copied for a fwmark virtual service.

This problem appears to have been introduced by
be8be9eccbf2d908 "ipvs: Fix IPv4 FWMARK virtual services"
in 2.6.30.

----------------------------------------------------------------
Michal Kubecek (1):
      ipvs: fix AF assignment in ip_vs_conn_new()

 net/netfilter/ipvs/ip_vs_conn.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

^ permalink raw reply

* [PATCH nf] ipvs: fix AF assignment in ip_vs_conn_new()
From: Simon Horman @ 2014-02-04 12:34 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: lvs-devel, netdev, netfilter-devel, Wensong Zhang,
	Julian Anastasov, Michal Kubecek, Bogdano Arendartchuk,
	Simon Horman
In-Reply-To: <1391517261-27222-1-git-send-email-horms@verge.net.au>

From: Michal Kubecek <mkubecek@suse.cz>

If a fwmark is passed to ip_vs_conn_new(), it is passed in
vaddr, not daddr. Therefore we should set AF to AF_UNSPEC in
vaddr assignment (like we do in ip_vs_ct_in_get()), otherwise we
may copy only first 4 bytes of an IPv6 address into cp->daddr.

Signed-off-by: Bogdano Arendartchuk <barendartchuk@suse.com>
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
Acked-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
 net/netfilter/ipvs/ip_vs_conn.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 59a1a85..a8eb0a8 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -871,11 +871,11 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
 	cp->protocol	   = p->protocol;
 	ip_vs_addr_set(p->af, &cp->caddr, p->caddr);
 	cp->cport	   = p->cport;
-	ip_vs_addr_set(p->af, &cp->vaddr, p->vaddr);
-	cp->vport	   = p->vport;
-	/* proto should only be IPPROTO_IP if d_addr is a fwmark */
+	/* proto should only be IPPROTO_IP if p->vaddr is a fwmark */
 	ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
-		       &cp->daddr, daddr);
+		       &cp->vaddr, p->vaddr);
+	cp->vport	   = p->vport;
+	ip_vs_addr_set(p->af, &cp->daddr, daddr);
 	cp->dport          = dport;
 	cp->flags	   = flags;
 	cp->fwmark         = fwmark;
-- 
1.8.5.2

^ permalink raw reply related

* Re: linux-3.14-rc1 & PACKET_QDISC_BYPASS : slow_path warning
From: Daniel Borkmann @ 2014-02-04 12:56 UTC (permalink / raw)
  To: Mathias Kretschmer
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Felix Fietkau, Jesper Dangaard Brouer
In-Reply-To: <52F01C97.20001-8LS2qeF34IpklNlQbfROjRvVK+yQ3ZXh@public.gmane.org>

Hi Mathias, [cc'ing Felix]

On 02/03/2014 11:47 PM, Mathias Kretschmer wrote:
> Hi Daniel,
>
> we are developing a wired/wireless MPLS switch. Currently the data plane runs in user space using PF_PACKET sockets via RX_RING/TX_RING.
>
> We had hoped to test the PACKET_QDISC_BYPASS option since this seems to be the proper optimization for our purposes.
>
> Unfortunately, we're seeing a 'slow path' warning for every packet that is being sent out. With PACKET_QDISC_BYPASS disabled, no warnings are dumped. Hardware is an older AMD Geode LX embedded board (ALiX).
>
> BTW, this happens while sending via a wireless (802.11) adhoc interface. Hence, it might be an interaction with the ieee80211 sub system.

Hm, so the WARN_ON() is triggered inside ath9k driver in relation to 802.11 QoS,
and came in from commit 066dae93bdf ("ath9k: rework tx queue selection and fix
queue stopping/waking"). We did the stress testing of that option for PF_PACKET
on 10Gbit/s NICs. Seems to me you might be running into the same issue when using
pktgen as it randomly or per round-robin selects tx queues as well? Not entirely
sure how necessary this WARN_ON() is though, Felix? I think QDISC_BYPASS might not
be the best option in your case, perhaps you will run into increased power usage
in your NIC as a side-effect?

Cheers,

Daniel
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: linux-3.14-rc1 & PACKET_QDISC_BYPASS : slow_path warning
From: Mathias Kretschmer @ 2014-02-04 13:13 UTC (permalink / raw)
  To: Daniel Borkmann
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Felix Fietkau, Jesper Dangaard Brouer
In-Reply-To: <52F0E361.9000304-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

Hi Daniel,

On 02/04/2014 01:56 PM, Daniel Borkmann wrote:
> Hi Mathias, [cc'ing Felix]
>
> On 02/03/2014 11:47 PM, Mathias Kretschmer wrote:
>> Hi Daniel,
>>
>> we are developing a wired/wireless MPLS switch. Currently the data plane runs in
>> user space using PF_PACKET sockets via RX_RING/TX_RING.
>>
>> We had hoped to test the PACKET_QDISC_BYPASS option since this seems to be the
>> proper optimization for our purposes.
>>
>> Unfortunately, we're seeing a 'slow path' warning for every packet that is being
>> sent out. With PACKET_QDISC_BYPASS disabled, no warnings are dumped. Hardware is
>> an older AMD Geode LX embedded board (ALiX).
>>
>> BTW, this happens while sending via a wireless (802.11) adhoc interface. Hence, it
>> might be an interaction with the ieee80211 sub system.
>
> Hm, so the WARN_ON() is triggered inside ath9k driver in relation to 802.11 QoS,
> and came in from commit 066dae93bdf ("ath9k: rework tx queue selection and fix
> queue stopping/waking"). We did the stress testing of that option for PF_PACKET
> on 10Gbit/s NICs. Seems to me you might be running into the same issue when using
> pktgen as it randomly or per round-robin selects tx queues as well? Not entirely
> sure how necessary this WARN_ON() is though, Felix? I think QDISC_BYPASS might not
> be the best option in your case, perhaps you will run into increased power usage
> in your NIC as a side-effect?

I'm not familiar with the exact implementation details, but from the description of 
this option, it seems to me that this is exactly what one would want to use if the 
goal is to send an Ethernet frame out on a particular interface without any further 
processing by the kernel.

Why would this increase the power usage on the NIC ?  Due to a higher achievable 
packet rate ?  That would be acceptable :)

Cheers,

Mathias


> Cheers,
>
> Daniel

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [bisected] Re: WARNING: at net/ipv4/devinet.c:1599
From: Geert Uytterhoeven @ 2014-02-04 14:19 UTC (permalink / raw)
  To: David S. Miller, Jiri Pirko
  Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org

On Sun, Jan 26, 2014 at 10:56 AM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> On m68k/ARAnyM:
>
> WARNING: CPU: 0 PID: 407 at net/ipv4/devinet.c:1599 0x316a99()
> Modules linked in:
> CPU: 0 PID: 407 Comm: ifconfig Not tainted
> 3.13.0-atari-09263-g0c71d68014d1 #1378
> Stack from 10c4fdf0:
>         10c4fdf0 002ffabb 000243e8 00000000 008ced6c 00024416 00316a99 0000063f
>         00316a99 00000009 00000000 002501b4 00316a99 0000063f c0a86117 00000080
>         c0a86117 00ad0c90 00250a5a 00000014 00ad0c90 00000000 00000000 00000001
>         00b02dd0 00356594 00000000 00356594 c0a86117 eff6c9e4 008ced6c 00000002
>         008ced60 0024f9b4 00250b52 00ad0c90 00000000 00000000 00252390 00ad0c90
>         eff6c9e4 0000004f 00000000 00000000 eff6c9e4 8000e25c eff6c9e4 80001020
> Call Trace: [<000243e8>] warn_slowpath_common+0x52/0x6c
>  [<00024416>] warn_slowpath_null+0x14/0x1a
>  [<002501b4>] rtmsg_ifa+0xdc/0xf0
>  [<00250a5a>] __inet_insert_ifa+0xd6/0x1c2
>  [<0024f9b4>] inet_abc_len+0x0/0x42
>  [<00250b52>] inet_insert_ifa+0xc/0x12
>  [<00252390>] devinet_ioctl+0x2ae/0x5d6
>  [<00020000>] _060_fpsp_effadd+0xc90c/0xd518
>  [<00020000>] _060_fpsp_effadd+0xc90c/0xd518
>  [<002530ec>] inet_ioctl+0x120/0x14e
>  [<00008916>] atari_scc_console_write+0x42/0x5c
>  [<00008916>] atari_scc_console_write+0x42/0x5c
>  [<001f7666>] sock_ioctl+0x56/0x256
>  [<00008916>] atari_scc_console_write+0x42/0x5c
>  [<00095434>] vfs_ioctl+0x1c/0x30
>  [<00008916>] atari_scc_console_write+0x42/0x5c
>  [<0009559c>] do_vfs_ioctl+0x7a/0x3b8
>  [<00008916>] atari_scc_console_write+0x42/0x5c
>  [<00002884>] buserr+0x20/0x28
>  [<00008916>] atari_scc_console_write+0x42/0x5c
>  [<00095910>] SyS_ioctl+0x36/0x5a
>  [<00008916>] atari_scc_console_write+0x42/0x5c
>  [<00008916>] atari_scc_console_write+0x42/0x5c
>  [<00002980>] syscall+0x8/0xc
>  [<00008916>] atari_scc_console_write+0x42/0x5c
>  [<0010c00b>] mext_leaf_block+0x443/0x81e
>
> ---[ end trace 44b14c97c2210758 ]---
>
> Adding some debugging code reveals that net_fill_ifaddr() fails in
>
>     put_cacheinfo(skb, ifa->ifa_cstamp, ifa->ifa_tstamp,
>                               preferred, valid))
>
> nla_put complains:
>
> lib/nlattr.c:454: skb_tailroom(skb) = 12, nla_total_size(attrlen) = 20

Bisected to:

commit ad6c81359fc3e6086d1d6f91acda9d5d0e64b2c3
Author: Jiri Pirko <jiri@resnulli.us>
Date:   Sun Dec 8 12:16:10 2013 +0100

    ipv4: add support for IFA_FLAGS nl attribute

    Signed-off-by: Jiri Pirko <jiri@resnulli.us>
    Signed-off-by: David S. Miller <davem@davemloft.net>

Reverting that commit on v3.14-rc1 fixes the problem.

I don't know why it fails. My first guess was the alignment of ifa_flags
(on m68k __u32 is aligned to 2 bytes, so there's no implicit padding):

        __be32                  ifa_broadcast;
        unsigned char           ifa_scope;
        unsigned char           ifa_prefixlen;
        __u32                   ifa_flags;

but adding 2 bytes of explicit alignment didn't help.

Anyone with a clue?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: linux-3.14-rc1 & PACKET_QDISC_BYPASS : slow_path warning
From: Daniel Borkmann @ 2014-02-04 14:25 UTC (permalink / raw)
  To: Mathias Kretschmer
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Felix Fietkau, Jesper Dangaard Brouer
In-Reply-To: <52F0E771.8070904-8LS2qeF34IpklNlQbfROjRvVK+yQ3ZXh@public.gmane.org>

On 02/04/2014 02:13 PM, Mathias Kretschmer wrote:
> On 02/04/2014 01:56 PM, Daniel Borkmann wrote:
>> On 02/03/2014 11:47 PM, Mathias Kretschmer wrote:
...
>>> we are developing a wired/wireless MPLS switch. Currently the data plane runs in
>>> user space using PF_PACKET sockets via RX_RING/TX_RING.
>>>
>>> We had hoped to test the PACKET_QDISC_BYPASS option since this seems to be the
>>> proper optimization for our purposes.
>>>
>>> Unfortunately, we're seeing a 'slow path' warning for every packet that is being
>>> sent out. With PACKET_QDISC_BYPASS disabled, no warnings are dumped. Hardware is
>>> an older AMD Geode LX embedded board (ALiX).
>>>
>>> BTW, this happens while sending via a wireless (802.11) adhoc interface. Hence, it
>>> might be an interaction with the ieee80211 sub system.
>>
>> Hm, so the WARN_ON() is triggered inside ath9k driver in relation to 802.11 QoS,
>> and came in from commit 066dae93bdf ("ath9k: rework tx queue selection and fix
>> queue stopping/waking"). We did the stress testing of that option for PF_PACKET
>> on 10Gbit/s NICs. Seems to me you might be running into the same issue when using
>> pktgen as it randomly or per round-robin selects tx queues as well? Not entirely
>> sure how necessary this WARN_ON() is though, Felix? I think QDISC_BYPASS might not
>> be the best option in your case, perhaps you will run into increased power usage
>> in your NIC as a side-effect?
>
> I'm not familiar with the exact implementation details, but from the description of this option, it seems to me that this is exactly what one would want to use if the goal is to send an Ethernet frame out on a particular interface without any further processing by the kernel.
>
> Why would this increase the power usage on the NIC ?  Due to a higher achievable packet rate ?  That would be acceptable :)

I'm not too familiar with the ieee80211 sub system, so I let Felix answer side
effects and if actually the WARN_ON() is needed. ;) PACKET_QDISC_BYPASS is, as
documented, designed for advanced pktgen resp. traffic generator like scenarios
where you just sort of "brute force" packets to your NIC to stress test a remote
machine for further analysis. I don't think it's very useful in your scenario
when you have a wired/wireless MPLS switch, you rather might want to buffer/queue
and therefore use qdisc layer instead.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: linux-3.14-rc1 & PACKET_QDISC_BYPASS : slow_path warning
From: Mathias Kretschmer @ 2014-02-04 14:35 UTC (permalink / raw)
  To: Daniel Borkmann
  Cc: netdev, linux-wireless@vger.kernel.org, Felix Fietkau,
	Jesper Dangaard Brouer
In-Reply-To: <52F0F86C.3050402@redhat.com>

On 02/04/2014 03:25 PM, Daniel Borkmann wrote:
> On 02/04/2014 02:13 PM, Mathias Kretschmer wrote:
>> On 02/04/2014 01:56 PM, Daniel Borkmann wrote:
>>> On 02/03/2014 11:47 PM, Mathias Kretschmer wrote:
> ...
>>>> we are developing a wired/wireless MPLS switch. Currently the data plane runs in
>>>> user space using PF_PACKET sockets via RX_RING/TX_RING.
>>>>
>>>> We had hoped to test the PACKET_QDISC_BYPASS option since this seems to be the
>>>> proper optimization for our purposes.
>>>>
>>>> Unfortunately, we're seeing a 'slow path' warning for every packet that is being
>>>> sent out. With PACKET_QDISC_BYPASS disabled, no warnings are dumped. Hardware is
>>>> an older AMD Geode LX embedded board (ALiX).
>>>>
>>>> BTW, this happens while sending via a wireless (802.11) adhoc interface. Hence, it
>>>> might be an interaction with the ieee80211 sub system.
>>>
>>> Hm, so the WARN_ON() is triggered inside ath9k driver in relation to 802.11 QoS,
>>> and came in from commit 066dae93bdf ("ath9k: rework tx queue selection and fix
>>> queue stopping/waking"). We did the stress testing of that option for PF_PACKET
>>> on 10Gbit/s NICs. Seems to me you might be running into the same issue when using
>>> pktgen as it randomly or per round-robin selects tx queues as well? Not entirely
>>> sure how necessary this WARN_ON() is though, Felix? I think QDISC_BYPASS might not
>>> be the best option in your case, perhaps you will run into increased power usage
>>> in your NIC as a side-effect?
>>
>> I'm not familiar with the exact implementation details, but from the description
>> of this option, it seems to me that this is exactly what one would want to use if
>> the goal is to send an Ethernet frame out on a particular interface without any
>> further processing by the kernel.
>>
>> Why would this increase the power usage on the NIC ?  Due to a higher achievable
>> packet rate ?  That would be acceptable :)
>
> I'm not too familiar with the ieee80211 sub system, so I let Felix answer side
> effects and if actually the WARN_ON() is needed. ;) PACKET_QDISC_BYPASS is, as
> documented, designed for advanced pktgen resp. traffic generator like scenarios
> where you just sort of "brute force" packets to your NIC to stress test a remote
> machine for further analysis. I don't think it's very useful in your scenario
> when you have a wired/wireless MPLS switch, you rather might want to buffer/queue
> and therefore use qdisc layer instead.

Hm, I was hoping/assuming that we still get to use hardware queues, if provided by 
the driver. The main goal was to avoid any further PF_PACKET framework overhead.

If the WARN_ON() issue gets solved, we will revisit this option and evaluate its 
applicability.

Thanks,

Mathias

^ permalink raw reply

* Re: linux-3.14-rc1 & PACKET_QDISC_BYPASS : slow_path warning
From: Felix Fietkau @ 2014-02-04 14:48 UTC (permalink / raw)
  To: Mathias Kretschmer, Daniel Borkmann
  Cc: netdev, linux-wireless@vger.kernel.org, Jesper Dangaard Brouer
In-Reply-To: <52F0FA96.7090903@fokus.fraunhofer.de>

On 2014-02-04 15:35, Mathias Kretschmer wrote:
> On 02/04/2014 03:25 PM, Daniel Borkmann wrote:
>> On 02/04/2014 02:13 PM, Mathias Kretschmer wrote:
>>> On 02/04/2014 01:56 PM, Daniel Borkmann wrote:
>>>> On 02/03/2014 11:47 PM, Mathias Kretschmer wrote:
>> ...
>>>>> we are developing a wired/wireless MPLS switch. Currently the data plane runs in
>>>>> user space using PF_PACKET sockets via RX_RING/TX_RING.
>>>>>
>>>>> We had hoped to test the PACKET_QDISC_BYPASS option since this seems to be the
>>>>> proper optimization for our purposes.
>>>>>
>>>>> Unfortunately, we're seeing a 'slow path' warning for every packet that is being
>>>>> sent out. With PACKET_QDISC_BYPASS disabled, no warnings are dumped. Hardware is
>>>>> an older AMD Geode LX embedded board (ALiX).
>>>>>
>>>>> BTW, this happens while sending via a wireless (802.11) adhoc interface. Hence, it
>>>>> might be an interaction with the ieee80211 sub system.
>>>>
>>>> Hm, so the WARN_ON() is triggered inside ath9k driver in relation to 802.11 QoS,
>>>> and came in from commit 066dae93bdf ("ath9k: rework tx queue selection and fix
>>>> queue stopping/waking"). We did the stress testing of that option for PF_PACKET
>>>> on 10Gbit/s NICs. Seems to me you might be running into the same issue when using
>>>> pktgen as it randomly or per round-robin selects tx queues as well? Not entirely
>>>> sure how necessary this WARN_ON() is though, Felix? I think QDISC_BYPASS might not
>>>> be the best option in your case, perhaps you will run into increased power usage
>>>> in your NIC as a side-effect?
>>>
>>> I'm not familiar with the exact implementation details, but from the description
>>> of this option, it seems to me that this is exactly what one would want to use if
>>> the goal is to send an Ethernet frame out on a particular interface without any
>>> further processing by the kernel.
>>>
>>> Why would this increase the power usage on the NIC ?  Due to a higher achievable
>>> packet rate ?  That would be acceptable :)
>>
>> I'm not too familiar with the ieee80211 sub system, so I let Felix answer side
>> effects and if actually the WARN_ON() is needed. ;) PACKET_QDISC_BYPASS is, as
>> documented, designed for advanced pktgen resp. traffic generator like scenarios
>> where you just sort of "brute force" packets to your NIC to stress test a remote
>> machine for further analysis. I don't think it's very useful in your scenario
>> when you have a wired/wireless MPLS switch, you rather might want to buffer/queue
>> and therefore use qdisc layer instead.
> 
> Hm, I was hoping/assuming that we still get to use hardware queues, if provided by 
> the driver. The main goal was to avoid any further PF_PACKET framework overhead.
> 
> If the WARN_ON() issue gets solved, we will revisit this option and evaluate its 
> applicability.
The reason for the WARN_ON is probably either the .ndo_select_queue call
is not run, or its queue selection result is changed before the frame
hits the driver's tx call.
This call sets both the queue and the TID (similar to 802.1d tag), which
makes it into the packet via 802.11e (WMM, QoS).
It is important to the driver that the TID is in sync with the queue
selection, if that is not the case, then pending frame counters can get
messed up.
If you really want to bypass qdisc, make sure that at least
ndo_select_queue is called before passing the frame to the netdev.

- Felix

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox