Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] drivers/net: Call netif_carrier_off at the end of the probe
From: Ben Hutchings @ 2011-02-15 15:58 UTC (permalink / raw)
  To: Francois Romieu; +Cc: Ivan Vecera, netdev, davem, aabdulla, Ben Hutchings
In-Reply-To: <20110215152246.GA11719@electric-eye.fr.zoreil.com>

On Tue, 2011-02-15 at 16:22 +0100, Francois Romieu wrote:
> Ivan Vecera <ivecera@redhat.com> :
> > Without calling of netif_carrier_off at the end of the probe the operstate
> > is unknown when the device is initially opened. By default the carrier is
> > on so when the device is opened and netif_carrier_on is called the link
> > watch event is not fired and operstate remains zero (unknown).
> 
> Stated this way it sounds like a core dev layer issue.

Due to hardware limitations, some network drivers cannot report the
carrier state and they never call netif_carrier_{on,off}().  Therefore
the initial operstate of 'unknown' is correct.

> I am not completely sure after reading some history. Namely:
> - (37e8273cd30592d3a82bcb70cbb1bdc4eaeb6b71 ?)
> - c276e098d3ee33059b4a1c747354226cec58487c 
> - 22604c866889c4b2e12b73cbf1683bda1b72a313
> - b47300168e770b60ab96c8924854c3b0eb4260eb
> 
> I am confused.

Drivers that can report carrier state should do so initially some time
between registering a device and bringing it up (either in the bus probe
function or the ndo_open function).  It generally seems to be safe to
assume that the link is down initially, and then to rely on
notifications from the hardware.  However, that does depend on the
behaviour of the hardware.

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* [PATCH] bnx2x: Support for managing RX indirection table
From: Tom Herbert @ 2011-02-15 16:24 UTC (permalink / raw)
  To: davem, eilong, netdev

Support fetching and retrieving RX indirection table via ethtool.

Signed-off-by: Tom Herbert <therbert@google.com>
---
 drivers/net/bnx2x/bnx2x.h         |    2 +
 drivers/net/bnx2x/bnx2x_ethtool.c |   58 +++++++++++++++++++++++++++++++++++++
 drivers/net/bnx2x/bnx2x_main.c    |   23 +++++++++++----
 3 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index 236d79a..bf16119 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -1076,6 +1076,7 @@ struct bnx2x {
 	int			num_queues;
 	int			disable_tpa;
 	int			int_mode;
+	u32			rx_indir_table[128];
 
 	struct tstorm_eth_mac_filter_config	mac_filters;
 #define BNX2X_ACCEPT_NONE		0x0000
@@ -1799,5 +1800,6 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 BNX2X_EXTERN int load_count[2][3]; /* per path: 0-common, 1-port0, 2-port1 */
 
 extern void bnx2x_set_ethtool_ops(struct net_device *netdev);
+extern void bnx2x_push_indir_table(struct bnx2x *bp);
 
 #endif /* bnx2x.h */
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
index 816fef6..a99fee4 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/bnx2x/bnx2x_ethtool.c
@@ -2134,6 +2134,61 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data)
 	return 0;
 }
 
+static int
+bnx2x_get_rxnfc(struct net_device *dev,
+		struct ethtool_rxnfc *info, void *rules __always_unused)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+
+	switch (info->cmd) {
+	case ETHTOOL_GRXRINGS:
+		info->data = bp->num_queues - NONE_ETH_CONTEXT_USE;
+		return 0;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int bnx2x_get_rxfh_indir(struct net_device *dev,
+				struct ethtool_rxfh_indir *indir)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+	size_t copy_size =
+		min_t(size_t, indir->size, TSTORM_INDIRECTION_TABLE_SIZE);
+
+	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
+		return -ENOENT;
+
+	indir->size = TSTORM_INDIRECTION_TABLE_SIZE;
+	memcpy(indir->ring_index, bp->rx_indir_table,
+	       copy_size * sizeof(bp->rx_indir_table[0]));
+	return 0;
+}
+
+static int bnx2x_set_rxfh_indir(struct net_device *dev,
+				const struct ethtool_rxfh_indir *indir)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+	size_t i;
+
+	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
+		return -ENOENT;
+
+	/* Validate size and indices */
+	if (indir->size != TSTORM_INDIRECTION_TABLE_SIZE)
+		return -EINVAL;
+	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
+		if (indir->ring_index[i] >=
+		    bp->num_queues - NONE_ETH_CONTEXT_USE)
+			return -EINVAL;
+
+	memcpy(bp->rx_indir_table, indir->ring_index,
+	       sizeof(bp->rx_indir_table));
+	bnx2x_push_indir_table(bp);
+	return 0;
+}
+
 static const struct ethtool_ops bnx2x_ethtool_ops = {
 	.get_settings		= bnx2x_get_settings,
 	.set_settings		= bnx2x_set_settings,
@@ -2170,6 +2225,9 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
 	.get_strings		= bnx2x_get_strings,
 	.phys_id		= bnx2x_phys_id,
 	.get_ethtool_stats	= bnx2x_get_ethtool_stats,
+	.get_rxnfc		= bnx2x_get_rxnfc,
+	.get_rxfh_indir		= bnx2x_get_rxfh_indir,
+	.set_rxfh_indir		= bnx2x_set_rxfh_indir,
 };
 
 void bnx2x_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index c238c4d..b1a84d4 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -4254,7 +4254,7 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp)
 		min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1);
 }
 
-static void bnx2x_init_ind_table(struct bnx2x *bp)
+void bnx2x_push_indir_table(struct bnx2x *bp)
 {
 	int func = BP_FUNC(bp);
 	int i;
@@ -4262,13 +4262,24 @@ static void bnx2x_init_ind_table(struct bnx2x *bp)
 	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
 		return;
 
-	DP(NETIF_MSG_IFUP,
-	   "Initializing indirection table  multi_mode %d\n", bp->multi_mode);
 	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
 		REG_WR8(bp, BAR_TSTRORM_INTMEM +
 			TSTORM_INDIRECTION_TABLE_OFFSET(func) + i,
-			bp->fp->cl_id + (i % (bp->num_queues -
-				NONE_ETH_CONTEXT_USE)));
+			bp->fp->cl_id + bp->rx_indir_table[i]);
+}
+
+static void bnx2x_init_indir_table(struct bnx2x *bp)
+{
+	int i;
+
+	BUG_ON(ARRAY_SIZE(bp->rx_indir_table) <
+	    TSTORM_INDIRECTION_TABLE_SIZE);
+
+	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
+		bp->rx_indir_table[i] =
+		    (i % (bp->num_queues - NONE_ETH_CONTEXT_USE));
+
+	bnx2x_push_indir_table(bp);
 }
 
 void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
@@ -4496,7 +4507,7 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
 	bnx2x_init_eq_ring(bp);
 	bnx2x_init_internal(bp, load_code);
 	bnx2x_pf_init(bp);
-	bnx2x_init_ind_table(bp);
+	bnx2x_init_indir_table(bp);
 	bnx2x_stats_init(bp);
 
 	/* At this point, we are ready for interrupts */
-- 
1.7.3.1


^ permalink raw reply related

* Re: [PATCH] bnx2x: Support for managing RX indirection table
From: Eric Dumazet @ 2011-02-15 16:35 UTC (permalink / raw)
  To: Tom Herbert; +Cc: davem, eilong, netdev
In-Reply-To: <alpine.DEB.2.00.1102150815060.27695@pokey.mtv.corp.google.com>

Le mardi 15 février 2011 à 08:24 -0800, Tom Herbert a écrit :
> Support fetching and retrieving RX indirection table via ethtool.
> 
> Signed-off-by: Tom Herbert <therbert@google.com>
> ---
>  drivers/net/bnx2x/bnx2x.h         |    2 +
>  drivers/net/bnx2x/bnx2x_ethtool.c |   58 +++++++++++++++++++++++++++++++++++++
>  drivers/net/bnx2x/bnx2x_main.c    |   23 +++++++++++----
>  3 files changed, 77 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
> index 236d79a..bf16119 100644
> --- a/drivers/net/bnx2x/bnx2x.h
> +++ b/drivers/net/bnx2x/bnx2x.h
> @@ -1076,6 +1076,7 @@ struct bnx2x {
>  	int			num_queues;
>  	int			disable_tpa;
>  	int			int_mode;
> +	u32			rx_indir_table[128];
>  
>  	struct tstorm_eth_mac_filter_config	mac_filters;
>  #define BNX2X_ACCEPT_NONE		0x0000
> @@ -1799,5 +1800,6 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
>  BNX2X_EXTERN int load_count[2][3]; /* per path: 0-common, 1-port0, 2-port1 */
>  
>  extern void bnx2x_set_ethtool_ops(struct net_device *netdev);
> +extern void bnx2x_push_indir_table(struct bnx2x *bp);
>  
>  #endif /* bnx2x.h */
> diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
> index 816fef6..a99fee4 100644
> --- a/drivers/net/bnx2x/bnx2x_ethtool.c
> +++ b/drivers/net/bnx2x/bnx2x_ethtool.c
> @@ -2134,6 +2134,61 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data)
>  	return 0;
>  }
>  
> +static int
> +bnx2x_get_rxnfc(struct net_device *dev,
> +		struct ethtool_rxnfc *info, void *rules __always_unused)
> +{
> +	struct bnx2x *bp = netdev_priv(dev);
> +
> +	switch (info->cmd) {
> +	case ETHTOOL_GRXRINGS:
> +		info->data = bp->num_queues - NONE_ETH_CONTEXT_USE;
> +		return 0;
> +
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +}
> +
> +static int bnx2x_get_rxfh_indir(struct net_device *dev,
> +				struct ethtool_rxfh_indir *indir)
> +{
> +	struct bnx2x *bp = netdev_priv(dev);
> +	size_t copy_size =
> +		min_t(size_t, indir->size, TSTORM_INDIRECTION_TABLE_SIZE);
> +
> +	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
> +		return -ENOENT;
> +
> +	indir->size = TSTORM_INDIRECTION_TABLE_SIZE;
> +	memcpy(indir->ring_index, bp->rx_indir_table,
> +	       copy_size * sizeof(bp->rx_indir_table[0]));
> +	return 0;
> +}
> +
> +static int bnx2x_set_rxfh_indir(struct net_device *dev,
> +				const struct ethtool_rxfh_indir *indir)
> +{
> +	struct bnx2x *bp = netdev_priv(dev);
> +	size_t i;
> +
> +	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
> +		return -ENOENT;
> +
> +	/* Validate size and indices */
> +	if (indir->size != TSTORM_INDIRECTION_TABLE_SIZE)
> +		return -EINVAL;
> +	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
> +		if (indir->ring_index[i] >=
> +		    bp->num_queues - NONE_ETH_CONTEXT_USE)

BNX2X_NUM_ETH_QUEUES(bp) instead of 
(bp->num_queues - NONE_ETH_CONTEXT_USE)

> +			return -EINVAL;
> +
> +	memcpy(bp->rx_indir_table, indir->ring_index,
> +	       sizeof(bp->rx_indir_table));
> +	bnx2x_push_indir_table(bp);
> +	return 0;
> +}
> +
>  static const struct ethtool_ops bnx2x_ethtool_ops = {
>  	.get_settings		= bnx2x_get_settings,
>  	.set_settings		= bnx2x_set_settings,
> @@ -2170,6 +2225,9 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
>  	.get_strings		= bnx2x_get_strings,
>  	.phys_id		= bnx2x_phys_id,
>  	.get_ethtool_stats	= bnx2x_get_ethtool_stats,
> +	.get_rxnfc		= bnx2x_get_rxnfc,
> +	.get_rxfh_indir		= bnx2x_get_rxfh_indir,
> +	.set_rxfh_indir		= bnx2x_set_rxfh_indir,
>  };
>  
>  void bnx2x_set_ethtool_ops(struct net_device *netdev)
> diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
> index c238c4d..b1a84d4 100644
> --- a/drivers/net/bnx2x/bnx2x_main.c
> +++ b/drivers/net/bnx2x/bnx2x_main.c
> @@ -4254,7 +4254,7 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp)
>  		min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1);
>  }
>  
> -static void bnx2x_init_ind_table(struct bnx2x *bp)
> +void bnx2x_push_indir_table(struct bnx2x *bp)
>  {
>  	int func = BP_FUNC(bp);
>  	int i;
> @@ -4262,13 +4262,24 @@ static void bnx2x_init_ind_table(struct bnx2x *bp)
>  	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
>  		return;
>  
> -	DP(NETIF_MSG_IFUP,
> -	   "Initializing indirection table  multi_mode %d\n", bp->multi_mode);
>  	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
>  		REG_WR8(bp, BAR_TSTRORM_INTMEM +
>  			TSTORM_INDIRECTION_TABLE_OFFSET(func) + i,
> -			bp->fp->cl_id + (i % (bp->num_queues -
> -				NONE_ETH_CONTEXT_USE)));

ditto

> +			bp->fp->cl_id + bp->rx_indir_table[i]);
> +}
> +
> +static void bnx2x_init_indir_table(struct bnx2x *bp)
> +{
> +	int i;
> +
> +	BUG_ON(ARRAY_SIZE(bp->rx_indir_table) <
> +	    TSTORM_INDIRECTION_TABLE_SIZE);
> +
> +	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
> +		bp->rx_indir_table[i] =
> +		    (i % (bp->num_queues - NONE_ETH_CONTEXT_USE));

and here

> +
> +	bnx2x_push_indir_table(bp);
>  }
>  
>  void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
> @@ -4496,7 +4507,7 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
>  	bnx2x_init_eq_ring(bp);
>  	bnx2x_init_internal(bp, load_code);
>  	bnx2x_pf_init(bp);
> -	bnx2x_init_ind_table(bp);
> +	bnx2x_init_indir_table(bp);
>  	bnx2x_stats_init(bp);
>  
>  	/* At this point, we are ready for interrupts */



^ permalink raw reply

* Re: [Bugme-new] [Bug 27212] New: Warning kmemcheck: Caught 64-bit read from uninitialized memory in netlink_broadcast_filtered
From: Christoph Lameter @ 2011-02-15 16:40 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: Eric Dumazet, Andrew Morton, netdev, bugzilla-daemon,
	bugme-daemon, casteyde.christian, Changli Gao, Vegard Nossum,
	David Miller, linux-kernel, David Rientjes
In-Reply-To: <AANLkTinKTdeO5mnE38n==aZMz5P1XKKM+kykhoBu0=9k@mail.gmail.com>

On Tue, 15 Feb 2011, Pekka Enberg wrote:

> Looks good to me. Christoph, David, any objections to the patch?

My eyes hurt. Is there some way you could use tabs or spaces instead of
these weird symbols?

If the kmemcheck people are fine with checking data beyond the last byte
of the object then its fine with me.

Acked-by: Christoph Lameter <cl@linux.com>

^ permalink raw reply

* Re: [PATCH] bnx2x: Support for managing RX indirection table
From: Ben Hutchings @ 2011-02-15 16:48 UTC (permalink / raw)
  To: Tom Herbert; +Cc: davem, eilong, netdev
In-Reply-To: <alpine.DEB.2.00.1102150815060.27695@pokey.mtv.corp.google.com>

On Tue, 2011-02-15 at 08:24 -0800, Tom Herbert wrote:
> Support fetching and retrieving RX indirection table via ethtool.
> 
> Signed-off-by: Tom Herbert <therbert@google.com>
> ---
>  drivers/net/bnx2x/bnx2x.h         |    2 +
>  drivers/net/bnx2x/bnx2x_ethtool.c |   58 +++++++++++++++++++++++++++++++++++++
>  drivers/net/bnx2x/bnx2x_main.c    |   23 +++++++++++----
>  3 files changed, 77 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
> index 236d79a..bf16119 100644
> --- a/drivers/net/bnx2x/bnx2x.h
> +++ b/drivers/net/bnx2x/bnx2x.h
> @@ -1076,6 +1076,7 @@ struct bnx2x {
>  	int			num_queues;
>  	int			disable_tpa;
>  	int			int_mode;
> +	u32			rx_indir_table[128];

Shouldn't the dimension be TSTORM_INDIRECTION_TABLE_SIZE?

[...]
> +static int bnx2x_set_rxfh_indir(struct net_device *dev,
> +				const struct ethtool_rxfh_indir *indir)
> +{
> +	struct bnx2x *bp = netdev_priv(dev);
> +	size_t i;
> +
> +	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
> +		return -ENOENT;
[...]

I think the error code for this should be -EOPNOTSUPP.  Similarly in
bnx2x_get_rxfh_indir().

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* Re: [PATCH V10 12/15] ptp: Added a brand new class driver for ptp clocks.
From: Richard Cochran @ 2011-02-15 17:29 UTC (permalink / raw)
  To: John Stultz
  Cc: linux-kernel, linux-api, netdev, Alan Cox, Arnd Bergmann,
	Christoph Lameter, David Miller, Krzysztof Halasa, Peter Zijlstra,
	Rodolfo Giometti, Thomas Gleixner, Benjamin Herrenschmidt,
	H. Peter Anvin, Ingo Molnar, Mike Frysinger, Paul Mackerras,
	Russell King
In-Reply-To: <20110211081524.GA12270@riccoc20.at.omicron.at>

On Fri, Feb 11, 2011 at 09:15:24AM +0100, Richard Cochran wrote:
> On Tue, Feb 01, 2011 at 06:00:31PM -0800, John Stultz wrote:
> > So what is serializing access to the timestamp_event_queue here? I don't
> > see any usage of tsevq_mux by the callers. Am I missing it? It looks
> > like its called from interrupt context, so do you really need a spinlock
> > and not a mutex here?
> 
> The external timestamp FIFO is written only from interrupt context.

Oops, I lied. After reworking the phyter driver, I find that I want to
enqueue time stamps from non-interrupt contexts, too.

So, you are right. This will need a spin lock...

Thanks,

Richard

^ permalink raw reply

* Re: [PATCH] bnx2x: Support for managing RX indirection table
From: Vlad Zolotarov @ 2011-02-15 17:31 UTC (permalink / raw)
  To: Tom Herbert; +Cc: netdev@vger.kernel.org
In-Reply-To: <alpine.DEB.2.00.1102150815060.27695@pokey.mtv.corp.google.com>

On Tuesday 15 February 2011 18:24:40 Tom Herbert wrote:
> Support fetching and retrieving RX indirection table via ethtool.
> 
> Signed-off-by: Tom Herbert <therbert@google.com>
> ---
>  drivers/net/bnx2x/bnx2x.h         |    2 +
>  drivers/net/bnx2x/bnx2x_ethtool.c |   58 +++++++++++++++++++++++++++++++++++++
>  drivers/net/bnx2x/bnx2x_main.c    |   23 +++++++++++----
>  3 files changed, 77 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
> index 236d79a..bf16119 100644
> --- a/drivers/net/bnx2x/bnx2x.h
> +++ b/drivers/net/bnx2x/bnx2x.h
> @@ -1076,6 +1076,7 @@ struct bnx2x {
>  	int			num_queues;
>  	int			disable_tpa;
>  	int			int_mode;
> +	u32			rx_indir_table[128];
>  
>  	struct tstorm_eth_mac_filter_config	mac_filters;
>  #define BNX2X_ACCEPT_NONE		0x0000
> @@ -1799,5 +1800,6 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
>  BNX2X_EXTERN int load_count[2][3]; /* per path: 0-common, 1-port0, 2-port1 */
>  
>  extern void bnx2x_set_ethtool_ops(struct net_device *netdev);
> +extern void bnx2x_push_indir_table(struct bnx2x *bp);

Why to use "extern" for the prototype here and "static" for the implementation 
below? Pls., declare it in .h (without an "extern") and use it as u do in 
bnx2x_ethtool.c and bnx2x_main.c as u do.

thanks,
vlad

>  
>  #endif /* bnx2x.h */
> diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
> index 816fef6..a99fee4 100644
> --- a/drivers/net/bnx2x/bnx2x_ethtool.c
> +++ b/drivers/net/bnx2x/bnx2x_ethtool.c
> @@ -2134,6 +2134,61 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data)
>  	return 0;
>  }
>  
> +static int
> +bnx2x_get_rxnfc(struct net_device *dev,
> +		struct ethtool_rxnfc *info, void *rules __always_unused)
> +{
> +	struct bnx2x *bp = netdev_priv(dev);
> +
> +	switch (info->cmd) {
> +	case ETHTOOL_GRXRINGS:
> +		info->data = bp->num_queues - NONE_ETH_CONTEXT_USE;
> +		return 0;
> +
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +}
> +
> +static int bnx2x_get_rxfh_indir(struct net_device *dev,
> +				struct ethtool_rxfh_indir *indir)
> +{
> +	struct bnx2x *bp = netdev_priv(dev);
> +	size_t copy_size =
> +		min_t(size_t, indir->size, TSTORM_INDIRECTION_TABLE_SIZE);
> +
> +	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
> +		return -ENOENT;
> +
> +	indir->size = TSTORM_INDIRECTION_TABLE_SIZE;
> +	memcpy(indir->ring_index, bp->rx_indir_table,
> +	       copy_size * sizeof(bp->rx_indir_table[0]));
> +	return 0;
> +}
> +
> +static int bnx2x_set_rxfh_indir(struct net_device *dev,
> +				const struct ethtool_rxfh_indir *indir)
> +{
> +	struct bnx2x *bp = netdev_priv(dev);
> +	size_t i;
> +
> +	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
> +		return -ENOENT;
> +
> +	/* Validate size and indices */
> +	if (indir->size != TSTORM_INDIRECTION_TABLE_SIZE)
> +		return -EINVAL;
> +	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
> +		if (indir->ring_index[i] >=
> +		    bp->num_queues - NONE_ETH_CONTEXT_USE)
> +			return -EINVAL;
> +
> +	memcpy(bp->rx_indir_table, indir->ring_index,
> +	       sizeof(bp->rx_indir_table));
> +	bnx2x_push_indir_table(bp);
> +	return 0;
> +}
> +
>  static const struct ethtool_ops bnx2x_ethtool_ops = {
>  	.get_settings		= bnx2x_get_settings,
>  	.set_settings		= bnx2x_set_settings,
> @@ -2170,6 +2225,9 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
>  	.get_strings		= bnx2x_get_strings,
>  	.phys_id		= bnx2x_phys_id,
>  	.get_ethtool_stats	= bnx2x_get_ethtool_stats,
> +	.get_rxnfc		= bnx2x_get_rxnfc,
> +	.get_rxfh_indir		= bnx2x_get_rxfh_indir,
> +	.set_rxfh_indir		= bnx2x_set_rxfh_indir,
>  };
>  
>  void bnx2x_set_ethtool_ops(struct net_device *netdev)
> diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
> index c238c4d..b1a84d4 100644
> --- a/drivers/net/bnx2x/bnx2x_main.c
> +++ b/drivers/net/bnx2x/bnx2x_main.c
> @@ -4254,7 +4254,7 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp)
>  		min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1);
>  }
>  
> -static void bnx2x_init_ind_table(struct bnx2x *bp)
> +void bnx2x_push_indir_table(struct bnx2x *bp)
>  {
>  	int func = BP_FUNC(bp);
>  	int i;
> @@ -4262,13 +4262,24 @@ static void bnx2x_init_ind_table(struct bnx2x *bp)
>  	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
>  		return;
>  
> -	DP(NETIF_MSG_IFUP,
> -	   "Initializing indirection table  multi_mode %d\n", bp->multi_mode);
>  	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
>  		REG_WR8(bp, BAR_TSTRORM_INTMEM +
>  			TSTORM_INDIRECTION_TABLE_OFFSET(func) + i,
> -			bp->fp->cl_id + (i % (bp->num_queues -
> -				NONE_ETH_CONTEXT_USE)));
> +			bp->fp->cl_id + bp->rx_indir_table[i]);
> +}
> +
> +static void bnx2x_init_indir_table(struct bnx2x *bp)
> +{
> +	int i;
> +
> +	BUG_ON(ARRAY_SIZE(bp->rx_indir_table) <
> +	    TSTORM_INDIRECTION_TABLE_SIZE);
> +
> +	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
> +		bp->rx_indir_table[i] =
> +		    (i % (bp->num_queues - NONE_ETH_CONTEXT_USE));
> +
> +	bnx2x_push_indir_table(bp);
>  }
>  
>  void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
> @@ -4496,7 +4507,7 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
>  	bnx2x_init_eq_ring(bp);
>  	bnx2x_init_internal(bp, load_code);
>  	bnx2x_pf_init(bp);
> -	bnx2x_init_ind_table(bp);
> +	bnx2x_init_indir_table(bp);
>  	bnx2x_stats_init(bp);
>  
>  	/* At this point, we are ready for interrupts */
> 


^ permalink raw reply

* Re: [PATCH] bnx2x: Support for managing RX indirection table
From: Vlad Zolotarov @ 2011-02-15 17:39 UTC (permalink / raw)
  To: Tom Herbert; +Cc: netdev@vger.kernel.org
In-Reply-To: <alpine.DEB.2.00.1102150815060.27695@pokey.mtv.corp.google.com>


>  void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
> @@ -4496,7 +4507,7 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
>  	bnx2x_init_eq_ring(bp);
>  	bnx2x_init_internal(bp, load_code);
>  	bnx2x_pf_init(bp);
> -	bnx2x_init_ind_table(bp);
> +	bnx2x_init_indir_table(bp);


Tom, one more thing: could u, pls., cancel this rename? ;)

thanks,
vlad


^ permalink raw reply

* Re: [PATCH] drivers/net: Call netif_carrier_off at the end of the probe
From: Ivan Vecera @ 2011-02-15 18:01 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev, davem, aabdulla, Ben Hutchings, Francois Romieu
In-Reply-To: <1297785532.2584.10.camel@bwh-desktop>

----- Original Message -----
> On Tue, 2011-02-15 at 16:22 +0100, Francois Romieu wrote:
> > Stated this way it sounds like a core dev layer issue.
> 
> ...
> > I am not completely sure after reading some history. Namely:
> > - (37e8273cd30592d3a82bcb70cbb1bdc4eaeb6b71 ?)
> > - c276e098d3ee33059b4a1c747354226cec58487c
> > - 22604c866889c4b2e12b73cbf1683bda1b72a313
> > - b47300168e770b60ab96c8924854c3b0eb4260eb
> >
> > I am confused.
> 
> Drivers that can report carrier state should do so initially some time
> between registering a device and bringing it up (either in the bus
> probe
> function or the ndo_open function). It generally seems to be safe to
> assume that the link is down initially, and then to rely on
> notifications from the hardware. However, that does depend on the
> behaviour of the hardware.
> 
Yes,that's true... forcedeth and r8169 are the drivers that detect link
state when device is opened and call netif_carrier_on(off) appropriately.

Ivan

^ permalink raw reply

* Re: [PATCH] net: provide capability and group sets via SCM
From: Casey Schaufler @ 2011-02-15 18:09 UTC (permalink / raw)
  To: David Miller
  Cc: linux-kernel, netdev, ext-jarkko.2.sakkinen, Janne.Karhunen,
	elena.reshetova, Casey Schaufler
In-Reply-To: <20110214.174919.48492611.davem@davemloft.net>

On 2/14/2011 5:49 PM, David Miller wrote:
> From: Casey Schaufler <casey@schaufler-ca.com>
> Date: Tue, 08 Feb 2011 14:28:27 -0800
>
>> Subject: [PATCH] net: provide group lists and capability set via CMSG
>>
>> Provide the namespace converted group list of the peer
>> process using the SCM mechanism. Provide the capability
>> set of the peer process. The capability set is not
>> namespace converted on the assumption that there is no
>> such conversion available or required.
>>
>> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> You can't just hit the asm-generic header, you have to also hit
> all of the architectures that don't use the asm-generic header,
> including sparc, powerpc, mips, s390, arm, alpha, cris, frv, h8300,
> ia64, m32r, m68k, m68knommu, mn10300, parisc, and xtensa.

OK, I was afraid of that. Updated version will include those.
Thank you.


> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>
>


^ permalink raw reply

* Re: mac addresses of local interfaces do not obey setageing 0
From: Stephen Hemminger @ 2011-02-15 18:25 UTC (permalink / raw)
  To: Veaceslav Falico; +Cc: netdev, bridge
In-Reply-To: <20110209181752.GA2042@darkmag.usersys.redhat.com>

On Wed, 9 Feb 2011 19:17:52 +0100
Veaceslav Falico <vfalico@redhat.com> wrote:

> Hello,
> 
> I have a host and a VM inside this host bridged. I've set ageing_time and
> forward_delay to 0 and trying to capture all the traffic that goes through that
> bridge from my VM, but it fails to capture the traffic that has dst ether
> address the same as the hosts address (i.e. I can't capture the traffic to the
> host).
> 
> From the code, I see that br->ageing_time doesn't really work with local mac
> addresses - has_expired() function never says that a local interface mac address
> is expired, because it verifies if fdb->is_static is set and returns right away.
> 
> Is this the desired behaviour? If so, is there a way to capture packets with
> destination to a local interface from another interface?
> 
> I've also done a small patch and it seems to fix the situation, but I am not
> sure if it's the right way to do it.
> 
> 
> Regards,
> Veaceslav
> 
> ---
>  net/bridge/br_fdb.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
> index 88485cc..3d380c2 100644
> --- a/net/bridge/br_fdb.c
> +++ b/net/bridge/br_fdb.c
> @@ -61,8 +61,8 @@ static inline unsigned long hold_time(const struct net_bridge *br)
>  static inline int has_expired(const struct net_bridge *br,
>  				  const struct net_bridge_fdb_entry *fdb)
>  {
> -	return !fdb->is_static &&
> -		time_before_eq(fdb->ageing_timer + hold_time(br), jiffies);
> +	return (br->ageing_time == 0) || (!fdb->is_static &&
> +		time_before_eq(fdb->ageing_timer + hold_time(br), jiffies));
>  }
>  

No.
Local addresses should never age.

The proper way to capture packet is to us AF_PACKET or tc actions.
-- 

^ permalink raw reply

* Re: [PATCH 02/14] net/fec: release mem_region requested in probe in error path and remove
From: David Miller @ 2011-02-15 18:31 UTC (permalink / raw)
  To: u.kleine-koenig; +Cc: netdev, shawn.guo, kernel
In-Reply-To: <20110215085305.GL13279@pengutronix.de>

From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Date: Tue, 15 Feb 2011 09:53:05 +0100

> On Mon, Feb 14, 2011 at 11:05:49AM -0800, David Miller wrote:
>> These merge commits look ugly and Linus wants them minimized.
> Hmm, right, I don't get why this looks uglier for Linus than a merge of
> a tree that bases on something you already have.  I guess you're too
> annoyed by now to explain why you think it does.

What's so hard to understand about the fact that when I pull from
someone I do not want any commits unrelated to the work that person
is sending me?

>> Either you follow the rules and my expectations, which is that when you
>> give me a GIT tree to pull from it's based upon one of my trees, or
>> I don't pull from you.
> So I rebased my tree on something older.  It now starts at
> 
> 	c69b909 (pch_can: fix module reload issue with MSI)
> 
> which is already in net-next/master.

You need to send a new pull request so that it gets properly tracked
in patchwork.

^ permalink raw reply

* Re: [PATCH] arp_notify: unconditionally send gratuitous ARP for NETDEV_NOTIFY_PEERS.
From: David Miller @ 2011-02-15 18:51 UTC (permalink / raw)
  To: Ian.Campbell; +Cc: netdev
In-Reply-To: <1297761225.21980.3663.camel@zakaz.uk.xensource.com>

From: Ian Campbell <Ian.Campbell@eu.citrix.com>
Date: Tue, 15 Feb 2011 09:13:45 +0000

> On Tue, 2011-02-15 at 01:46 +0000, David Miller wrote:
>> From: Ian Campbell <ian.campbell@citrix.com>
>> Date: Fri, 11 Feb 2011 17:44:16 +0000
>> 
>> > NETDEV_NOTIFY_PEER is an explicit request by the driver to send a link
>> > notification while NETDEV_UP/NETDEV_CHANGEADDR generate link
>> > notifications as a sort of side effect.
 ...
> I nearly forgot -- the NETDEV_NOTIFY_PEER stuff was tagged for
> stable/longterm backport (it appeared in 2.6.32.19 or so). I think this
> change should likewise go back, what do you think?

Sure, I've queued it up for -stable.

^ permalink raw reply

* Re: [PATCH 02/14] net/fec: release mem_region requested in probe in error path and remove
From: Uwe Kleine-König @ 2011-02-15 20:00 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, shawn.guo, kernel
In-Reply-To: <20110215.103159.193730541.davem@davemloft.net>

On Tue, Feb 15, 2011 at 10:31:59AM -0800, David Miller wrote:
> From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> Date: Tue, 15 Feb 2011 09:53:05 +0100
> 
> > On Mon, Feb 14, 2011 at 11:05:49AM -0800, David Miller wrote:
> >> These merge commits look ugly and Linus wants them minimized.
> > Hmm, right, I don't get why this looks uglier for Linus than a merge of
> > a tree that bases on something you already have.  I guess you're too
> > annoyed by now to explain why you think it does.
> 
> What's so hard to understand about the fact that when I pull from
> someone I do not want any commits unrelated to the work that person
> is sending me?
Perfectly fine, I can live with this explanation.  Next time say that at
once :-)
 
> >> Either you follow the rules and my expectations, which is that when you
> >> give me a GIT tree to pull from it's based upon one of my trees, or
> >> I don't pull from you.
> > So I rebased my tree on something older.  It now starts at
> > 
> > 	c69b909 (pch_can: fix module reload issue with MSI)
> > 
> > which is already in net-next/master.
> 
> You need to send a new pull request so that it gets properly tracked
> in patchwork.
Oh, I didn't know that patchwork tracks pull requests, too:

The following changes since commit c69b90920a36b88ab0d649963d81355d865eeb05:

  pch_can: fix module reload issue with MSI (2011-02-08 16:37:20 -0800)

are available in the git repository at:
  git://git.pengutronix.de/git/ukl/linux-2.6.git fec

Uwe Kleine-König (14):
      net/fec: no need to cast arguments for memcpy
      net/fec: release mem_region requested in probe in error path and remove
      net/fec: don't free an irq that failed to be requested
      net/fec: no need to check for validity of ndev in suspend and resume
      net/fec: no need to memzero private data
      net/fec: put the ioremap cookie immediately into a void __iomem pointer
      net/fec: consolidate all i.MX options to CONFIG_ARM
      net/fec: add phy_stop to fec_enet_close
      net/fec: consistenly name struct net_device pointers "ndev"
      net/fec: some whitespace cleanup
      net/fec: reorder functions a bit allows removing forward declarations
      net/fec: provide device for dma functions and matching sizes for map and unmap
      net/fec: postpone unsetting driver data until the hardware is stopped
      net/fec: enable flow control and length check on enet-mac

 drivers/net/Kconfig |    3 +-
 drivers/net/fec.c   |  650 ++++++++++++++++++++++++++-------------------------
 2 files changed, 328 insertions(+), 325 deletions(-)

Thanks
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply

* Re: potential null pointer dereference in drivers/isdn/hisax/isdnl2.c
From: Milton Miller @ 2011-02-15 20:09 UTC (permalink / raw)
  To: David Miller; +Cc: linux-kernel, netdev, tj, isdn, jj
In-Reply-To: <20110213.165309.123985803.davem@davemloft.net>

On Mon, 14 Feb 2011 00:53:09 -0000, Dave Miler wrote:
> From: Jesper Juhl <jj@chaosbits.net>
> 
> > In drivers/isdn/hisax/isdnl2.c:l2_pull_iqueue() we have this:
> > 
> > 	...
> > 		skb = alloc_skb(oskb->len + i, GFP_ATOMIC);
> > 		memcpy(skb_put(skb, i), header, i);
> > 	...
> > 
> > If alloc_skb() fails and returns NULL then the second line will cause a 
> > NULL pointer dereference - skb_put() gives the pointer to 
> > skb_tail_pointer() which dereferences it.
> > 
> > I'm not quite sure how this should be dealt with, so I'll just report it 
> > rather than submit a patch. Happy bug fixing :-)
> 
> Thanks Jesper, I'll fix this like so:
> 
> --------------------
> hisax: Fix unchecked alloc_skb() return.
> 
> Jesper Juhl noticed that l2_pull_iqueue() does not
> check to see if alloc_skb() fails.
> 
> Fix this by first trying to reallocate the headroom
> if necessary, rather than later after we've made hard
> to undo state changes.
> 
> Reported-by: Jesper Juhl <jj@chaosbits.net>
> Signed-off-by: David S. Miller <davem@davemloft.net>
> 
> ---
> drivers/isdn/hisax/isdnl2.c |   35 ++++++++++++++++++++---------------
>  1 files changed, 20 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
> index 0858791..98ac835 100644
> --- a/drivers/isdn/hisax/isdnl2.c
> +++ b/drivers/isdn/hisax/isdnl2.c
> @@ -1243,14 +1243,21 @@ l2_st7_tout_203(struct FsmInst *fi, int event, void *arg)
>  	st->l2.rc = 0;
>  }
>  
> +static int l2_hdr_space_needed(struct Layer2 *l2)
> +{
> +	int len = test_bit(FLG_LAPD, &l2->flag) ? 2 : 1;
> +
> +	return len + (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1);
> +}
> +

That struck me as an funny way to write 2 * len, so I finally looked
at the code.  I think one of those should be FLG_MOD128, but then
at that point why not use the existing l2headersize(l2, ui) with
ui = 0?

I see this is in linux-next of Feb 15, 2011.

milton

^ permalink raw reply

* pull request: sfc-next-2.6 2011-02-15
From: Ben Hutchings @ 2011-02-15 20:12 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, sf-linux-drivers, Tom Herbert, John Fastabend

The following changes since commit 263fb5b1bf9265d0e4ce59ff6ea92f478b5b61ea:

  Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 (2011-02-08 17:19:01 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next-2.6.git for-davem

Multiqueue TX priority support for sfc, and some necessary fixes
elsewhere.

Ben.

Ben Hutchings (5):
      sch_mqprio: Always set num_tc to 0 in mqprio_destroy()
      net: Adjust TX queue kobjects if number of queues changes during unregister
      sfc: Move TX queue core queue mapping into tx.c
      sfc: Distinguish queue lookup from test for queue existence
      sfc: Add TX queues for high-priority traffic

 drivers/net/sfc/efx.c        |   31 ++++----------
 drivers/net/sfc/efx.h        |    2 +
 drivers/net/sfc/ethtool.c    |    6 +-
 drivers/net/sfc/net_driver.h |   64 +++++++++++++++++++++++-------
 drivers/net/sfc/nic.c        |   51 ++++++++++++++++++------
 drivers/net/sfc/regs.h       |    6 +++
 drivers/net/sfc/selftest.c   |    2 +-
 drivers/net/sfc/tx.c         |   90 ++++++++++++++++++++++++++++++++++++++++-
 net/core/dev.c               |    3 +-
 net/sched/sch_mqprio.c       |   14 +++---
 10 files changed, 204 insertions(+), 65 deletions(-)

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* [PATCH net-next-2.6 1/5] sch_mqprio: Always set num_tc to 0 in mqprio_destroy()
From: Ben Hutchings @ 2011-02-15 20:14 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers, Tom Herbert, John Fastabend
In-Reply-To: <1297800733.2584.15.camel@bwh-desktop>

All the cleanup code in mqprio_destroy() is currently conditional on
priv->qdiscs being non-null, but that condition should only apply to
the per-queue qdisc cleanup.  We should always set the number of
traffic classes back to 0 here.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 net/sched/sch_mqprio.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
index effd4ee..ace37f9 100644
--- a/net/sched/sch_mqprio.c
+++ b/net/sched/sch_mqprio.c
@@ -29,18 +29,18 @@ static void mqprio_destroy(struct Qdisc *sch)
 	struct mqprio_sched *priv = qdisc_priv(sch);
 	unsigned int ntx;
 
-	if (!priv->qdiscs)
-		return;
-
-	for (ntx = 0; ntx < dev->num_tx_queues && priv->qdiscs[ntx]; ntx++)
-		qdisc_destroy(priv->qdiscs[ntx]);
+	if (priv->qdiscs) {
+		for (ntx = 0;
+		     ntx < dev->num_tx_queues && priv->qdiscs[ntx];
+		     ntx++)
+			qdisc_destroy(priv->qdiscs[ntx]);
+		kfree(priv->qdiscs);
+	}
 
 	if (priv->hw_owned && dev->netdev_ops->ndo_setup_tc)
 		dev->netdev_ops->ndo_setup_tc(dev, 0);
 	else
 		netdev_set_num_tc(dev, 0);
-
-	kfree(priv->qdiscs);
 }
 
 static int mqprio_parse_opt(struct net_device *dev, struct tc_mqprio_qopt *qopt)
-- 
1.7.3.4



-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply related

* [PATCH net-next-2.6 2/5] net: Adjust TX queue kobjects if number of queues changes during unregister
From: Ben Hutchings @ 2011-02-15 20:14 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers, Tom Herbert, John Fastabend
In-Reply-To: <1297800733.2584.15.camel@bwh-desktop>

If the root qdisc for a net device is mqprio, and the driver's
ndo_setup_tc() operation dynamically adds and remvoes TX queues,
netif_set_real_num_tx_queues() will be called during device
unregistration to remove the extra TX queues when the qdisc is
destroyed.  Currently this causes the corresponding kobjects
to be leaked, and the device's reference count never drops to 0.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 net/core/dev.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 6392ea0..30c71f9 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1648,7 +1648,8 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
 	if (txq < 1 || txq > dev->num_tx_queues)
 		return -EINVAL;
 
-	if (dev->reg_state == NETREG_REGISTERED) {
+	if (dev->reg_state == NETREG_REGISTERED ||
+	    dev->reg_state == NETREG_UNREGISTERING) {
 		ASSERT_RTNL();
 
 		rc = netdev_queue_update_kobjects(dev, dev->real_num_tx_queues,
-- 
1.7.3.4



-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply related

* [PATCH net-next-2.6 3/5] sfc: Move TX queue core queue mapping into tx.c
From: Ben Hutchings @ 2011-02-15 20:14 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers, Tom Herbert
In-Reply-To: <1297800733.2584.15.camel@bwh-desktop>

efx_hard_start_xmit() needs to implement a mapping which is the
inverse of tx_queue::core_txq.  Move the initialisation of
tx_queue::core_txq next to efx_hard_start_xmit() to make the
connection more obvious.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/sfc/efx.c |    6 ++----
 drivers/net/sfc/efx.h |    1 +
 drivers/net/sfc/tx.c  |    7 +++++++
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 002bac7..c559bc3 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1910,10 +1910,8 @@ static int efx_register_netdev(struct efx_nic *efx)
 
 	efx_for_each_channel(channel, efx) {
 		struct efx_tx_queue *tx_queue;
-		efx_for_each_channel_tx_queue(tx_queue, channel) {
-			tx_queue->core_txq = netdev_get_tx_queue(
-				efx->net_dev, tx_queue->queue / EFX_TXQ_TYPES);
-		}
+		efx_for_each_channel_tx_queue(tx_queue, channel)
+			efx_init_tx_queue_core_txq(tx_queue);
 	}
 
 	/* Always start with carrier off; PHY events will detect the link */
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index d43a7e5..1162070 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -29,6 +29,7 @@
 extern int efx_probe_tx_queue(struct efx_tx_queue *tx_queue);
 extern void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
 extern void efx_init_tx_queue(struct efx_tx_queue *tx_queue);
+extern void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue);
 extern void efx_fini_tx_queue(struct efx_tx_queue *tx_queue);
 extern void efx_release_tx_buffers(struct efx_tx_queue *tx_queue);
 extern netdev_tx_t
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
index 2f5e9da..7e463fb 100644
--- a/drivers/net/sfc/tx.c
+++ b/drivers/net/sfc/tx.c
@@ -347,6 +347,13 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
 	return efx_enqueue_skb(tx_queue, skb);
 }
 
+void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue)
+{
+	/* Must be inverse of queue lookup in efx_hard_start_xmit() */
+	tx_queue->core_txq = netdev_get_tx_queue(
+		tx_queue->efx->net_dev, tx_queue->queue / EFX_TXQ_TYPES);
+}
+
 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
 {
 	unsigned fill_level;
-- 
1.7.3.4



-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply related

* [PATCH net-next-2.6 4/5] sfc: Distinguish queue lookup from test for queue existence
From: Ben Hutchings @ 2011-02-15 20:14 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers, Tom Herbert
In-Reply-To: <1297800733.2584.15.camel@bwh-desktop>

efx_channel_get_{rx,tx}_queue() currently return NULL if the channel
isn't used for traffic in that direction.  In most cases this is a
bug, but some callers rely on it as an existence test.

Add existence test functions efx_channel_has_{rx_queue,tx_queues}()
and use them as appropriate.

Change efx_channel_get_{rx,tx}_queue() to assert that the requested
queue exists.

Remove now-redundant initialisation from efx_set_channels().

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/sfc/efx.c        |   17 ++---------------
 drivers/net/sfc/ethtool.c    |    6 +++---
 drivers/net/sfc/net_driver.h |   39 ++++++++++++++++++++++++++++-----------
 3 files changed, 33 insertions(+), 29 deletions(-)

diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index c559bc3..6189d30 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1271,21 +1271,8 @@ static void efx_remove_interrupts(struct efx_nic *efx)
 
 static void efx_set_channels(struct efx_nic *efx)
 {
-	struct efx_channel *channel;
-	struct efx_tx_queue *tx_queue;
-
 	efx->tx_channel_offset =
 		separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
-
-	/* Channel pointers were set in efx_init_struct() but we now
-	 * need to clear them for TX queues in any RX-only channels. */
-	efx_for_each_channel(channel, efx) {
-		if (channel->channel - efx->tx_channel_offset >=
-		    efx->n_tx_channels) {
-			efx_for_each_channel_tx_queue(tx_queue, channel)
-				tx_queue->channel = NULL;
-		}
-	}
 }
 
 static int efx_probe_nic(struct efx_nic *efx)
@@ -1531,9 +1518,9 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
 	efx->irq_rx_adaptive = rx_adaptive;
 	efx->irq_rx_moderation = rx_ticks;
 	efx_for_each_channel(channel, efx) {
-		if (efx_channel_get_rx_queue(channel))
+		if (efx_channel_has_rx_queue(channel))
 			channel->irq_moderation = rx_ticks;
-		else if (efx_channel_get_tx_queue(channel, 0))
+		else if (efx_channel_has_tx_queues(channel))
 			channel->irq_moderation = tx_ticks;
 	}
 }
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index 713969a..272cfe7 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -631,7 +631,7 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev,
 	/* Find lowest IRQ moderation across all used TX queues */
 	coalesce->tx_coalesce_usecs_irq = ~((u32) 0);
 	efx_for_each_channel(channel, efx) {
-		if (!efx_channel_get_tx_queue(channel, 0))
+		if (!efx_channel_has_tx_queues(channel))
 			continue;
 		if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) {
 			if (channel->channel < efx->n_rx_channels)
@@ -676,8 +676,8 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
 
 	/* If the channel is shared only allow RX parameters to be set */
 	efx_for_each_channel(channel, efx) {
-		if (efx_channel_get_rx_queue(channel) &&
-		    efx_channel_get_tx_queue(channel, 0) &&
+		if (efx_channel_has_rx_queue(channel) &&
+		    efx_channel_has_tx_queues(channel) &&
 		    tx_usecs) {
 			netif_err(efx, drv, efx->net_dev, "Channel is shared. "
 				  "Only RX coalescing may be set\n");
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index c652702..77b7ce4 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -938,19 +938,28 @@ efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
 	return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type];
 }
 
+static inline bool efx_channel_has_tx_queues(struct efx_channel *channel)
+{
+	return channel->channel - channel->efx->tx_channel_offset <
+		channel->efx->n_tx_channels;
+}
+
 static inline struct efx_tx_queue *
 efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type)
 {
-	struct efx_tx_queue *tx_queue = channel->tx_queue;
-	EFX_BUG_ON_PARANOID(type >= EFX_TXQ_TYPES);
-	return tx_queue->channel ? tx_queue + type : NULL;
+	EFX_BUG_ON_PARANOID(!efx_channel_has_tx_queues(channel) ||
+			    type >= EFX_TXQ_TYPES);
+	return &channel->tx_queue[type];
 }
 
 /* Iterate over all TX queues belonging to a channel */
 #define efx_for_each_channel_tx_queue(_tx_queue, _channel)		\
-	for (_tx_queue = efx_channel_get_tx_queue(channel, 0);		\
-	     _tx_queue && _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \
-	     _tx_queue++)
+	if (!efx_channel_has_tx_queues(_channel))			\
+		;							\
+	else								\
+		for (_tx_queue = (_channel)->tx_queue;			\
+		     _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES;	\
+		     _tx_queue++)
 
 static inline struct efx_rx_queue *
 efx_get_rx_queue(struct efx_nic *efx, unsigned index)
@@ -959,18 +968,26 @@ efx_get_rx_queue(struct efx_nic *efx, unsigned index)
 	return &efx->channel[index]->rx_queue;
 }
 
+static inline bool efx_channel_has_rx_queue(struct efx_channel *channel)
+{
+	return channel->channel < channel->efx->n_rx_channels;
+}
+
 static inline struct efx_rx_queue *
 efx_channel_get_rx_queue(struct efx_channel *channel)
 {
-	return channel->channel < channel->efx->n_rx_channels ?
-		&channel->rx_queue : NULL;
+	EFX_BUG_ON_PARANOID(!efx_channel_has_rx_queue(channel));
+	return &channel->rx_queue;
 }
 
 /* Iterate over all RX queues belonging to a channel */
 #define efx_for_each_channel_rx_queue(_rx_queue, _channel)		\
-	for (_rx_queue = efx_channel_get_rx_queue(channel);		\
-	     _rx_queue;							\
-	     _rx_queue = NULL)
+	if (!efx_channel_has_rx_queue(_channel))			\
+		;							\
+	else								\
+		for (_rx_queue = &(_channel)->rx_queue;			\
+		     _rx_queue;						\
+		     _rx_queue = NULL)
 
 static inline struct efx_channel *
 efx_rx_queue_channel(struct efx_rx_queue *rx_queue)
-- 
1.7.3.4



-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply related

* [PATCH net-next-2.6 5/5] sfc: Add TX queues for high-priority traffic
From: Ben Hutchings @ 2011-02-15 20:15 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers, Tom Herbert
In-Reply-To: <1297800733.2584.15.camel@bwh-desktop>

Implement the ndo_setup_tc() operation with 2 traffic classes.

Current Solarstorm controllers do not implement TX queue priority, but
they do allow queues to be 'paced' with an enforced delay between
packets.  Paced and unpaced queues are scheduled in round-robin within
two separate hardware bins (paced queues with a large delay may be
placed into a third bin temporarily, but we won't use that).  If there
are queues in both bins, the TX scheduler will alternate between them.

If we make high-priority queues unpaced and best-effort queues paced,
and high-priority queues are mostly empty, a single high-priority queue
can then instantly take 50% of the packet rate regardless of how many
of the best-effort queues have descriptors outstanding.

We do not actually want an enforced delay between packets on best-
effort queues, so we set the pace value to a reserved value that
actually results in a delay of 0.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/sfc/efx.c        |    8 ++-
 drivers/net/sfc/efx.h        |    1 +
 drivers/net/sfc/net_driver.h |   29 +++++++++++---
 drivers/net/sfc/nic.c        |   51 ++++++++++++++++++------
 drivers/net/sfc/regs.h       |    6 +++
 drivers/net/sfc/selftest.c   |    2 +-
 drivers/net/sfc/tx.c         |   87 +++++++++++++++++++++++++++++++++++++++--
 7 files changed, 156 insertions(+), 28 deletions(-)

diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 6189d30..d4e0425 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -673,7 +673,7 @@ static void efx_fini_channels(struct efx_nic *efx)
 
 		efx_for_each_channel_rx_queue(rx_queue, channel)
 			efx_fini_rx_queue(rx_queue);
-		efx_for_each_channel_tx_queue(tx_queue, channel)
+		efx_for_each_possible_channel_tx_queue(tx_queue, channel)
 			efx_fini_tx_queue(tx_queue);
 		efx_fini_eventq(channel);
 	}
@@ -689,7 +689,7 @@ static void efx_remove_channel(struct efx_channel *channel)
 
 	efx_for_each_channel_rx_queue(rx_queue, channel)
 		efx_remove_rx_queue(rx_queue);
-	efx_for_each_channel_tx_queue(tx_queue, channel)
+	efx_for_each_possible_channel_tx_queue(tx_queue, channel)
 		efx_remove_tx_queue(tx_queue);
 	efx_remove_eventq(channel);
 }
@@ -1836,6 +1836,7 @@ static const struct net_device_ops efx_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller = efx_netpoll,
 #endif
+	.ndo_setup_tc		= efx_setup_tc,
 };
 
 static void efx_update_name(struct efx_nic *efx)
@@ -2386,7 +2387,8 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
 	int i, rc;
 
 	/* Allocate and initialise a struct net_device and struct efx_nic */
-	net_dev = alloc_etherdev_mq(sizeof(*efx), EFX_MAX_CORE_TX_QUEUES);
+	net_dev = alloc_etherdev_mqs(sizeof(*efx), EFX_MAX_CORE_TX_QUEUES,
+				     EFX_MAX_RX_QUEUES);
 	if (!net_dev)
 		return -ENOMEM;
 	net_dev->features |= (type->offload_features | NETIF_F_SG |
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index 1162070..0cb198a 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -37,6 +37,7 @@ efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev);
 extern netdev_tx_t
 efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
 extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
+extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc);
 
 /* RX */
 extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 77b7ce4..96e22ad 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -63,10 +63,12 @@
 /* Checksum generation is a per-queue option in hardware, so each
  * queue visible to the networking core is backed by two hardware TX
  * queues. */
-#define EFX_MAX_CORE_TX_QUEUES	EFX_MAX_CHANNELS
-#define EFX_TXQ_TYPE_OFFLOAD	1
-#define EFX_TXQ_TYPES		2
-#define EFX_MAX_TX_QUEUES	(EFX_TXQ_TYPES * EFX_MAX_CORE_TX_QUEUES)
+#define EFX_MAX_TX_TC		2
+#define EFX_MAX_CORE_TX_QUEUES	(EFX_MAX_TX_TC * EFX_MAX_CHANNELS)
+#define EFX_TXQ_TYPE_OFFLOAD	1	/* flag */
+#define EFX_TXQ_TYPE_HIGHPRI	2	/* flag */
+#define EFX_TXQ_TYPES		4
+#define EFX_MAX_TX_QUEUES	(EFX_TXQ_TYPES * EFX_MAX_CHANNELS)
 
 /**
  * struct efx_special_buffer - An Efx special buffer
@@ -140,6 +142,7 @@ struct efx_tx_buffer {
  * @buffer: The software buffer ring
  * @txd: The hardware descriptor ring
  * @ptr_mask: The size of the ring minus 1.
+ * @initialised: Has hardware queue been initialised?
  * @flushed: Used when handling queue flushing
  * @read_count: Current read pointer.
  *	This is the number of buffers that have been removed from both rings.
@@ -182,6 +185,7 @@ struct efx_tx_queue {
 	struct efx_tx_buffer *buffer;
 	struct efx_special_buffer txd;
 	unsigned int ptr_mask;
+	bool initialised;
 	enum efx_flush_state flushed;
 
 	/* Members used mainly on the completion path */
@@ -377,7 +381,7 @@ struct efx_channel {
 	bool rx_pkt_csummed;
 
 	struct efx_rx_queue rx_queue;
-	struct efx_tx_queue tx_queue[2];
+	struct efx_tx_queue tx_queue[EFX_TXQ_TYPES];
 };
 
 enum efx_led_mode {
@@ -952,15 +956,28 @@ efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type)
 	return &channel->tx_queue[type];
 }
 
+static inline bool efx_tx_queue_used(struct efx_tx_queue *tx_queue)
+{
+	return !(tx_queue->efx->net_dev->num_tc < 2 &&
+		 tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI);
+}
+
 /* Iterate over all TX queues belonging to a channel */
 #define efx_for_each_channel_tx_queue(_tx_queue, _channel)		\
 	if (!efx_channel_has_tx_queues(_channel))			\
 		;							\
 	else								\
 		for (_tx_queue = (_channel)->tx_queue;			\
-		     _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES;	\
+		     _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES && \
+			     efx_tx_queue_used(_tx_queue);		\
 		     _tx_queue++)
 
+/* Iterate over all possible TX queues belonging to a channel */
+#define efx_for_each_possible_channel_tx_queue(_tx_queue, _channel)	\
+	for (_tx_queue = (_channel)->tx_queue;				\
+	     _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES;		\
+	     _tx_queue++)
+
 static inline struct efx_rx_queue *
 efx_get_rx_queue(struct efx_nic *efx, unsigned index)
 {
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index da38659..1d0b8b6 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -445,8 +445,8 @@ int efx_nic_probe_tx(struct efx_tx_queue *tx_queue)
 
 void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
 {
-	efx_oword_t tx_desc_ptr;
 	struct efx_nic *efx = tx_queue->efx;
+	efx_oword_t reg;
 
 	tx_queue->flushed = FLUSH_NONE;
 
@@ -454,7 +454,7 @@ void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
 	efx_init_special_buffer(efx, &tx_queue->txd);
 
 	/* Push TX descriptor ring to card */
-	EFX_POPULATE_OWORD_10(tx_desc_ptr,
+	EFX_POPULATE_OWORD_10(reg,
 			      FRF_AZ_TX_DESCQ_EN, 1,
 			      FRF_AZ_TX_ISCSI_DDIG_EN, 0,
 			      FRF_AZ_TX_ISCSI_HDIG_EN, 0,
@@ -470,17 +470,15 @@ void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
 
 	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
 		int csum = tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD;
-		EFX_SET_OWORD_FIELD(tx_desc_ptr, FRF_BZ_TX_IP_CHKSM_DIS, !csum);
-		EFX_SET_OWORD_FIELD(tx_desc_ptr, FRF_BZ_TX_TCP_CHKSM_DIS,
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_TX_IP_CHKSM_DIS, !csum);
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_TX_TCP_CHKSM_DIS,
 				    !csum);
 	}
 
-	efx_writeo_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
+	efx_writeo_table(efx, &reg, efx->type->txd_ptr_tbl_base,
 			 tx_queue->queue);
 
 	if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) {
-		efx_oword_t reg;
-
 		/* Only 128 bits in this register */
 		BUILD_BUG_ON(EFX_MAX_TX_QUEUES > 128);
 
@@ -491,6 +489,16 @@ void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
 			set_bit_le(tx_queue->queue, (void *)&reg);
 		efx_writeo(efx, &reg, FR_AA_TX_CHKSM_CFG);
 	}
+
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+		EFX_POPULATE_OWORD_1(reg,
+				     FRF_BZ_TX_PACE,
+				     (tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI) ?
+				     FFE_BZ_TX_PACE_OFF :
+				     FFE_BZ_TX_PACE_RESERVED);
+		efx_writeo_table(efx, &reg, FR_BZ_TX_PACE_TBL,
+				 tx_queue->queue);
+	}
 }
 
 static void efx_flush_tx_queue(struct efx_tx_queue *tx_queue)
@@ -1238,8 +1246,10 @@ int efx_nic_flush_queues(struct efx_nic *efx)
 
 	/* Flush all tx queues in parallel */
 	efx_for_each_channel(channel, efx) {
-		efx_for_each_channel_tx_queue(tx_queue, channel)
-			efx_flush_tx_queue(tx_queue);
+		efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
+			if (tx_queue->initialised)
+				efx_flush_tx_queue(tx_queue);
+		}
 	}
 
 	/* The hardware supports four concurrent rx flushes, each of which may
@@ -1262,8 +1272,9 @@ int efx_nic_flush_queues(struct efx_nic *efx)
 					++rx_pending;
 				}
 			}
-			efx_for_each_channel_tx_queue(tx_queue, channel) {
-				if (tx_queue->flushed != FLUSH_DONE)
+			efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
+				if (tx_queue->initialised &&
+				    tx_queue->flushed != FLUSH_DONE)
 					++tx_pending;
 			}
 		}
@@ -1278,8 +1289,9 @@ int efx_nic_flush_queues(struct efx_nic *efx)
 	/* Mark the queues as all flushed. We're going to return failure
 	 * leading to a reset, or fake up success anyway */
 	efx_for_each_channel(channel, efx) {
-		efx_for_each_channel_tx_queue(tx_queue, channel) {
-			if (tx_queue->flushed != FLUSH_DONE)
+		efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
+			if (tx_queue->initialised &&
+			    tx_queue->flushed != FLUSH_DONE)
 				netif_err(efx, hw, efx->net_dev,
 					  "tx queue %d flush command timed out\n",
 					  tx_queue->queue);
@@ -1682,6 +1694,19 @@ void efx_nic_init_common(struct efx_nic *efx)
 	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
 		EFX_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
 	efx_writeo(efx, &temp, FR_AZ_TX_RESERVED);
+
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+		EFX_POPULATE_OWORD_4(temp,
+				     /* Default values */
+				     FRF_BZ_TX_PACE_SB_NOT_AF, 0x15,
+				     FRF_BZ_TX_PACE_SB_AF, 0xb,
+				     FRF_BZ_TX_PACE_FB_BASE, 0,
+				     /* Allow large pace values in the
+				      * fast bin. */
+				     FRF_BZ_TX_PACE_BIN_TH,
+				     FFE_BZ_TX_PACE_RESERVED);
+		efx_writeo(efx, &temp, FR_BZ_TX_PACE);
+	}
 }
 
 /* Register dump */
diff --git a/drivers/net/sfc/regs.h b/drivers/net/sfc/regs.h
index 96430ed..8227de6 100644
--- a/drivers/net/sfc/regs.h
+++ b/drivers/net/sfc/regs.h
@@ -2907,6 +2907,12 @@
 #define FRF_CZ_TMFT_SRC_MAC_HI_LBN 44
 #define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH 16
 
+/* TX_PACE_TBL */
+/* Values >20 are documented as reserved, but will result in a queue going
+ * into the fast bin with a pace value of zero. */
+#define FFE_BZ_TX_PACE_OFF 0
+#define FFE_BZ_TX_PACE_RESERVED 21
+
 /* DRIVER_EV */
 /* Sub-fields of an RX flush completion event */
 #define FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_LBN 12
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index 0ebfb99..f936892 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -644,7 +644,7 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests,
 			goto out;
 		}
 
-		/* Test both types of TX queue */
+		/* Test all enabled types of TX queue */
 		efx_for_each_channel_tx_queue(tx_queue, channel) {
 			state->offload_csum = (tx_queue->queue &
 					       EFX_TXQ_TYPE_OFFLOAD);
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
index 7e463fb..1a51653 100644
--- a/drivers/net/sfc/tx.c
+++ b/drivers/net/sfc/tx.c
@@ -336,22 +336,89 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	struct efx_tx_queue *tx_queue;
+	unsigned index, type;
 
 	if (unlikely(efx->port_inhibited))
 		return NETDEV_TX_BUSY;
 
-	tx_queue = efx_get_tx_queue(efx, skb_get_queue_mapping(skb),
-				    skb->ip_summed == CHECKSUM_PARTIAL ?
-				    EFX_TXQ_TYPE_OFFLOAD : 0);
+	index = skb_get_queue_mapping(skb);
+	type = skb->ip_summed == CHECKSUM_PARTIAL ? EFX_TXQ_TYPE_OFFLOAD : 0;
+	if (index >= efx->n_tx_channels) {
+		index -= efx->n_tx_channels;
+		type |= EFX_TXQ_TYPE_HIGHPRI;
+	}
+	tx_queue = efx_get_tx_queue(efx, index, type);
 
 	return efx_enqueue_skb(tx_queue, skb);
 }
 
 void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue)
 {
+	struct efx_nic *efx = tx_queue->efx;
+
 	/* Must be inverse of queue lookup in efx_hard_start_xmit() */
-	tx_queue->core_txq = netdev_get_tx_queue(
-		tx_queue->efx->net_dev, tx_queue->queue / EFX_TXQ_TYPES);
+	tx_queue->core_txq =
+		netdev_get_tx_queue(efx->net_dev,
+				    tx_queue->queue / EFX_TXQ_TYPES +
+				    ((tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI) ?
+				     efx->n_tx_channels : 0));
+}
+
+int efx_setup_tc(struct net_device *net_dev, u8 num_tc)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+	struct efx_channel *channel;
+	struct efx_tx_queue *tx_queue;
+	unsigned tc;
+	int rc;
+
+	if (efx_nic_rev(efx) < EFX_REV_FALCON_B0 || num_tc > EFX_MAX_TX_TC)
+		return -EINVAL;
+
+	if (num_tc == net_dev->num_tc)
+		return 0;
+
+	for (tc = 0; tc < num_tc; tc++) {
+		net_dev->tc_to_txq[tc].offset = tc * efx->n_tx_channels;
+		net_dev->tc_to_txq[tc].count = efx->n_tx_channels;
+	}
+
+	if (num_tc > net_dev->num_tc) {
+		/* Initialise high-priority queues as necessary */
+		efx_for_each_channel(channel, efx) {
+			efx_for_each_possible_channel_tx_queue(tx_queue,
+							       channel) {
+				if (!(tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI))
+					continue;
+				if (!tx_queue->buffer) {
+					rc = efx_probe_tx_queue(tx_queue);
+					if (rc)
+						return rc;
+				}
+				if (!tx_queue->initialised)
+					efx_init_tx_queue(tx_queue);
+				efx_init_tx_queue_core_txq(tx_queue);
+			}
+		}
+	} else {
+		/* Reduce number of classes before number of queues */
+		net_dev->num_tc = num_tc;
+	}
+
+	rc = netif_set_real_num_tx_queues(net_dev,
+					  max_t(int, num_tc, 1) *
+					  efx->n_tx_channels);
+	if (rc)
+		return rc;
+
+	/* Do not destroy high-priority queues when they become
+	 * unused.  We would have to flush them first, and it is
+	 * fairly difficult to flush a subset of TX queues.  Leave
+	 * it to efx_fini_channels().
+	 */
+
+	net_dev->num_tc = num_tc;
+	return 0;
 }
 
 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
@@ -437,6 +504,8 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
 
 	/* Set up TX descriptor ring */
 	efx_nic_init_tx(tx_queue);
+
+	tx_queue->initialised = true;
 }
 
 void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
@@ -459,9 +528,14 @@ void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
 
 void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
 {
+	if (!tx_queue->initialised)
+		return;
+
 	netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
 		  "shutting down TX queue %d\n", tx_queue->queue);
 
+	tx_queue->initialised = false;
+
 	/* Flush TX queue, remove descriptor ring */
 	efx_nic_fini_tx(tx_queue);
 
@@ -473,6 +547,9 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
 
 void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
 {
+	if (!tx_queue->buffer)
+		return;
+
 	netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
 		  "destroying TX queue %d\n", tx_queue->queue);
 	efx_nic_remove_tx(tx_queue);
-- 
1.7.3.4


-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply related

* Re: potential null pointer dereference in drivers/isdn/hisax/isdnl2.c
From: David Miller @ 2011-02-15 20:15 UTC (permalink / raw)
  To: miltonm; +Cc: linux-kernel, netdev, tj, isdn, jj
In-Reply-To: <1297800556_10580@mail4.comsite.net>

From: Milton Miller <miltonm@bga.com>
Date: Tue, 15 Feb 2011 14:09:16 -0600

> On Mon, 14 Feb 2011 00:53:09 -0000, Dave Miler wrote:
>> diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
>> index 0858791..98ac835 100644
>> --- a/drivers/isdn/hisax/isdnl2.c
>> +++ b/drivers/isdn/hisax/isdnl2.c
>> @@ -1243,14 +1243,21 @@ l2_st7_tout_203(struct FsmInst *fi, int event, void *arg)
>>  	st->l2.rc = 0;
>>  }
>>  
>> +static int l2_hdr_space_needed(struct Layer2 *l2)
>> +{
>> +	int len = test_bit(FLG_LAPD, &l2->flag) ? 2 : 1;
>> +
>> +	return len + (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1);
>> +}
>> +
> 
> That struck me as an funny way to write 2 * len, so I finally looked
> at the code.  I think one of those should be FLG_MOD128, but then
> at that point why not use the existing l2headersize(l2, ui) with
> ui = 0?
> 
> I see this is in linux-next of Feb 15, 2011.

Good catch, thanks.  I'll fix this.

^ permalink raw reply

* Re: pull request: sfc-next-2.6 2011-02-15
From: David Miller @ 2011-02-15 20:26 UTC (permalink / raw)
  To: bhutchings; +Cc: netdev, linux-net-drivers, therbert, john.r.fastabend
In-Reply-To: <1297800733.2584.15.camel@bwh-desktop>

From: Ben Hutchings <bhutchings@solarflare.com>
Date: Tue, 15 Feb 2011 20:12:13 +0000

> The following changes since commit 263fb5b1bf9265d0e4ce59ff6ea92f478b5b61ea:
> 
>   Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 (2011-02-08 17:19:01 -0800)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next-2.6.git for-davem
> 
> Multiqueue TX priority support for sfc, and some necessary fixes
> elsewhere.

Looks good, pulled, thanks Ben.

^ permalink raw reply

* Re: 3x59x WOL and CONFIG_SUSPEND
From: Rafael J. Wysocki @ 2011-02-15 20:36 UTC (permalink / raw)
  To: Markku Pesonen; +Cc: netdev, Steffen Klassert
In-Reply-To: <4D5A85DB.7070309@gmail.com>

On Tuesday, February 15, 2011, Markku Pesonen wrote:
> Hi,
> 
> Since commit 074037ec79bea73edf1b1ec72fef1010e83e3cc5
> (PM / Wakeup: Introduce wakeup source objects and event statistics (v3)),
> Wake-On-Lan on my 3c905C has not worked unless I enable CONFIG_SUSPEND.
> The driver says "0000:00:0b.0: WOL not supported."
> 
> Enabling CONFIG_SUSPEND makes Wake-On-Lan work on 2.6.37 while 2.6.36
> works just fine without it. Is this a regression or intended behavior?

It is indended.  CONFIG_PM_SLEEP is necessary for wakeup to work (as it should
have been before).

Thanks,
Rafael

^ permalink raw reply

* [PATCH] mac80211:  Add power to debugfs.
From: greearb @ 2011-02-15 21:04 UTC (permalink / raw)
  To: netdev; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 1f02e59... 51f0d78... M	net/mac80211/debugfs.c
 net/mac80211/debugfs.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 1f02e59..51f0d78 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -60,6 +60,10 @@ static const struct file_operations name## _ops = {			\
 	debugfs_create_file(#name, mode, phyd, local, &name## _ops);
 
 
+DEBUGFS_READONLY_FILE(user_power, "%d",
+		      local->user_power_level);
+DEBUGFS_READONLY_FILE(power, "%d",
+		      local->hw.conf.power_level);
 DEBUGFS_READONLY_FILE(frequency, "%d",
 		      local->hw.conf.channel->center_freq);
 DEBUGFS_READONLY_FILE(total_ps_buffered, "%d",
@@ -391,6 +395,8 @@ void debugfs_hw_add(struct ieee80211_local *local)
 	DEBUGFS_ADD(uapsd_queues);
 	DEBUGFS_ADD(uapsd_max_sp_len);
 	DEBUGFS_ADD(channel_type);
+	DEBUGFS_ADD(user_power);
+	DEBUGFS_ADD(power);
 
 	statsd = debugfs_create_dir("statistics", phyd);
 
-- 
1.7.2.3


^ permalink raw reply related


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