Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] netfilter: ipvs: fix compiler warnings
From: Simon Horman @ 2011-01-22  2:22 UTC (permalink / raw)
  To: Changli Gao
  Cc: Wensong Zhang, Julian Anastasov, Patrick McHardy, David S. Miller,
	netdev, lvs-devel, netfilter-devel
In-Reply-To: <1295604133-6869-1-git-send-email-xiaosuo@gmail.com>

On Fri, Jan 21, 2011 at 06:02:13PM +0800, Changli Gao wrote:
> Fix compiler warnings when no transport protocol load balancing support
> is configured.
> 
> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
> ---
>  net/netfilter/ipvs/ip_vs_core.c  |    4 +---
>  net/netfilter/ipvs/ip_vs_ctl.c   |    4 ++++
>  net/netfilter/ipvs/ip_vs_proto.c |    4 ++++
>  3 files changed, 9 insertions(+), 3 deletions(-)
> diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
> index f36a84f..d889f4f 100644
> --- a/net/netfilter/ipvs/ip_vs_core.c
> +++ b/net/netfilter/ipvs/ip_vs_core.c
> @@ -1894,9 +1894,7 @@ static int __net_init __ip_vs_init(struct net *net)
>  
>  static void __net_exit __ip_vs_cleanup(struct net *net)
>  {
> -	struct netns_ipvs *ipvs = net_ipvs(net);
> -
> -	IP_VS_DBG(10, "ipvs netns %d released\n", ipvs->gen);
> +	IP_VS_DBG(10, "ipvs netns %d released\n", net_ipvs(net)->gen);
>  }
>  

The hunk above seems unrelated to the problem described.
The rest of the changes look good. I will double check and
apply them to my tree.

Patrick, I have another fix. So I think it would be best
to take this fix though my tree and. I'll send you a pull
request shortly.

>  static struct pernet_operations ipvs_core_ops = {
> diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
> index 09ca2ce..68b8033 100644
> --- a/net/netfilter/ipvs/ip_vs_ctl.c
> +++ b/net/netfilter/ipvs/ip_vs_ctl.c
> @@ -2062,7 +2062,9 @@ static const struct file_operations ip_vs_stats_percpu_fops = {
>   */
>  static int ip_vs_set_timeout(struct net *net, struct ip_vs_timeout_user *u)
>  {
> +#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP)
>  	struct ip_vs_proto_data *pd;
> +#endif
>  
>  	IP_VS_DBG(2, "Setting timeout tcp:%d tcpfin:%d udp:%d\n",
>  		  u->tcp_timeout,
> @@ -2405,7 +2407,9 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get,
>  static inline void
>  __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u)
>  {
> +#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP)
>  	struct ip_vs_proto_data *pd;
> +#endif
>  
>  #ifdef CONFIG_IP_VS_PROTO_TCP
>  	pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
> diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
> index 6ac986c..17484a4 100644
> --- a/net/netfilter/ipvs/ip_vs_proto.c
> +++ b/net/netfilter/ipvs/ip_vs_proto.c
> @@ -60,6 +60,9 @@ static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp)
>  	return 0;
>  }
>  
> +#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP) || \
> +    defined(CONFIG_IP_VS_PROTO_SCTP) || defined(CONFIG_IP_VS_PROTO_AH) || \
> +    defined(CONFIG_IP_VS_PROTO_ESP)
>  /*
>   *	register an ipvs protocols netns related data
>   */
> @@ -85,6 +88,7 @@ register_ip_vs_proto_netns(struct net *net, struct ip_vs_protocol *pp)
>  
>  	return 0;
>  }
> +#endif
>  
>  /*
>   *	unregister an ipvs protocol
> 

^ permalink raw reply

* Re: [PATCH] netfilter: ipvs: fix compiler warnings
From: Changli Gao @ 2011-01-22  2:34 UTC (permalink / raw)
  To: Simon Horman
  Cc: Wensong Zhang, Julian Anastasov, Patrick McHardy, David S. Miller,
	netdev, lvs-devel, netfilter-devel
In-Reply-To: <20110122022232.GL2661@verge.net.au>

On Sat, Jan 22, 2011 at 10:22 AM, Simon Horman <horms@verge.net.au> wrote:
> On Fri, Jan 21, 2011 at 06:02:13PM +0800, Changli Gao wrote:
>> Fix compiler warnings when no transport protocol load balancing support
>> is configured.
>>
>> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
>> ---
>>  net/netfilter/ipvs/ip_vs_core.c  |    4 +---
>>  net/netfilter/ipvs/ip_vs_ctl.c   |    4 ++++
>>  net/netfilter/ipvs/ip_vs_proto.c |    4 ++++
>>  3 files changed, 9 insertions(+), 3 deletions(-)
>> diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
>> index f36a84f..d889f4f 100644
>> --- a/net/netfilter/ipvs/ip_vs_core.c
>> +++ b/net/netfilter/ipvs/ip_vs_core.c
>> @@ -1894,9 +1894,7 @@ static int __net_init __ip_vs_init(struct net *net)
>>
>>  static void __net_exit __ip_vs_cleanup(struct net *net)
>>  {
>> -     struct netns_ipvs *ipvs = net_ipvs(net);
>> -
>> -     IP_VS_DBG(10, "ipvs netns %d released\n", ipvs->gen);
>> +     IP_VS_DBG(10, "ipvs netns %d released\n", net_ipvs(net)->gen);
>>  }
>>
>
> The hunk above seems unrelated to the problem described.
> The rest of the changes look good. I will double check and
> apply them to my tree.
>

Yes, is a separated patch needed? It is trivial. Thanks.

-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* [net-2.6 PATCH 2/2] dcbnl: make get_app handling symmetric for IEEE and CEE DCBx
From: John Fastabend @ 2011-01-22  2:35 UTC (permalink / raw)
  To: davem, shmulikr; +Cc: netdev
In-Reply-To: <20110122023512.4239.40379.stgit@jf-dev1-dcblab>

The IEEE get/set app handlers use generic routines and do not
require the net_device to implement the dcbnl_ops routines. This
patch makes it symmetric so user space and drivers do not have
to handle the CEE version and IEEE DCBx versions differently.

Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---

 net/dcb/dcbnl.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index d900ab9..6b03f56 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -583,7 +583,7 @@ static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb,
 	u8 up, idtype;
 	int ret = -EINVAL;
 
-	if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->getapp)
+	if (!tb[DCB_ATTR_APP])
 		goto out;
 
 	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
@@ -604,7 +604,16 @@ static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb,
 		goto out;
 
 	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
-	up = netdev->dcbnl_ops->getapp(netdev, idtype, id);
+
+	if (netdev->dcbnl_ops->getapp) {
+		up = netdev->dcbnl_ops->getapp(netdev, idtype, id);
+	} else {
+		struct dcb_app app = {
+					.selector = idtype,
+					.protocol = id,
+				     };
+		up = dcb_getapp(netdev, &app);
+	}
 
 	/* send this back */
 	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);


^ permalink raw reply related

* [net-2.6 PATCH 1/2] net: dcbnl: remove redundant DCB_CAP_DCBX_STATIC bit
From: John Fastabend @ 2011-01-22  2:35 UTC (permalink / raw)
  To: davem, shmulikr; +Cc: netdev

Remove redundant DCB_CAP_DCBX_STATIC bit in DCB capabilities

Setting this bit indicates that no embedded DCBx engine is
present and the hardware can not be configured. This is the
same as having none of the DCB capability flags set or simply
not implementing the dcbnl ops at all.

This patch removes this bit. The bit has not made a stable
release yet so removing it should not be an issue with
existing apps.

Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
CC: Shmulik Ravid <shmulikr@broadcom.com>
---

 include/linux/dcbnl.h |    7 -------
 1 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h
index 68cd248..ac9df34 100644
--- a/include/linux/dcbnl.h
+++ b/include/linux/dcbnl.h
@@ -423,18 +423,11 @@ enum dcbnl_cap_attrs {
  *
  * @DCB_CAP_DCBX_VER_IEEE: for a non-host DCBX engine, indicates the engine
  *                         supports the IEEE protocol flavor
- *
- * @DCB_CAP_DCBX_STATIC: for a non-host DCBX engine, indicates the engine
- *                       supports static configuration (i.e no actual
- *                       negotiation is performed negotiated parameters equal
- *                       the initial configuration)
- *
  */
 #define DCB_CAP_DCBX_HOST		0x01
 #define DCB_CAP_DCBX_LLD_MANAGED	0x02
 #define DCB_CAP_DCBX_VER_CEE		0x04
 #define DCB_CAP_DCBX_VER_IEEE		0x08
-#define DCB_CAP_DCBX_STATIC		0x10
 
 /**
  * enum dcbnl_numtcs_attrs - number of traffic classes


^ permalink raw reply related

* Re: [net-2.6 PATCH 1/2] net: dcbnl: remove redundant DCB_CAP_DCBX_STATIC bit
From: John Fastabend @ 2011-01-22  2:52 UTC (permalink / raw)
  To: davem@davemloft.net, shmulikr@broadcom.com; +Cc: netdev@vger.kernel.org
In-Reply-To: <20110122023512.4239.40379.stgit@jf-dev1-dcblab>

On 1/21/2011 6:35 PM, John Fastabend wrote:
> Remove redundant DCB_CAP_DCBX_STATIC bit in DCB capabilities
> 
> Setting this bit indicates that no embedded DCBx engine is
> present and the hardware can not be configured. This is the
> same as having none of the DCB capability flags set or simply
> not implementing the dcbnl ops at all.
> 
> This patch removes this bit. The bit has not made a stable
> release yet so removing it should not be an issue with
> existing apps.
> 
> Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
> CC: Shmulik Ravid <shmulikr@broadcom.com>
> ---
> 

Shmulik, could you ACK this because you added these bits? But
I was adding support for this in lldpad and I see no reason that
we need these?

Thanks,
John.

^ permalink raw reply

* [GIT PULL nf-next-2.6] IPVS updates for v2.6.38-rc1
From: Simon Horman @ 2011-01-22  3:10 UTC (permalink / raw)
  To: lvs-devel, netfilter-devel, netdev
  Cc: Changli Gao, Hans Schillstrom, Julian Anastasov, Patrick McHardy

Hi Patrick, please consider pulling
  git://git.kernel.org/pub/scm/linux/kernel/git/horms/lvs-test-2.6.git for-patrick

This includes bugfixes by Changli Gao and Hans Schillstrom.

Changli Gao (1):
      netfilter: ipvs: fix compiler warnings

Simon Horman (1):
      IPVS: Change sock_create_kernel() to __sock_create()

 net/netfilter/ipvs/ip_vs_ctl.c   |    4 ++++
 net/netfilter/ipvs/ip_vs_proto.c |    4 ++++
 net/netfilter/ipvs/ip_vs_sync.c  |    4 ++--
 3 files changed, 10 insertions(+), 2 deletions(-)


^ permalink raw reply

* [PATCH 2/2] IPVS: Change sock_create_kernel() to __sock_create()
From: Simon Horman @ 2011-01-22  3:10 UTC (permalink / raw)
  To: lvs-devel, netfilter-devel, netdev
  Cc: Changli Gao, Hans Schillstrom, Julian Anastasov, Patrick McHardy,
	Simon Horman
In-Reply-To: <1295665835-8708-1-git-send-email-horms@verge.net.au>

The recent netns changes omitted to change
sock_create_kernel() to __sock_create() in ip_vs_sync.c

The effect of this is that the interface will be selected in the
root-namespace, from my point of view it's a major bug.

Reported-by: Hans Schillstrom <hans@schillstrom.com>
Acked-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
 net/netfilter/ipvs/ip_vs_sync.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index d1adf98..d5a6e64 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1305,7 +1305,7 @@ static struct socket *make_send_sock(struct net *net)
 	int result;
 
 	/* First create a socket */
-	result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
+	result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1);
 	if (result < 0) {
 		pr_err("Error during creation of socket; terminating\n");
 		return ERR_PTR(result);
@@ -1351,7 +1351,7 @@ static struct socket *make_receive_sock(struct net *net)
 	int result;
 
 	/* First create a socket */
-	result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
+	result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1);
 	if (result < 0) {
 		pr_err("Error during creation of socket; terminating\n");
 		return ERR_PTR(result);
-- 
1.7.2.3


^ permalink raw reply related

* [PATCH 1/2] netfilter: ipvs: fix compiler warnings
From: Simon Horman @ 2011-01-22  3:10 UTC (permalink / raw)
  To: lvs-devel, netfilter-devel, netdev
  Cc: Changli Gao, Hans Schillstrom, Julian Anastasov, Patrick McHardy,
	Simon Horman
In-Reply-To: <1295665835-8708-1-git-send-email-horms@verge.net.au>

From: Changli Gao <xiaosuo@gmail.com>

Fix compiler warnings when no transport protocol load balancing support
is configured.

[horms@verge.net.au: removed suprious __ip_vs_cleanup() clean-up hunk]
Signed-off-by: Changli Gao <xiaosuo@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
 net/netfilter/ipvs/ip_vs_ctl.c   |    4 ++++
 net/netfilter/ipvs/ip_vs_proto.c |    4 ++++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 09ca2ce..68b8033 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -2062,7 +2062,9 @@ static const struct file_operations ip_vs_stats_percpu_fops = {
  */
 static int ip_vs_set_timeout(struct net *net, struct ip_vs_timeout_user *u)
 {
+#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP)
 	struct ip_vs_proto_data *pd;
+#endif
 
 	IP_VS_DBG(2, "Setting timeout tcp:%d tcpfin:%d udp:%d\n",
 		  u->tcp_timeout,
@@ -2405,7 +2407,9 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get,
 static inline void
 __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u)
 {
+#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP)
 	struct ip_vs_proto_data *pd;
+#endif
 
 #ifdef CONFIG_IP_VS_PROTO_TCP
 	pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index 6ac986c..17484a4 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -60,6 +60,9 @@ static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp)
 	return 0;
 }
 
+#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP) || \
+    defined(CONFIG_IP_VS_PROTO_SCTP) || defined(CONFIG_IP_VS_PROTO_AH) || \
+    defined(CONFIG_IP_VS_PROTO_ESP)
 /*
  *	register an ipvs protocols netns related data
  */
@@ -85,6 +88,7 @@ register_ip_vs_proto_netns(struct net *net, struct ip_vs_protocol *pp)
 
 	return 0;
 }
+#endif
 
 /*
  *	unregister an ipvs protocol
-- 
1.7.2.3


^ permalink raw reply related

* Re: [PATCH] netfilter: ipvs: fix compiler warnings
From: Simon Horman @ 2011-01-22  3:11 UTC (permalink / raw)
  To: Changli Gao
  Cc: Wensong Zhang, Julian Anastasov, Patrick McHardy, David S. Miller,
	netdev, lvs-devel, netfilter-devel
In-Reply-To: <AANLkTimoSQbjH-iW6x36FHs6yzDgsey9RS+yFXnKOxq5@mail.gmail.com>

On Sat, Jan 22, 2011 at 10:34:23AM +0800, Changli Gao wrote:
> On Sat, Jan 22, 2011 at 10:22 AM, Simon Horman <horms@verge.net.au> wrote:
> > On Fri, Jan 21, 2011 at 06:02:13PM +0800, Changli Gao wrote:
> >> Fix compiler warnings when no transport protocol load balancing support
> >> is configured.
> >>
> >> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
> >> ---
> >>  net/netfilter/ipvs/ip_vs_core.c  |    4 +---
> >>  net/netfilter/ipvs/ip_vs_ctl.c   |    4 ++++
> >>  net/netfilter/ipvs/ip_vs_proto.c |    4 ++++
> >>  3 files changed, 9 insertions(+), 3 deletions(-)
> >> diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
> >> index f36a84f..d889f4f 100644
> >> --- a/net/netfilter/ipvs/ip_vs_core.c
> >> +++ b/net/netfilter/ipvs/ip_vs_core.c
> >> @@ -1894,9 +1894,7 @@ static int __net_init __ip_vs_init(struct net *net)
> >>
> >>  static void __net_exit __ip_vs_cleanup(struct net *net)
> >>  {
> >> -     struct netns_ipvs *ipvs = net_ipvs(net);
> >> -
> >> -     IP_VS_DBG(10, "ipvs netns %d released\n", ipvs->gen);
> >> +     IP_VS_DBG(10, "ipvs netns %d released\n", net_ipvs(net)->gen);
> >>  }
> >>
> >
> > The hunk above seems unrelated to the problem described.
> > The rest of the changes look good. I will double check and
> > apply them to my tree.
> >
> 
> Yes, is a separated patch needed? It is trivial. Thanks.

Yes, please send a separate patch.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] netfilter: ipvs: fix compiler warnings
From: Simon Horman @ 2011-01-22  3:12 UTC (permalink / raw)
  To: Changli Gao
  Cc: Wensong Zhang, Julian Anastasov, Patrick McHardy, David S. Miller,
	netdev, lvs-devel, netfilter-devel
In-Reply-To: <20110122031116.GA8443@verge.net.au>

On Sat, Jan 22, 2011 at 02:11:16PM +1100, Simon Horman wrote:
> On Sat, Jan 22, 2011 at 10:34:23AM +0800, Changli Gao wrote:
> > On Sat, Jan 22, 2011 at 10:22 AM, Simon Horman <horms@verge.net.au> wrote:
> > > On Fri, Jan 21, 2011 at 06:02:13PM +0800, Changli Gao wrote:
> > >> Fix compiler warnings when no transport protocol load balancing support
> > >> is configured.
> > >>
> > >> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
> > >> ---
> > >>  net/netfilter/ipvs/ip_vs_core.c  |    4 +---
> > >>  net/netfilter/ipvs/ip_vs_ctl.c   |    4 ++++
> > >>  net/netfilter/ipvs/ip_vs_proto.c |    4 ++++
> > >>  3 files changed, 9 insertions(+), 3 deletions(-)
> > >> diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
> > >> index f36a84f..d889f4f 100644
> > >> --- a/net/netfilter/ipvs/ip_vs_core.c
> > >> +++ b/net/netfilter/ipvs/ip_vs_core.c
> > >> @@ -1894,9 +1894,7 @@ static int __net_init __ip_vs_init(struct net *net)
> > >>
> > >>  static void __net_exit __ip_vs_cleanup(struct net *net)
> > >>  {
> > >> -     struct netns_ipvs *ipvs = net_ipvs(net);
> > >> -
> > >> -     IP_VS_DBG(10, "ipvs netns %d released\n", ipvs->gen);
> > >> +     IP_VS_DBG(10, "ipvs netns %d released\n", net_ipvs(net)->gen);
> > >>  }
> > >>
> > >
> > > The hunk above seems unrelated to the problem described.
> > > The rest of the changes look good. I will double check and
> > > apply them to my tree.
> > >
> > 
> > Yes, is a separated patch needed? It is trivial. Thanks.
> 
> Yes, please send a separate patch.

To clarify, I have applied the other hunks and included
them in a pull request that I sent to Patrick a few moments ago.

^ permalink raw reply

* Re: [PATCH net-next-2.6 v3 0/2] can: add driver for Softing card
From: David Miller @ 2011-01-22  4:17 UTC (permalink / raw)
  To: kurt.van.dijck-/BeEPy95v10
  Cc: socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-pcmcia-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20110111143007.GB387-MxZ6Iy/zr/UdbCeoMzGj59i2O/JbrIOy@public.gmane.org>

From: Kurt Van Dijck <kurt.van.dijck-/BeEPy95v10@public.gmane.org>
Date: Tue, 11 Jan 2011 15:30:08 +0100

> This series will add a driver for Softing PCMCIA CAN card.

Both patches applied, thanks.

^ permalink raw reply

* Re: [RFC PATCH] ipsec: fix IPv4 AH alignment on 32 bits
From: David Miller @ 2011-01-22  4:20 UTC (permalink / raw)
  To: nicolas.dichtel; +Cc: netdev, christophe.gouault
In-Reply-To: <4D2F3453.9020203@6wind.com>

From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Date: Thu, 13 Jan 2011 18:20:19 +0100

> here is a patch to fix alignment of IPv4 AH. Note that this break
> compatiblity for some algorithms (like SHA256) with old kernels
> ... but upstream cannot use SHA256 on IPv4, for example, with a target
> that is RFC compliant.
> 
> I don't know what is the best way to fix this.

We cannot just start rejecting the old 8-byte alignment on input if
Linux has been using an 8-byte alignment since day one.

If you want this change to be considered seriously, you need to relax
the AH4 input check.

^ permalink raw reply

* Re: [PATCH v2 1/3] can: at91_can: clean up usage of AT91_MB_RX_FIRST and AT91_MB_RX_NUM
From: Wolfgang Grandegger @ 2011-01-22  7:14 UTC (permalink / raw)
  To: David Miller
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, mkl-bIcnvbaLZ9MEGnE8C9+IrQ
In-Reply-To: <20110121.165409.200115988.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>

On 01/22/2011 01:54 AM, David Miller wrote:
> From: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> Date: Mon, 17 Jan 2011 20:50:36 +0100
> 
>> On 01/11/2011 02:21 PM, Marc Kleine-Budde wrote:
>>> This patch cleans up the usage of two macros which specify the mailbox
>>> usage. AT91_MB_RX_FIRST and AT91_MB_RX_NUM define the first and the
>>> number of RX mailboxes. The current driver uses these variables in an
>>> unclean way; assuming that AT91_MB_RX_FIRST is 0;
>>>
>>> This patch cleans up the usage of these macros, no longer assuming
>>> AT91_MB_RX_FIRST == 0.
>>>
>>> Signed-off-by: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>>
>> Any comments on this?
> 
> I would also seriously like to see these changes get some feedback,
> they've been rotting in patchwork for more than a week.

V2 was OK and it got my "Acked-by" here:

http://marc.info/?l=linux-netdev&m=129534267002747&w=2

Wolfgang.

^ permalink raw reply

* Re: [PATCH v2 1/3] can: at91_can: clean up usage of AT91_MB_RX_FIRST and AT91_MB_RX_NUM
From: Kurt Van Dijck @ 2011-01-22  7:50 UTC (permalink / raw)
  To: David Miller
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, mkl-bIcnvbaLZ9MEGnE8C9+IrQ,
	wg-5Yr1BZd7O62+XT7JhA+gdA
In-Reply-To: <20110121.165409.200115988.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>

On Fri, Jan 21, 2011 at 04:54:09PM -0800, David Miller wrote:
> > On 01/11/2011 02:21 PM, Marc Kleine-Budde wrote:
> >> This patch cleans up the usage of two macros which specify the mailbox
> >> usage. AT91_MB_RX_FIRST and AT91_MB_RX_NUM define the first and the
> >> number of RX mailboxes. The current driver uses these variables in an
> >> unclean way; assuming that AT91_MB_RX_FIRST is 0;
> >> 
> >> This patch cleans up the usage of these macros, no longer assuming
> >> AT91_MB_RX_FIRST == 0.
> >> 
> >> Signed-off-by: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > 
> > Any comments on this?
> 
> I would also seriously like to see these changes get some feedback,
> they've been rotting in patchwork for more than a week.

I have no experience with this specific chip.
IMO, this chip errata (as explained in the post) got an elegant solution.
That part definitely gets my
Acked-by: Kurt Van Dijck <kurt.van.dijck-/BeEPy95v10@public.gmane.org>

Regards,
Kurt

^ permalink raw reply

* Re: [RFC] ipv6: don't flush routes when setting loopback down
From: Eric W. Biederman @ 2011-01-22  8:17 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jiri Bohac, David Miller, brian.haley, netdev, maheshkelkar,
	lorenzo, yoshfuji, stable
In-Reply-To: <20110119120123.40974cbe@s6510>

Stephen Hemminger <shemminger@vyatta.com> writes:

> On Wed, 19 Jan 2011 20:56:32 +0100
> Jiri Bohac <jbohac@suse.cz> wrote:
>
>> On Wed, Jan 19, 2011 at 11:38:17AM -0800, Stephen Hemminger wrote:
>> > Jiri Bohac <jbohac@suse.cz> wrote:
>> > > I have the feeling that Eric's patch is the safest solution we
>> > > have so far:
>> > Eric's patch has other regressions, see the discussion.
>> 
>> What regression do you mean? I have read the whole discussion
>> thoroughly. You only say in one message that deleting ::1 would
>> propagate to routing daemons. And Eric correctly stated that
>> people couldn't hit this, because  deleting ::1 would break
>> things on its own.
>> 
>> Is there a real problem with Eric's fix?
>> 
>> Thanks,
>> 
>
> If address is assigned to loopback interface (other than ::1) then
> Eric's fix doesn't work.  It is common to use an additional address
> on the lo device when doing routing protocols.

Sigh.

I just got back to looking through the rest of my failures in 2.6.37 and
despite it looking like it worked when i tested it, your patch doesn't
actually work on my real work load that has broken.

At least your change that confirmed that the root problem is somewhere
in the routing.

Eric



^ permalink raw reply

* Re: [PATCH] neigh: __rcu annotations
From: Paul E. McKenney @ 2011-01-22  1:36 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1295510567.2653.487.camel@edumazet-laptop>

On Thu, Jan 20, 2011 at 09:02:47AM +0100, Eric Dumazet wrote:
> fix some minor issues and sparse (__rcu) warnings
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> ---
>  net/core/neighbour.c |   13 +++++++------
>  1 file changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/net/core/neighbour.c b/net/core/neighbour.c
> index 60a9029..799f06e 100644
> --- a/net/core/neighbour.c
> +++ b/net/core/neighbour.c
> @@ -316,7 +316,7 @@ static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries)
>  {
>  	size_t size = entries * sizeof(struct neighbour *);
>  	struct neigh_hash_table *ret;
> -	struct neighbour **buckets;
> +	struct neighbour __rcu **buckets;
> 
>  	ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
>  	if (!ret)
> @@ -324,14 +324,14 @@ static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries)
>  	if (size <= PAGE_SIZE)
>  		buckets = kzalloc(size, GFP_ATOMIC);
>  	else
> -		buckets = (struct neighbour **)
> +		buckets = (struct neighbour __rcu **)
>  			  __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
>  					   get_order(size));
>  	if (!buckets) {
>  		kfree(ret);
>  		return NULL;
>  	}
> -	rcu_assign_pointer(ret->hash_buckets, buckets);
> +	ret->hash_buckets = buckets;
>  	ret->hash_mask = entries - 1;
>  	get_random_bytes(&ret->hash_rnd, sizeof(ret->hash_rnd));
>  	return ret;
> @@ -343,7 +343,7 @@ static void neigh_hash_free_rcu(struct rcu_head *head)
>  						    struct neigh_hash_table,
>  						    rcu);
>  	size_t size = (nht->hash_mask + 1) * sizeof(struct neighbour *);
> -	struct neighbour **buckets = nht->hash_buckets;
> +	struct neighbour __rcu **buckets = nht->hash_buckets;
> 
>  	if (size <= PAGE_SIZE)
>  		kfree(buckets);
> @@ -1540,7 +1540,7 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
>  		panic("cannot create neighbour proc dir entry");
>  #endif
> 
> -	tbl->nht = neigh_hash_alloc(8);
> +	RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(8));
> 
>  	phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
>  	tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
> @@ -1602,7 +1602,8 @@ int neigh_table_clear(struct neigh_table *tbl)
>  	}
>  	write_unlock(&neigh_tbl_lock);
> 
> -	call_rcu(&tbl->nht->rcu, neigh_hash_free_rcu);
> +	call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
> +		 neigh_hash_free_rcu);

Hello, Eric,

Any chance of a comment?  Perhaps something like:

	/*
	 * Because this has been removed from the list, no other updater
	 * can access this element.
	 */

							Thanx, Paul

>  	tbl->nht = NULL;
> 
>  	kfree(tbl->phash_buckets);
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: Problems with /proc/net/tcp6  - possible bug - ipv6
From: Eric Dumazet @ 2011-01-22  8:59 UTC (permalink / raw)
  To: PK; +Cc: linux-kernel, netdev
In-Reply-To: <702550.61465.qm@web63902.mail.re1.yahoo.com>

Le vendredi 21 janvier 2011 à 22:30 -0800, PK a écrit :
> Creating many ipv6 connections hits a ceiling on connections/fds ; okay, fine.
> 
> But in my case I'm seeing millions of entries spring up within a few seconds and 
> then vanish within a few minutes, in /proc/net/tcp6 (vanish due to garbage 
> collection?)
> 
> Furthermore I can trigger this easily on vanilla kernels from 2.6.36 to 
> 2.6.38-rc1-next-20110121  inside a ubuntu 10.10 amd64 vm, causing the kernel to 
> spew warnings.  There is also some corruption in the logs (see kernel-sample.log 
> line 296), but that may be unrelated.
> 
> More explanation, kernel config of the primary machine I saw this on, sample 
> ruby script to reproduce (inside the ubuntu VMs I apt-get and use ruby-1.9.1), 
> are located at
> https://github.com/runningdogx/net6-bug
> 
> Seems to only affect 64-bit.  So far I have not been able to reproduce on 32-bit 
> ubuntu VMs of any kernel version.
> Seems to only affect IPv6.  So far I have not been able to reproduce using IPv4 
> connections (and watching /proc/net/tcp of course).
> Does not trigger the bug if the connections are made to ::1.  Only externally 
> routable local and global IPv6 addresses seem to cause problems.
> Seems to have been introduced between 2.6.35 and 2.6.36 (see README on github 
> for more kernels I've tried)
> 
> All the tested Ubuntu VMs are stock 10.10 userland, with vanilla kernels (the 
> latest ubuntu kernel is 2.6.35-something, and my initial test didn't show it 
> suffering from this problem)
> 
> Originally noticed on separate Gentoo 64-bit non-vm system when doing web 
> benchmarking.
> 
> not subscribed, so please keep me in cc although I'll try to follow the thread
> 
> 

Hi PK (Sorry, your real name is hidden)

I could not reproduce this on current linux-2.6 kernel.

How many vcpus running in your VM, and memory ?

Note : a recent commit did fix /proc/net/tcp[6] behavior

commit 1bde5ac49398a064c753bb490535cfad89e99a5f
Author: Eric Dumazet <eric.dumazet@gmail.com>
Date:   Thu Dec 23 09:32:46 2010 -0800

    tcp: fix listening_get_next()
    
    Alexey Vlasov found /proc/net/tcp could sometime loop and display
    millions of sockets in LISTEN state.
    
    In 2.6.29, when we converted TCP hash tables to RCU, we left two
    sk_next() calls in listening_get_next().
    
    We must instead use sk_nulls_next() to properly detect an end of chain.
    
    Reported-by: Alexey Vlasov <renton@renton.name>
    Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* Re: [PATCH] xen: netfront: Drop GSO SKBs which do not have csum_blank.
From: Ian Campbell @ 2011-01-22  9:43 UTC (permalink / raw)
  To: Jeremy Fitzhardinge; +Cc: netdev@vger.kernel.org, xen-devel@lists.xensource.com
In-Reply-To: <4D3A2BD2.5030802@goop.org>

On Sat, 2011-01-22 at 00:58 +0000, Jeremy Fitzhardinge wrote: 
> On 01/05/2011 05:23 AM, Ian Campbell wrote:
> > The Linux network stack expects all GSO SKBs to have ip_summed ==
> > CHECKSUM_PARTIAL (which implies that the frame contains a partial
> > checksum) and the Xen network ring protocol similarly expects an SKB
> > which has GSO set to also have NETRX_csum_blank (which also implies a
> > partial checksum). Therefore drop such frames on receive otherwise
> > they will trigger the warning in skb_gso_segment.
> >
> > Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> > Cc: Jeremy Fitzhardinge <jeremy@goop.org>
> > Cc: xen-devel@lists.xensource.com
> > Cc: netdev@vger.kernel.org
> > ---
> >  drivers/net/xen-netfront.c |    5 +++++
> >  1 files changed, 5 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
> > index cdbeec9..8b8c480 100644
> > --- a/drivers/net/xen-netfront.c
> > +++ b/drivers/net/xen-netfront.c
> > @@ -836,6 +836,11 @@ static int handle_incoming_queue(struct net_device *dev,
> >  				dev->stats.rx_errors++;
> >  				continue;
> >  			}
> > +		} else if (skb_is_gso(skb)) {
> > +			kfree_skb(skb);
> > +			packets_dropped++;
> > +			dev->stats.rx_errors++;
> > +			continue;
> 
> This looks redundant; why not something like:
> 
> diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
> index 47e6a71..c1b8f64 100644
> --- a/drivers/net/xen-netfront.c
> +++ b/drivers/net/xen-netfront.c
> @@ -852,13 +852,12 @@ static int handle_incoming_queue(struct net_device *dev,
>  		/* Ethernet work: Delayed to here as it peeks the header. */
>  		skb->protocol = eth_type_trans(skb, dev);
>  
> -		if (skb->ip_summed == CHECKSUM_PARTIAL) {
> -			if (skb_checksum_setup(skb)) {
> -				kfree_skb(skb);
> -				packets_dropped++;
> -				dev->stats.rx_errors++;
> -				continue;
> -			}
> +		if (skb->ip_summed != CHECKSUM_PARTIAL ||
> +		    skb_checksum_setup(skb)) {

That drops non-partial skbs. However they are fine unless they also
claim to be gso.

Perhaps you meant "skb->ip_summed == CHECKSUM_PARTIAL && !
skb_checksum_setup(skb)" which I think works but doesn't allow us to
correctly chain the gso check onto the else.

Ian.

> +			kfree_skb(skb);
> +			packets_dropped++;
> +			dev->stats.rx_errors++;
> +			continue;
>  		}
>  
>  		dev->stats.rx_packets++;
> 
> Thanks,
> 	J
> 
> 



^ permalink raw reply

* [PATCH] unicore32: add nic/mac driver for PKUnity SoC
From: Guan Xuetao @ 2011-01-22 11:09 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel

From: Guan Xuetao <gxt@mprc.pku.edu.cn>

This patch adds nic/mac driver for PKUnity SoC.

Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
---
 drivers/net/Kconfig    |    6 +
 drivers/net/Makefile   |    1 +
 drivers/net/puv3_mac.c | 2066 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 2073 insertions(+), 0 deletions(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 4f1755b..cc99bc3 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2014,6 +2014,12 @@ config BCM63XX_ENET
 	  This driver supports the ethernet MACs in the Broadcom 63xx
 	  MIPS chipset family (BCM63XX).
 
+config PUV3_MAC
+	tristate "PKUnity v3 UMAL Gigabit Network Adapter support"
+	depends on UNICORE32 && ARCH_PUV3
+	select MII
+	select PHYLIB
+
 source "drivers/net/fs_enet/Kconfig"
 
 source "drivers/net/octeon/Kconfig"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index b90738d..9533b62 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -147,6 +147,7 @@ obj-$(CONFIG_FORCEDETH) += forcedeth.o
 obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
 obj-$(CONFIG_AX88796) += ax88796.o
 obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
+obj-$(CONFIG_PUV3_MAC) += puv3_mac.o
 
 obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
diff --git a/drivers/net/puv3_mac.c b/drivers/net/puv3_mac.c
new file mode 100644
index 0000000..b96c10c
--- /dev/null
+++ b/drivers/net/puv3_mac.c
@@ -0,0 +1,2066 @@
+/*
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/bug.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/cache.h>
+#include <linux/io.h>
+
+#include <asm/processor.h>	/* Processor type for cache alignment. */
+#include <mach/hardware.h>
+
+MODULE_DESCRIPTION("PKUNITY-3 SOC Ethernet driver");
+MODULE_LICENSE("GPL v2");
+
+/**********************************************************************
+ *  Globals
+ ********************************************************************* */
+
+static const char umal_string[] = "PKUnity-v3-UMAL";
+static const char umal_mdio_string[] = "umal-mdio";
+
+struct eth_addr {
+	u8 addr[6];
+};
+
+struct eth_addr hw_addr[1] = {
+	{ {0x00, 0x25, 0x9b, 0xff, 0x00, 0x00} }
+};
+
+/**********************************************************************
+ *  Simple types
+ ********************************************************************* */
+
+enum umal_speed {
+	umal_speed_none = 0,
+	umal_speed_10 = SPEED_10,
+	umal_speed_100 = SPEED_100,
+	umal_speed_1000 = SPEED_1000,
+};
+
+enum umal_duplex {
+	umal_duplex_none = -1,
+	umal_duplex_half = DUPLEX_HALF,
+	umal_duplex_full = DUPLEX_FULL,
+};
+
+enum umal_fc {
+	umal_fc_none,
+	umal_fc_disabled,
+	umal_fc_frame,
+	umal_fc_collision,
+	umal_fc_carrier,
+};
+
+enum umal_state {
+	umal_state_uninit,
+	umal_state_off,
+	umal_state_on,
+	umal_state_broken,
+};
+
+/**********************************************************************
+ *  Macros
+ ********************************************************************* */
+
+#define UMALDMA_NEXTBUF(d, f) ((((d)->f+1) == (d)->umaldma_dscrtable_end) ? \
+			  (d)->umaldma_dscrtable : (d)->f+1)
+
+#define DMA_RX			0
+#define DMA_TX			1
+
+#define UMAL_MAX_TXDESCR	256
+#define UMAL_MAX_RXDESCR	256
+
+#define ETHER_ADDR_LEN		6
+#define ENET_PACKET_SIZE	1518
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT		(2*HZ)
+
+/**********************************************************************
+ *  DMA Descriptor structure
+ ********************************************************************* */
+
+struct umaldmadscr {
+	dma_addr_t   PacketStartAddr;
+	int          PacketSize;
+	dma_addr_t   NextDescriptor;
+	struct umaldmadscr *NextDescriptor_Virt;
+};
+
+/**********************************************************************
+ *  DMA Controller structure
+ ********************************************************************* */
+
+struct umaldma {
+	/*
+	 * This stuff is used to identify the channel and the registers
+	 * associated with it.
+	 */
+	/* back pointer to associated MAC */
+	struct umal_softc	*umaldma_eth;
+	/* direction (1=transmit) */
+	int			umaldma_txdir;
+	/* total # of descriptors in ring */
+	int			umaldma_maxdescr;
+	/*
+	 * This stuff is for maintenance of the ring
+	 */
+	/* base of descriptor table */
+	struct umaldmadscr	*umaldma_dscrtable;
+	void			*umaldma_dscrtable_unaligned;
+	/* and also the phys addr */
+	dma_addr_t		umaldma_dscrtable_phys;
+	/* and also the phys addr */
+	dma_addr_t		umaldma_dscrtable_phys_unaligned;
+	/* end of descriptor table */
+	struct umaldmadscr	*umaldma_dscrtable_end;
+	/* context table, one per descr */
+	struct sk_buff		**umaldma_ctxtable;
+	/* next dscr for sw to add */
+	struct umaldmadscr	*umaldma_addptr;
+	/* next dscr for sw to remove */
+	struct umaldmadscr	*umaldma_remptr;
+};
+
+/**********************************************************************
+ *  Ethernet softc structure
+ ********************************************************************* */
+
+struct umal_softc {
+
+	/*
+	 * Linux-specific things
+	 */
+	struct net_device	*umal_dev;	/* pointer to linux device */
+	int			umal_idx;
+	struct phy_device	*phy_dev;	/* the associated PHY device */
+	struct mii_bus		*mii_bus;	/* the MII bus */
+	int			phy_irq[PHY_MAX_ADDR];
+	spinlock_t		umal_lock;	/* spin lock */
+	int			umal_devflags;	/* current device flags */
+
+	/*
+	 * Controller-specific things
+	 */
+	enum umal_state		umal_state;	/* current state */
+	unsigned char		umal_hwaddr[ETHER_ADDR_LEN];
+
+	enum umal_speed		umal_speed;	/* current speed */
+	enum umal_duplex	umal_duplex;	/* current duplex */
+	enum umal_fc		umal_fc;	/* cur. flow control setting */
+	int			umal_pause;	/* current pause setting */
+	int			umal_link;	/* current link state */
+
+	struct umaldma		umal_rxdma;	/* rx dma channel */
+	struct umaldma		umal_txdma;	/* tx dma channel */
+};
+
+/**********************************************************************
+ *  Prototypes
+ ********************************************************************* */
+
+static int umal_mii_reset(struct mii_bus *bus);
+static int umal_mii_read(struct mii_bus *bus, int phyaddr, int regidx);
+static int umal_mii_write(struct mii_bus *bus, int phyaddr, int regidx,
+		u16 val);
+static int umal_mii_probe(struct net_device *dev);
+
+static void umaldma_initctx(struct umaldma *d, struct umal_softc *s,
+		int rxtx, int maxdescr);
+static void umaldma_uninitctx(struct umaldma *d);
+static void umaldma_channel_start(struct umaldma *d, int rxtx);
+static void umaldma_channel_stop(struct umaldma *d);
+static int umaldma_add_rcvbuffer(struct umal_softc *sc, struct umaldma *d,
+		struct sk_buff *m);
+static int umaldma_add_txbuffer(struct umaldma *d, struct sk_buff *m);
+static void umaldma_emptyring(struct umaldma *d);
+static void umaldma_fillring(struct umal_softc *sc, struct umaldma *d);
+static int umaldma_rx_process(struct umal_softc *sc, struct umaldma *d,
+		int work_to_do, int poll);
+static void umaldma_tx_process(struct umal_softc *sc, struct umaldma *d,
+		int poll);
+
+static int umal_initctx(struct umal_softc *s);
+static void umal_uninitctx(struct umal_softc *s);
+static void umal_channel_start(struct umal_softc *s);
+static void umal_channel_stop(struct umal_softc *s);
+static enum umal_state umal_set_channel_state(struct umal_softc *,
+		enum umal_state);
+
+static int umal_init(struct platform_device *pldev, long long base);
+static int umal_open(struct net_device *dev);
+static int umal_close(struct net_device *dev);
+static int umal_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static irqreturn_t umal_intr(int irq, void *dev_instance);
+static void umal_clr_intr(struct net_device *dev);
+static int umal_start_tx(struct sk_buff *skb, struct net_device *dev);
+static void umal_tx_timeout(struct net_device *dev);
+static void umal_set_rx_mode(struct net_device *dev);
+static void umal_promiscuous_mode(struct umal_softc *sc, int onoff);
+static void umal_setmulti(struct umal_softc *sc);
+static int umal_set_speed(struct umal_softc *s, enum umal_speed speed);
+static int umal_set_duplex(struct umal_softc *s, enum umal_duplex duplex,
+		enum umal_fc fc);
+static int umal_change_mtu(struct net_device *_dev, int new_mtu);
+static void umal_miipoll(struct net_device *dev);
+
+/**********************************************************************
+ *  MII Bus functions for PAL (phy abstraction layer)
+ ********************************************************************* */
+
+/**********************************************************************
+ *  UMAL_MII_RESET(bus)
+ *
+ *  Reset MII bus.
+ *
+ *  Input parameters:
+ *	   bus     - MDIO bus handle
+ *
+ *  Return value:
+ *	   0 if ok
+ ********************************************************************* */
+static int umal_mii_reset(struct mii_bus *bus)
+{
+	UMAL_MIICFG = UMAL_MIICFG_RESET; /* reset the MII management */
+	UMAL_MIICFG = 0x0;		/* enable the MII management */
+	UMAL_MIICFG |= 0x7;		/* source clock division = 28 */
+
+	return 0;
+}
+
+/**********************************************************************
+ *  UMAL_MII_READ(bus, phyaddr, regidx)
+ *  Read a PHY register.
+ *
+ *  Input parameters:
+ *	   bus     - MDIO bus handle
+ *	   phyaddr - PHY's address
+ *	   regnum  - index of register to read
+ *
+ *  Return value:
+ *	   value read, or 0xffff if an error occurred.
+ ********************************************************************* */
+static int umal_mii_read(struct mii_bus *bus, int phyaddr, int regidx)
+{
+	int tmp = 0;
+
+	UMAL_MIIADDR = (phyaddr<<8) | regidx;
+	UMAL_MIICMD = UMAL_MIICMD_READ;
+
+	tmp = UMAL_MIIIDCT;
+	while (tmp & UMAL_MIIIDCT_BUSY)
+		tmp = UMAL_MIIIDCT;
+
+	if (tmp & UMAL_MIIIDCT_NOTVALID)
+		return 0xffff;
+
+	UMAL_MIICMD = 0;
+
+	tmp = UMAL_MIISTATUS;
+	return tmp;
+}
+
+/**********************************************************************
+ *  UMAL_MII_WRITE(bus, phyaddr, regidx, regval)
+ *
+ *  Write a value to a PHY register.
+ *
+ *  Input parameters:
+ *	   bus     - MDIO bus handle
+ *	   phyaddr - PHY to use
+ *	   regidx  - register within the PHY
+ *	   regval  - data to write to register
+ *
+ *  Return value:
+ *	   0 if ok
+ ********************************************************************* */
+static int umal_mii_write(struct mii_bus *bus, int phyaddr, int regidx, u16 val)
+{
+	int tmp = 0;
+
+	UMAL_MIIADDR = (phyaddr<<8) | regidx;
+	UMAL_MIICTRL = val;
+
+	tmp = UMAL_MIIIDCT;
+	while (tmp & UMAL_MIIIDCT_BUSY)
+		tmp = UMAL_MIIIDCT;
+
+	return 0;
+}
+
+/**********************************************************************
+ *  UMAL_MII_PROBE(dev)
+ *
+ *  Write a value to a PHY register.
+ *
+ *  Input parameters:
+ *	   dev - net_device structure
+ *
+ *  Return value:
+ *	   0 if ok
+ ********************************************************************* */
+static int umal_mii_probe(struct net_device *dev)
+{
+	struct umal_softc *sc = netdev_priv(dev);
+	struct phy_device *phy_dev;
+	int i;
+
+	for (i = 0; i < PHY_MAX_ADDR; i++) {
+		phy_dev = sc->mii_bus->phy_map[i];
+		if (phy_dev)
+			break;
+	}
+	if (!phy_dev) {
+		printk(KERN_ERR "%s: no PHY found\n", dev->name);
+		return -ENXIO;
+	}
+
+	phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), &umal_miipoll, 0,
+			      PHY_INTERFACE_MODE_MII);
+	if (IS_ERR(phy_dev)) {
+		printk(KERN_ERR "%s: could not attach to PHY\n", dev->name);
+		return PTR_ERR(phy_dev);
+	}
+
+	/* Remove any features not supported by the controller */
+	phy_dev->supported &= SUPPORTED_10baseT_Half |
+			      SUPPORTED_10baseT_Full |
+			      SUPPORTED_100baseT_Half |
+			      SUPPORTED_100baseT_Full |
+			      SUPPORTED_Autoneg |
+			      SUPPORTED_MII;
+	phy_dev->advertising = phy_dev->supported;
+
+	pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+		dev->name, phy_dev->drv->name,
+		dev_name(&phy_dev->dev), phy_dev->irq);
+
+	sc->phy_dev = phy_dev;
+
+	return 0;
+}
+
+/**********************************************************************
+ *  UMAL DMA functions
+ ********************************************************************* */
+
+/**********************************************************************
+ *  UMALDMA_INITCTX(d,s,txrx,maxdescr)
+ *
+ *  Initialize a DMA channel context.  Since there are potentially
+ *  eight DMA channels per MAC, it's nice to do this in a standard
+ *  way.
+ *
+ *  Input parameters:
+ *	   d - struct umaldma (DMA channel context)
+ *	   s - struct umal_softc (pointer to a MAC)
+ *	   txrx - Identifies DMA_TX or DMA_RX for channel direction
+ *	   maxdescr - number of descriptors
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umaldma_initctx(struct umaldma *d, struct umal_softc *s, int rxtx,
+		int maxdescr)
+{
+	struct umaldmadscr *dscr_item;
+	int idx;
+
+	/*
+	 * Save away interesting stuff in the structure
+	 */
+
+	d->umaldma_eth   = s;
+	d->umaldma_txdir = rxtx;
+	d->umaldma_maxdescr = maxdescr;
+
+	/*
+	 * Allocate memory for the ring
+	 */
+
+	d->umaldma_dscrtable_unaligned = dma_alloc_coherent(NULL,
+					sizeof(*d->umaldma_dscrtable),
+					&d->umaldma_dscrtable_phys_unaligned,
+					GFP_KERNEL | GFP_DMA);
+
+	dma_cache_sync(NULL, d->umaldma_dscrtable_unaligned,
+			sizeof(*d->umaldma_dscrtable), DMA_BIDIRECTIONAL);
+
+	/*
+	 * The descriptor table must be aligned to at least 16 bytes or the
+	 * MAC will corrupt it.
+	 */
+
+	d->umaldma_dscrtable = (struct umaldmadscr *)
+			ALIGN((unsigned long)d->umaldma_dscrtable_unaligned,
+			sizeof(*d->umaldma_dscrtable));
+
+	d->umaldma_dscrtable_end = d->umaldma_dscrtable + d->umaldma_maxdescr;
+
+	d->umaldma_dscrtable_phys = ALIGN((unsigned long)
+				d->umaldma_dscrtable_phys_unaligned,
+				sizeof(*d->umaldma_dscrtable));
+
+	for (idx = 0; idx < d->umaldma_maxdescr; idx++) {
+		dscr_item                      = d->umaldma_dscrtable + idx;
+		dscr_item->PacketStartAddr     = 0;
+		dscr_item->PacketSize          = UMAL_DESC_PACKETSIZE_EMPTY;
+		dscr_item->NextDescriptor      = (dma_addr_t)(
+				(struct umaldmadscr *)d->umaldma_dscrtable_phys
+				+ (idx+1));
+		dscr_item->NextDescriptor_Virt = d->umaldma_dscrtable + (idx+1);
+	}
+	dscr_item                      = d->umaldma_dscrtable +
+					(d->umaldma_maxdescr - 1);
+	dscr_item->NextDescriptor      = d->umaldma_dscrtable_phys;
+	dscr_item->NextDescriptor_Virt = d->umaldma_dscrtable;
+
+	d->umaldma_addptr = d->umaldma_dscrtable;
+	d->umaldma_remptr = d->umaldma_dscrtable;
+
+	/*
+	 * And context table
+	 */
+
+	d->umaldma_ctxtable = kcalloc(d->umaldma_maxdescr,
+				    sizeof(*d->umaldma_ctxtable), GFP_KERNEL);
+}
+
+/**********************************************************************
+ *  UMALDMA_UNINITCTX(d)
+ *
+ *  Uninitialize a DMA channel context.
+ *
+ *  Input parameters:
+ *	   d - struct umaldma (DMA channel context)
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umaldma_uninitctx(struct umaldma *d)
+{
+	if (d->umaldma_dscrtable_unaligned) {
+		dma_free_coherent(NULL,
+				sizeof(*d->umaldma_dscrtable),
+				d->umaldma_dscrtable_unaligned,
+				d->umaldma_dscrtable_phys_unaligned);
+		d->umaldma_dscrtable_unaligned = d->umaldma_dscrtable = NULL;
+		d->umaldma_dscrtable_phys_unaligned = 0;
+		d->umaldma_dscrtable_phys = 0;
+	}
+
+	kfree(d->umaldma_ctxtable);
+	d->umaldma_ctxtable = NULL;
+}
+
+/**********************************************************************
+ *  UMALDMA_CHANNEL_START(d)
+ *
+ *  Open a DMA channel.
+ *
+ *  Input parameters:
+ *	   d - DMA channel to init (context must be previously init'd)
+ *	   rxtx - DMA_RX or DMA_TX depending on what type of channel
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umaldma_channel_start(struct umaldma *d, int rxtx)
+{
+	/*
+	 * Turn on the DMA channel
+	 */
+
+	if (rxtx == DMA_TX) {
+		UMAL_DMATxDescriptor = d->umaldma_dscrtable_phys;
+		UMAL_DMATxCtrl       = UMAL_DMA_Enable;
+	} else {
+		UMAL_DMARxDescriptor = d->umaldma_dscrtable_phys;
+		UMAL_DMARxCtrl       = UMAL_DMA_Enable;
+	}
+}
+
+/**********************************************************************
+ *  UMALDMA_CHANNEL_STOP(d)
+ *
+ *  Close DMA channel.
+ *
+ *  Input parameters:
+ *	   d - DMA channel to init (context must be previously init'd
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umaldma_channel_stop(struct umaldma *d)
+{
+	/*
+	 * Turn off the DMA channel
+	 */
+
+	if (d->umaldma_txdir == DMA_TX) {
+		UMAL_DMATxCtrl       = 0;
+		UMAL_DMATxDescriptor = 0;
+	} else {
+		UMAL_DMARxCtrl       = 0;
+		UMAL_DMARxDescriptor = 0;
+	}
+
+	/*
+	 * Zero ring pointers
+	 */
+
+	d->umaldma_addptr = d->umaldma_dscrtable;
+	d->umaldma_remptr = d->umaldma_dscrtable;
+}
+
+/**********************************************************************
+ *  UMALDMA_ADD_RCVBUFFER(d,sb)
+ *
+ *  Add a buffer to the specified DMA channel.
+ *  For receive channels, this queues a buffer for inbound packets.
+ *
+ *  Input parameters:
+ *	   sc - softc structure
+ *	    d - DMA channel descriptor
+ *	   sb - sk_buff to add, or NULL if we should allocate one
+ *
+ *  Return value:
+ *	   0 if buffer could not be added (ring is full)
+ *	   1 if buffer added successfully
+ ********************************************************************* */
+static int umaldma_add_rcvbuffer(struct umal_softc *sc, struct umaldma *d,
+		struct sk_buff *sb)
+{
+	struct net_device *dev = sc->umal_dev;
+	struct umaldmadscr *dsc;
+	struct umaldmadscr *nextdsc;
+	struct sk_buff *sb_new = NULL;
+
+	/* get pointer to our current place in the ring */
+
+	dsc = d->umaldma_addptr;
+	nextdsc = UMALDMA_NEXTBUF(d, umaldma_addptr);
+
+	/*
+	 * figure out if the ring is full - if the next descriptor
+	 * is the same as the one that we're going to remove from
+	 * the ring, the ring is full
+	 */
+
+	if (nextdsc == d->umaldma_remptr)
+		return -ENOSPC;
+
+	/*
+	 * Allocate a sk_buff if we don't already have one.
+	 * If we do have an sk_buff, reset it so that it's empty.
+	 *
+	 * Note: sk_buffs don't seem to be guaranteed to have any sort
+	 * of alignment when they are allocated.  Therefore, allocate enough
+	 * extra space to make sure that:
+	 *
+	 *    1. the data does not start in the middle of a cache line.
+	 *    2. The data does not end in the middle of a cache line
+	 *    3. The buffer can be aligned such that the IP addresses are
+	 *       naturally aligned.
+	 *
+	 *  Remember, the SOCs MAC writes whole cache lines at a time,
+	 *  without reading the old contents first.  So, if the sk_buff's
+	 *  data portion starts in the middle of a cache line, the SOC
+	 *  DMA will trash the beginning (and ending) portions.
+	 */
+
+	if (sb == NULL) {
+		sb_new = netdev_alloc_skb(dev, ENET_PACKET_SIZE +
+					       SMP_CACHE_BYTES * 2 +
+					       NET_IP_ALIGN);
+		if (sb_new == NULL) {
+			pr_info("%s: sk_buff allocation failed\n",
+			       d->umaldma_eth->umal_dev->name);
+			return -ENOBUFS;
+		}
+		skb_reserve(sb_new, 2);
+	} else {
+		sb_new = sb;
+		/*
+		 * nothing special to reinit buffer, it's already aligned
+		 * and sb->data already points to a good place.
+		 */
+	}
+
+	/*
+	 * fill in the descriptor
+	 */
+
+	dsc->PacketStartAddr = virt_to_phys(sb_new->data);
+	dsc->PacketSize      = UMAL_DESC_PACKETSIZE_EMPTY;
+
+	/*
+	 * fill in the context
+	 */
+
+	d->umaldma_ctxtable[dsc-d->umaldma_dscrtable] = sb_new;
+
+	/*
+	 * point at next packet
+	 */
+
+	d->umaldma_addptr = nextdsc;
+
+	return 0;					/* we did it */
+}
+
+/**********************************************************************
+ *  UMALDMA_ADD_TXBUFFER(d,sb)
+ *
+ *  Add a transmit buffer to the specified DMA channel, causing a
+ *  transmit to start.
+ *
+ *  Input parameters:
+ *	   d - DMA channel descriptor
+ *	   sb - sk_buff to add
+ *
+ *  Return value:
+ *	   0 transmit queued successfully
+ *	   otherwise error code
+ ********************************************************************* */
+static int umaldma_add_txbuffer(struct umaldma *d, struct sk_buff *sb)
+{
+	struct umaldmadscr *dsc;
+	struct umaldmadscr *nextdsc;
+
+	/* get pointer to our current place in the ring */
+
+	dsc = d->umaldma_addptr;
+	nextdsc = UMALDMA_NEXTBUF(d, umaldma_addptr);
+
+	/*
+	 * figure out if the ring is full - if the next descriptor
+	 * is the same as the one that we're going to remove from
+	 * the ring, the ring is full
+	 */
+	if (nextdsc == d->umaldma_remptr)
+		return -ENOSPC;
+
+	/*
+	 * fill in the descriptor.  Note that the number of cache
+	 * blocks in the descriptor is the number of blocks
+	 * *spanned*, so we need to add in the offset (if any)
+	 * while doing the calculation.
+	 */
+	dsc->PacketStartAddr = virt_to_phys(sb->data);
+	dsc->PacketSize      = sb->len | UMAL_DESC_PACKETSIZE_NONEMPTY;
+
+	dma_map_single(NULL, sb->data, sb->len, DMA_BIDIRECTIONAL);
+	dma_cache_sync(NULL, sb->data, sb->len, DMA_BIDIRECTIONAL);
+
+	/*
+	 * fill in the context
+	 */
+	d->umaldma_ctxtable[dsc-d->umaldma_dscrtable] = sb;
+
+	/*
+	 * point at next packet
+	 */
+	d->umaldma_addptr = nextdsc;
+
+	return 0;					/* we did it */
+}
+
+/**********************************************************************
+ *  UMALDMA_EMPTYRING(d)
+ *
+ *  Free all allocated sk_buffs on the specified DMA channel;
+ *
+ *  Input parameters:
+ *	   d  - DMA channel
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umaldma_emptyring(struct umaldma *d)
+{
+	int idx;
+	struct sk_buff *sb;
+
+	for (idx = 0; idx < d->umaldma_maxdescr; idx++) {
+		sb = d->umaldma_ctxtable[idx];
+		if (sb) {
+			dev_kfree_skb(sb);
+			d->umaldma_ctxtable[idx] = NULL;
+		}
+	}
+}
+
+/**********************************************************************
+ *  UMALDMA_FILLRING(sc,d)
+ *
+ *  Fill the specified DMA channel (must be receive channel)
+ *  with sk_buffs
+ *
+ *  Input parameters:
+ *	   sc - softc structure
+ *	    d - DMA channel
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umaldma_fillring(struct umal_softc *sc, struct umaldma *d)
+{
+	int idx;
+	for (idx = 0; idx < UMAL_MAX_RXDESCR - 1; idx++) {
+		if (umaldma_add_rcvbuffer(sc, d, NULL) != 0)
+			break;
+	}
+}
+
+/**********************************************************************
+ *  UMALDMA_RX_PROCESS(sc,d,work_to_do,poll)
+ *
+ *  Process "completed" receive buffers on the specified DMA channel.
+ *
+ *  Input parameters:
+ *            sc - softc structure
+ *	       d - DMA channel context
+ *    work_to_do - no. of packets to process before enabling interrupt
+ *                 again (for NAPI)
+ *          poll - 1: using polling (for NAPI)
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static int umaldma_rx_process(struct umal_softc *sc, struct umaldma *d,
+		int work_to_do, int poll)
+{
+	struct net_device *dev = sc->umal_dev;
+	int curidx;
+	int hwidx;
+	struct umaldmadscr *dsc;
+	struct sk_buff *sb;
+	int len;
+	int work_done = 0;
+	int dropped = 0;
+	unsigned int int_status;
+
+	if (!netif_device_present(dev))
+		return 0;
+
+	int_status = UMAL_DMAInterrupt;
+
+	if (int_status & INT_RX_BUS_ERR) {
+		UMAL_DMARxStatus = CLR_RX_BUS_ERR;
+		UMAL_DMARxCtrl |= UMAL_DMA_Enable;
+	}
+
+	if (int_status & INT_RX_OVERFLOW) {
+		UMAL_DMARxStatus = CLR_RX_OVERFLOW;
+		UMAL_DMARxCtrl |= UMAL_DMA_Enable;
+	}
+
+	if (int_status & INT_RX_PKT) {
+		while (work_to_do-- > 0) {
+
+			/*
+			 * figure out where we are (as an index) and where
+			 * the hardware is (also as an index)
+			 *
+			 * This could be done faster if (for example) the
+			 * descriptor table was page-aligned and contiguous in
+			 * both virtual and physical memory -- you could then
+			 * just compare the low-order bits of the virtual
+			 * address (sbdma_remptr) and the physical address
+			 * (sbdma_curdscr CSR)
+			 */
+
+			dsc = d->umaldma_remptr;
+			curidx = dsc - d->umaldma_dscrtable;
+
+			hwidx = (struct umaldmadscr *)UMAL_DMARxDescriptor -
+				(struct umaldmadscr *)d->umaldma_dscrtable_phys;
+
+			UMAL_DMARxStatus = CLR_RX_PKT;
+
+			/*
+			 * If they're the same, that means we've processed all
+			 * of the descriptors up to (but not including) the one
+			 * that the hardware is working on right now.
+			 */
+			if (curidx == hwidx)
+				goto done;
+
+			/*
+			 * Otherwise, get the packet's sk_buff ptr back
+			 */
+			sb = d->umaldma_ctxtable[curidx];
+			len = dsc->PacketSize & 0xfff;
+			d->umaldma_ctxtable[curidx] = NULL;
+
+			/*
+			 * .. and advance to the next buffer.
+			 */
+			d->umaldma_remptr = UMALDMA_NEXTBUF(d, umaldma_remptr);
+
+			/*
+			 * Check packet status.  If good, process it.
+			 * If not, silently drop it and put it back on the
+			 * receive ring.
+			 */
+			if (likely(!(dsc->PacketSize &
+					UMAL_DESC_PACKETSIZE_EMPTY))) {
+				/*
+				 * Add a new buffer to replace the old one.
+				 * If we fail to allocate a buffer, we're going
+				 * to drop this packet and put it right back on
+				 * the receive ring.
+				 */
+				if (unlikely(umaldma_add_rcvbuffer(sc, d, NULL)
+						== -ENOBUFS)) {
+					dev->stats.rx_dropped++;
+					/* Re-add old buffer */
+					umaldma_add_rcvbuffer(sc, d, sb);
+					/* No point in continuing */
+					printk(KERN_ERR "dropped packet (1)\n");
+					d->umaldma_remptr = UMALDMA_NEXTBUF(d,
+							umaldma_remptr);
+					goto done;
+				} else {
+					/*
+					 * Set length into the packet
+					 */
+					skb_put(sb, len + 4);
+
+					/*
+					 * Buffer has been replaced on the
+					 * receive ring.  Pass the buffer to
+					 * the kernel
+					 */
+					sb->protocol = eth_type_trans(sb,
+						d->umaldma_eth->umal_dev);
+					/*
+					 * Check hw IPv4/TCP checksum
+					 * if supported
+					 */
+					skb_checksum_none_assert(sb);
+
+					if (poll)
+						dropped = netif_receive_skb(sb);
+					else
+						dropped = netif_rx(sb);
+
+					if (dropped == NET_RX_DROP) {
+						dev->stats.rx_dropped++;
+						d->umaldma_remptr =
+							UMALDMA_NEXTBUF(d,
+								umaldma_remptr);
+						goto done;
+					} else {
+						dev->stats.rx_bytes += len;
+						dev->stats.rx_packets++;
+					}
+				}
+			} else {
+				/*
+				 * Packet was mangled somehow.  Just drop it and
+				 * put it back on the receive ring.
+				 */
+				dev->stats.rx_errors++;
+				umaldma_add_rcvbuffer(sc, d, sb);
+			}
+			work_done++;
+		}
+	}
+done:
+	return work_done;
+}
+
+/**********************************************************************
+ *  UMALDMA_TX_PROCESS(sc,d,poll)
+ *
+ *  Process "completed" transmit buffers on the specified DMA channel.
+ *  This is normally called within the interrupt service routine.
+ *  Note that this isn't really ideal for priority channels, since
+ *  it processes all of the packets on a given channel before
+ *  returning.
+ *
+ *  Input parameters:
+ *      sc - softc structure
+ *	 d - DMA channel context
+ *    poll - 1: using polling (for NAPI)
+ *
+ *  Return value:
+ *	   nothing
+ **********************************************************************/
+static void umaldma_tx_process(struct umal_softc *sc, struct umaldma *d,
+		int poll)
+{
+	struct net_device *dev = sc->umal_dev;
+	int curidx;
+	int hwidx;
+	struct umaldmadscr *dsc;
+	struct sk_buff *sb;
+	unsigned long flags;
+	int packets_handled = 0;
+	unsigned int int_status;
+
+	spin_lock_irqsave(&(sc->umal_lock), flags);
+
+	if (!netif_device_present(dev))
+		return;
+
+	int_status = UMAL_DMAInterrupt;
+
+
+	if (int_status & INT_TX_BUS_ERR)
+		UMAL_DMATxStatus = CLR_TX_BUS_ERR;
+
+	if (int_status & INT_TX_UNDERRUN)
+		UMAL_DMATxStatus = CLR_TX_UNDERRUN;
+
+	if (int_status & INT_TX_PKT) {
+		hwidx = (struct umaldmadscr *)UMAL_DMATxDescriptor -
+			(struct umaldmadscr *)d->umaldma_dscrtable_phys;
+
+		if (d->umaldma_remptr == d->umaldma_addptr)
+			goto end_unlock;
+
+		for (;;) {
+			/*
+			 * figure out where we are (as an index) and where
+			 * the hardware is (also as an index)
+			 *
+			 * This could be done faster if (for example) the
+			 * descriptor table was page-aligned and contiguous in
+			 * both virtual and physical memory -- you could then
+			 * just compare the low-order bits of the virtual
+			 * address (sbdma_remptr) and the physical address
+			 * (sbdma_curdscr CSR)
+			 */
+			curidx = d->umaldma_remptr - d->umaldma_dscrtable;
+
+			/*
+			 * If they're the same, that means we've processed all
+			 * of the descriptors up to (but not including) the one
+			 * that the hardware is working on right now.
+			 */
+			if (curidx == hwidx)
+				break;
+
+			/*
+			 * Otherwise, get the packet's sk_buff ptr back
+			 */
+			dsc = &(d->umaldma_dscrtable[curidx]);
+			sb = d->umaldma_ctxtable[curidx];
+
+			/*
+			 * Stats
+			 */
+			dev->stats.tx_bytes += sb->len;
+			dev->stats.tx_packets++;
+
+			/*
+			 * for transmits, we just free buffers.
+			 */
+			dev_kfree_skb_irq(sb);
+			d->umaldma_ctxtable[curidx] = NULL;
+			UMAL_DMATxStatus = CLR_TX_PKT;
+
+			/*
+			 * .. and advance to the next buffer.
+			 */
+			d->umaldma_remptr = UMALDMA_NEXTBUF(d, umaldma_remptr);
+			packets_handled++;
+		}
+
+		/*
+		 * Decide if we should wake up the protocol or not.
+		 * Other drivers seem to do this when we reach a low
+		 * watermark on the transmit queue.
+		 */
+		if (packets_handled)
+			netif_wake_queue(d->umaldma_eth->umal_dev);
+	}
+
+end_unlock:
+	spin_unlock_irqrestore(&(sc->umal_lock), flags);
+}
+
+/**********************************************************************
+ *  UMAL Channel functions
+ ********************************************************************* */
+
+/**********************************************************************
+ *  UMAL_INITCTX(s)
+ *
+ *  Initialize an Ethernet context structure - this is called
+ *  once per MAC. Memory is allocated here, so don't
+ *  call it again from inside the ioctl routines that bring the
+ *  interface up/down
+ *
+ *  Input parameters:
+ *	   s - umal context structure
+ *
+ *  Return value:
+ *	   0
+ ********************************************************************* */
+static int umal_initctx(struct umal_softc *s)
+{
+	/*
+	 * Initialize the DMA channels.
+	 * Note: Only do this _once_, as it allocates memory from the kernel!
+	 */
+
+	umaldma_initctx(&(s->umal_txdma), s, DMA_TX, UMAL_MAX_TXDESCR);
+	umaldma_initctx(&(s->umal_rxdma), s, DMA_RX, UMAL_MAX_RXDESCR);
+
+	/*
+	 * initial state is OFF
+	 */
+
+	s->umal_state = umal_state_off;
+
+	return 0;
+}
+
+/**********************************************************************
+ *  UMAL_UNINITCTX(s)
+ *
+ *  Initialize an Ethernet context structure - this is called
+ *  once per MAC on the 1250.  Memory is allocated here, so don't
+ *  call it again from inside the ioctl routines that bring the
+ *  interface up/down
+ *
+ *  Input parameters:
+ *	   s - umal context structure
+ *
+ *  Return value:
+ *	   Nothing
+ ********************************************************************* */
+static void umal_uninitctx(struct umal_softc *s)
+{
+	umaldma_uninitctx(&(s->umal_txdma));
+	umaldma_uninitctx(&(s->umal_rxdma));
+}
+
+/**********************************************************************
+ *  UMAL_CHANNEL_START(s)
+ *
+ *  Start packet processing on this MAC.
+ *
+ *  Input parameters:
+ *	   s - umal context structure
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umal_channel_start(struct umal_softc *s)
+{
+	/*
+	 * Don't do this if running
+	 */
+	if (s->umal_state == umal_state_on)
+		return;
+
+	/* don't accept any packets, disable all interrupts */
+	umaldma_channel_stop(&(s->umal_rxdma));
+	umaldma_channel_stop(&(s->umal_txdma));
+
+	UMAL_DMAIntrMask = 0;
+	umal_clr_intr(s->umal_dev);
+
+	/*
+	 * Program the hardware address.  It goes into the hardware-address
+	 * register as well as the first filter register.
+	 */
+	UMAL_STADDR1 = s->umal_hwaddr[0]<<24 |  s->umal_hwaddr[1]<<16 |
+			s->umal_hwaddr[2]<<8 | s->umal_hwaddr[3];
+	UMAL_STADDR2 = s->umal_hwaddr[4]<<24 |  s->umal_hwaddr[5]<<16;
+
+	/*
+	 * Configure the speed, duplex, and flow control
+	 */
+	umal_set_speed(s, s->umal_speed);
+	umal_set_duplex(s, s->umal_duplex, s->umal_fc);
+
+	/*
+	 * Program multicast addresses
+	 */
+	umal_setmulti(s);
+
+	/*
+	 * If channel was in promiscuous mode before, turn that on
+	 */
+	if (s->umal_devflags & IFF_PROMISC)
+		umal_promiscuous_mode(s, 1);
+
+	/*
+	 * Fill the receive ring
+	 */
+	umaldma_fillring(s, &(s->umal_rxdma));
+
+	umaldma_channel_start(&(s->umal_rxdma), DMA_RX);
+	umaldma_channel_start(&(s->umal_txdma), DMA_TX);
+
+	s->umal_state = umal_state_on;
+
+	/*
+	 * Initialize DMA channels (rings should be ok now)
+	 */
+	UMAL_DMAIntrMask = INT_RX_BUS_ERR | INT_RX_OVERFLOW |
+			INT_RX_PKT        | INT_TX_BUS_ERR |
+			INT_TX_UNDERRUN   | INT_TX_PKT |
+			UMAL_DMAIntrMask_ENABLEHALFWORD;
+
+	/*
+	 * we're running now.
+	 */
+	UMAL_CFG1 |= UMAL_CFG1_RXENABLE | UMAL_CFG1_TXENABLE;
+}
+
+/**********************************************************************
+ *  UMAL_CHANNEL_STOP(s)
+ *
+ *  Stop packet processing on this MAC.
+ *
+ *  Input parameters:
+ *	   s - umal context structure
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umal_channel_stop(struct umal_softc *s)
+{
+	/* don't do this if already stopped */
+	if (s->umal_state == umal_state_off)
+		return;
+
+	/* don't accept any packets, disable all interrupts */
+	UMAL_DMAIntrMask = 0;
+	umal_clr_intr(s->umal_dev);
+
+	/* turn off receiver and transmitter */
+	UMAL_CFG1 = UMAL_CFG1_RESET;		/* reset MAC */
+	UMAL_CFG1 = 0;
+
+	/* We're stopped now. */
+	s->umal_state = umal_state_off;
+
+	/*
+	 * Stop DMA channels (rings should be ok now)
+	 */
+	umaldma_channel_stop(&(s->umal_rxdma));
+	umaldma_channel_stop(&(s->umal_txdma));
+
+	/* Empty the receive and transmit rings */
+	umaldma_emptyring(&(s->umal_rxdma));
+	umaldma_emptyring(&(s->umal_txdma));
+}
+
+/**********************************************************************
+ *  UMAL_SET_CHANNEL_STATE(s,state)
+ *
+ *  Set the channel's state ON or OFF
+ *
+ *  Input parameters:
+ *	   s - umal context structure
+ *	   state - new state
+ *
+ *  Return value:
+ *	   old state
+ ********************************************************************* */
+static enum umal_state umal_set_channel_state(struct umal_softc *s,
+		enum umal_state state)
+{
+	enum umal_state oldstate = s->umal_state;
+
+	/*
+	 * If same as previous state, return
+	 */
+	if (state == oldstate)
+		return oldstate;
+
+	/*
+	 * If new state is ON, turn channel on
+	 */
+	if (state == umal_state_on)
+		umal_channel_start(s);
+	else
+		umal_channel_stop(s);
+
+	/*
+	 * Return previous state
+	 */
+	return oldstate;
+}
+
+/**********************************************************************
+ *  UMAL functions
+ ********************************************************************* */
+static const struct net_device_ops umal_netdev_ops = {
+	.ndo_open		= umal_open,
+	.ndo_stop		= umal_close,
+	.ndo_start_xmit		= umal_start_tx,
+	.ndo_set_multicast_list	= umal_set_rx_mode,
+	.ndo_tx_timeout		= umal_tx_timeout,
+	.ndo_do_ioctl		= umal_mii_ioctl,
+	.ndo_change_mtu		= umal_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
+/**********************************************************************
+ *  UMAL_INIT(dev)
+ *
+ *  Attach routine - init hardware and hook ourselves into linux
+ *
+ *  Input parameters:
+ *	   dev - net_device structure
+ *
+ *  Return value:
+ *	   0 if ok
+ ********************************************************************* */
+static int umal_init(struct platform_device *pldev, long long base)
+{
+	struct net_device *dev = dev_get_drvdata(&pldev->dev);
+	int idx = pldev->id;
+	struct umal_softc *sc = netdev_priv(dev);
+	unsigned char *eaddr;
+	int i;
+	int err;
+
+	sc->umal_dev = dev;
+	sc->umal_idx = idx;
+
+	eaddr = sc->umal_hwaddr;
+#ifdef CONFIG_CMDLINE_FORCE
+	for (i = 0; i < 6; i++)
+		eaddr[i] = hw_addr[0].addr[i];
+#endif
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = eaddr[i];
+
+	/*
+	 * Set up Linux device callins
+	 */
+
+	spin_lock_init(&(sc->umal_lock));
+
+	dev->netdev_ops = &umal_netdev_ops;
+	dev->watchdog_timeo = TX_TIMEOUT;
+
+	dev->irq		= IRQ_UMAL;
+
+	sc->mii_bus = mdiobus_alloc();
+	if (sc->mii_bus == NULL) {
+		err = -ENOMEM;
+		goto uninit_ctx;
+	}
+
+	sc->mii_bus->name = umal_mdio_string;
+	snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx);
+	sc->mii_bus->priv = sc;
+	sc->mii_bus->read = umal_mii_read;
+	sc->mii_bus->write = umal_mii_write;
+	sc->mii_bus->reset = umal_mii_reset;
+	sc->mii_bus->irq = sc->phy_irq;
+	for (i = 0; i < PHY_MAX_ADDR; ++i)
+		sc->mii_bus->irq[i] = PHY_POLL;
+
+	sc->mii_bus->parent = &pldev->dev;
+
+	/*
+	 * Probe PHY address
+	 */
+	err = mdiobus_register(sc->mii_bus);
+	if (err) {
+		printk(KERN_ERR "%s: unable to register MDIO bus\n",
+		       dev->name);
+		goto free_mdio;
+	}
+	dev_set_drvdata(&pldev->dev, sc->mii_bus);
+
+	err = register_netdev(dev);
+	if (err) {
+		printk(KERN_ERR "%s.%d: unable to register netdev\n",
+		       umal_string, idx);
+		goto unreg_mdio;
+	}
+
+	pr_info("%s.%d: registered as %s\n", umal_string, idx, dev->name);
+
+	/*
+	 * Initialize context (get pointers to registers and stuff), then
+	 * allocate the memory for the descriptor tables.
+	 */
+	dev->dev.coherent_dma_mask = 0xFFFFFFFF;
+	umal_initctx(sc);
+
+	/*
+	 * Display Ethernet address (this is called during the config
+	 * process so we need to finish off the config message that
+	 * was being displayed)
+	 */
+	pr_info("%s: UMAL Ethernet at 0x%08Lx, address: %pM\n",
+	       dev->name, base, eaddr);
+
+	return 0;
+unreg_mdio:
+	mdiobus_unregister(sc->mii_bus);
+	dev_set_drvdata(&pldev->dev, NULL);
+free_mdio:
+	mdiobus_free(sc->mii_bus);
+uninit_ctx:
+	umal_uninitctx(sc);
+	return err;
+}
+
+/**********************************************************************
+ *  UMAL_OPEN(dev)
+ *
+ *  Open umal device
+ *
+ *  Input parameters:
+ *	   dev - net_device structure
+ *
+ *  Return value:
+ *	   0 if ok
+ *	   otherwise error
+ ********************************************************************* */
+static int umal_open(struct net_device *dev)
+{
+	struct umal_softc *sc = netdev_priv(dev);
+	int err;
+
+	sc->umal_speed = umal_speed_none;
+	sc->umal_duplex = umal_duplex_none;
+	sc->umal_fc = umal_fc_none;
+	sc->umal_pause = -1;
+	sc->umal_link = 0;
+
+	/* reset mac and interface */
+	UMAL_CFG1 = UMAL_CFG1_RESET;		/* reset MAC */
+	UMAL_CFG1 = 0;				/* clear the reset bit of MAC */
+	UMAL_IFCTRL = UMAL_IFCTRL_RESET;	/* reset the MAC Interface */
+	UMAL_DMAIntrMask = 0;
+
+	/*
+	 * Attach to the PHY
+	 */
+	err = umal_mii_probe(dev);
+	if (err)
+		goto out_unregister;
+
+	/*
+	 * Turn on the channel
+	 */
+	phy_start(sc->phy_dev);
+
+	/* config fifo */
+	UMAL_FIFOCFG0 = 0x000000ff;	/* reset FIFO */
+	UMAL_FIFOCFG1 = 0x0fff0fff;	/* request enable modules in fifo */
+	UMAL_FIFOCFG2 = 0x0aaa0555;	/* request enable modules in fifo */
+	UMAL_FIFOCFG3 = 0x02800fff;	/* set water mark register */
+	UMAL_FIFOCFG4 = 0x00000070;
+	UMAL_FIFOCFG5 = 0x0007ff8f;
+	UMAL_FIFOCFG0 = 0x0000ff00;	/* request enable modules in fifo */
+
+	UMAL_CFG2 = 0x7016;
+
+	/*
+	 * map/route interrupt (clear status first, in case something
+	 * weird is pending; we haven't initialized the mac registers
+	 * yet)
+	 */
+	umal_clr_intr(dev);
+
+	err = request_irq(dev->irq, umal_intr, IRQF_SHARED, dev->name, dev);
+	if (err) {
+		printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name,
+		       dev->irq);
+		goto out_err;
+	}
+
+	umal_set_channel_state(sc, umal_state_on);
+
+	netif_start_queue(dev);
+
+	umal_set_rx_mode(dev);
+
+	return 0;
+
+out_unregister:
+	free_irq(dev->irq, dev);
+out_err:
+	return err;
+}
+
+/**********************************************************************
+ *  UMAL_CLSOE(dev)
+ *
+ *  Close umal device
+ *
+ *  Input parameters:
+ *	   dev - net_device structure
+ *
+ *  Return value:
+ *	   0 if ok
+ ********************************************************************* */
+static int umal_close(struct net_device *dev)
+{
+	struct umal_softc *sc = netdev_priv(dev);
+
+	phy_stop(sc->phy_dev);
+
+	umal_set_channel_state(sc, umal_state_off);
+
+	netif_stop_queue(dev);
+
+	phy_disconnect(sc->phy_dev);
+	sc->phy_dev = NULL;
+
+	free_irq(dev->irq, dev);
+
+	umaldma_emptyring(&(sc->umal_rxdma));
+	umaldma_emptyring(&(sc->umal_txdma));
+
+	return 0;
+}
+
+/**********************************************************************
+ *  UMAL_MII_IOCTL(dev,rq,cmd)
+ *
+ *  Umal device ioctrl routine
+ *
+ *  Input parameters:
+ *	   dev - net_device structure
+ *	   rq  - interface request structure
+ *	   cmd - ioctrl command
+ *
+ *  Return value:
+ *	   ioctrl command result
+ ********************************************************************* */
+static int umal_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct umal_softc *sc = netdev_priv(dev);
+
+	if (!netif_running(dev) || !sc->phy_dev)
+		return -EINVAL;
+
+	return phy_mii_ioctl(sc->phy_dev, rq, cmd);
+}
+
+/**********************************************************************
+ *  UMAL_INTR(irq,dev_instance)
+ *
+ *  Interrupt handler for MAC interrupts
+ *
+ *  Input parameters:
+ *	   irq - irq number
+ *	   dev_instance - net_device structure
+ *
+ *  Return value:
+ *	   irq handling result
+ ********************************************************************* */
+static irqreturn_t umal_intr(int irq, void *dev_instance)
+{
+	struct net_device *dev = (struct net_device *) dev_instance;
+	struct umal_softc *sc = netdev_priv(dev);
+	uint64_t isr;
+	int handled = 0;
+
+	/*
+	 * Read the ISR (this clears the bits in the real
+	 * register, except for counter addr)
+	 */
+	isr = UMAL_DMAInterrupt;
+	if (isr == 0)
+		return IRQ_RETVAL(0);
+
+	if (sc->umal_state != umal_state_on) {
+		umal_clr_intr(dev);
+		return IRQ_RETVAL(0);
+	}
+	handled = 1;
+
+	/*
+	 * Transmits on channel 0
+	 */
+	if (isr & INT_TX_MASK)
+		umaldma_tx_process(sc, &(sc->umal_txdma), 0);
+	if (isr & INT_RX_MASK)
+		umaldma_rx_process(sc, &(sc->umal_rxdma),
+				 UMAL_MAX_RXDESCR * 2, 0);
+
+	return IRQ_RETVAL(handled);
+}
+
+/**********************************************************************
+ *  UMAL_CLR_INTR(dev)
+ *
+ *  Clear all interrupt of umal
+ *
+ *  Input parameters:
+ *	   dev - net_device structure
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umal_clr_intr(struct net_device *dev)
+{
+	unsigned int int_status;
+
+	if (!netif_device_present(dev))
+		return;
+	int_status = UMAL_DMAInterrupt;
+	if (int_status & INT_RX_PKT)
+		UMAL_DMARxStatus = CLR_RX_PKT;
+
+	if (int_status & INT_RX_BUS_ERR)
+		UMAL_DMARxStatus = CLR_RX_BUS_ERR;
+
+	if (int_status & INT_RX_OVERFLOW)
+		UMAL_DMARxStatus = CLR_RX_OVERFLOW;
+
+	if (int_status & INT_TX_PKT)
+		UMAL_DMATxStatus = CLR_TX_PKT;
+
+	if (int_status & INT_TX_BUS_ERR)
+		UMAL_DMATxStatus = CLR_TX_BUS_ERR;
+
+	if (int_status & INT_TX_UNDERRUN)
+		UMAL_DMATxStatus = CLR_TX_UNDERRUN;
+}
+
+/**********************************************************************
+ *  UMAL_START_TX(skb,dev)
+ *
+ *  Start output on the specified interface.  Basically, we
+ *  queue as many buffers as we can until the ring fills up, or
+ *  we run off the end of the queue, whichever comes first.
+ *
+ *  Input parameters:
+ *	   skb - sk_buff structure
+ *	   dev - net_device structure
+ *
+ *  Return value:
+ *	   0 if ok
+ *	   otherwise error
+ ********************************************************************* */
+static int umal_start_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct umal_softc *sc = netdev_priv(dev);
+	unsigned long flags;
+
+	/* lock eth irq */
+	spin_lock_irqsave(&sc->umal_lock, flags);
+
+	/*
+	 * Put the buffer on the transmit ring.  If we
+	 * don't have room, stop the queue.
+	 */
+	if (umaldma_add_txbuffer(&(sc->umal_txdma), skb)) {
+		/* XXX save skb that we could not send */
+		netif_stop_queue(dev);
+		spin_unlock_irqrestore(&sc->umal_lock, flags);
+
+		return NETDEV_TX_BUSY;
+	}
+
+	UMAL_CFG1 |= UMAL_CFG1_TXENABLE;
+	UMAL_DMATxCtrl |= UMAL_DMA_Enable;
+
+	spin_unlock_irqrestore(&sc->umal_lock, flags);
+
+	return 0;
+}
+
+/**********************************************************************
+ *  UMAL_TX_TIMEOUT(dev)
+ *
+ *  Tx timeout, update statistic structure
+ *
+ *  Input parameters:
+ *	   dev - net_device structure
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umal_tx_timeout(struct net_device *dev)
+{
+	struct umal_softc *sc = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&sc->umal_lock, flags);
+
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	dev->stats.tx_errors++;
+
+	spin_unlock_irqrestore(&sc->umal_lock, flags);
+
+	printk(KERN_WARNING "%s: Transmit timed out\n", dev->name);
+}
+
+/**********************************************************************
+ *  UMAL_SET_RX_MODE(dev)
+ *
+ *  Set promiscuous mode and multicast list
+ *
+ *  Input parameters:
+ *	   dev - net_device structure
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umal_set_rx_mode(struct net_device *dev)
+{
+	unsigned long flags;
+	struct umal_softc *sc = netdev_priv(dev);
+
+	spin_lock_irqsave(&sc->umal_lock, flags);
+	if ((dev->flags ^ sc->umal_devflags) & IFF_PROMISC) {
+		/*
+		 * Promiscuous changed.
+		 */
+		if (dev->flags & IFF_PROMISC)
+			umal_promiscuous_mode(sc, 1);
+		else
+			umal_promiscuous_mode(sc, 0);
+	}
+	spin_unlock_irqrestore(&sc->umal_lock, flags);
+
+	/*
+	 * Program the multicasts.  Do this every time.
+	 */
+	umal_setmulti(sc);
+}
+
+/**********************************************************************
+ *  UMAL_PROMISCUOUS_MODE(sc,onoff)
+ *
+ *  Turn on or off promiscuous mode
+ *
+ *  Input parameters:
+ *	   sc - softc
+ *      onoff - 1 to turn on, 0 to turn off
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umal_promiscuous_mode(struct umal_softc *sc, int onoff)
+{
+	if (onoff) {
+		UMAL_FIFOCFG4 &= ~0x40000;
+		UMAL_FIFOCFG5 |= 0x40000;
+	} else {
+		UMAL_FIFOCFG4 |= 0x40000;
+		UMAL_FIFOCFG5 &= ~0x40000;
+	}
+}
+
+/**********************************************************************
+ *  UMAL_SETMULTI(sc)
+ *
+ *  Reprogram the multicast table into the hardware, given
+ *  the list of multicasts associated with the interface
+ *  structure.
+ *
+ *  Input parameters:
+ *	   sc - softc
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umal_setmulti(struct umal_softc *sc)
+{
+}
+
+/**********************************************************************
+ *  UMAL_SET_SPEED(s,speed)
+ *
+ *  Configure LAN speed for the specified MAC.
+ *  Warning: must be called when MAC is off!
+ *
+ *  Input parameters:
+ *	   s - sbmac structure
+ *	   speed - speed to set MAC to (see enum sbmac_speed)
+ *
+ *  Return value:
+ *	   1 if successful
+ *	   0 indicates invalid parameters
+ ********************************************************************* */
+static int umal_set_speed(struct umal_softc *s, enum umal_speed speed)
+{
+	unsigned int cfg;
+
+	/*
+	 * Save new current values
+	 */
+	s->umal_speed = speed;
+
+	if (s->umal_state == umal_state_on)
+		return 0;	/* save for next restart */
+
+	/*
+	 * Read current register values
+	 */
+	cfg = UMAL_CFG2;
+
+	/*
+	 * Mask out the stuff we want to change
+	 */
+	cfg &= ~(UMAL_CFG2_MODEMASK);
+
+	/*
+	 * Now add in the new bits
+	 */
+	switch (speed) {
+	case umal_speed_10:
+		cfg |= UMAL_CFG2_NIBBLEMODE;
+		break;
+
+	case umal_speed_100:
+		cfg |= UMAL_CFG2_NIBBLEMODE;
+		break;
+
+	default:
+		return 0;
+	}
+
+	/*
+	 * Send the bits back to the hardware
+	 */
+	UMAL_CFG2 = cfg;
+
+	return 1;
+}
+
+/**********************************************************************
+ *  UMAL_SET_DUPLEX(s,duplex,fc)
+ *
+ *  Set Ethernet duplex and flow control options for this MAC
+ *  Warning: must be called when MAC is off!
+ *
+ *  Input parameters:
+ *	   s - umal structure
+ *	   duplex - duplex setting (see enum sbmac_duplex)
+ *	   fc - flow control setting (see enum sbmac_fc)
+ *
+ *  Return value:
+ *	   1 if ok
+ *	   0 if an invalid parameter combination was specified
+ ********************************************************************* */
+static int umal_set_duplex(struct umal_softc *s, enum umal_duplex duplex,
+		enum umal_fc fc)
+{
+	unsigned int cfg1, cfg2;
+	int err = 0;
+
+	/*
+	 * Save new current values
+	 */
+	s->umal_duplex = duplex;
+	s->umal_fc = fc;
+
+	if (s->umal_state == umal_state_on)
+		return 0;	/* save for next restart */
+
+	/*
+	 * Read current register values
+	 */
+	cfg1 = UMAL_CFG1;
+	cfg2 = UMAL_CFG2;
+
+	/*
+	 * Mask off the stuff we're about to change
+	 */
+	cfg1 &= ~(UMAL_CFG1_TXFLOWCTL | UMAL_CFG1_RXFLOWCTL);
+	cfg2 &= ~(UMAL_CFG2_FULLDUPLEX);
+
+	err = 0;
+	switch (duplex) {
+	case umal_duplex_half:
+		break;
+
+	case umal_duplex_full:
+		cfg2 |= UMAL_CFG2_FULLDUPLEX;
+		break;
+
+	default:
+		err = 1;
+	}
+	if (!err)
+		UMAL_CFG2 = cfg2;
+
+	err = 0;
+	switch (fc) {
+	case umal_fc_disabled:
+		break;
+
+	case umal_fc_collision:
+		break;
+
+	case umal_fc_carrier:
+		break;
+
+	case umal_fc_frame:
+		cfg1 |= UMAL_CFG1_TXFLOWCTL | UMAL_CFG1_RXFLOWCTL;
+		break;
+
+	default:
+		err = 1;
+	}
+
+	if (!err)
+		UMAL_CFG1 = cfg1;
+
+	/*
+	 * Send the bits back to the hardware
+	 */
+	return 1;
+}
+
+/**********************************************************************
+ *  UMAL_CHANGE_MTU(dev,new_mtu)
+ *
+ *  Change MTU value
+ *
+ *  Input parameters:
+ *	   dev - net_device structure
+ *	   new_mtu - new mtu value
+ *
+ *  Return value:
+ *	   1 if ok
+ ********************************************************************* */
+static int umal_change_mtu(struct net_device *dev, int new_mtu)
+{
+	if (new_mtu >  ENET_PACKET_SIZE)
+		return -EINVAL;
+
+	dev->mtu = new_mtu;
+
+	pr_info("changing the mtu to %d\n", new_mtu);
+
+	return 0;
+}
+
+/**********************************************************************
+ *  UMAL_MIIPOLL(dev)
+ *
+ *  Phy statemachine call back routine for link change
+ *
+ *  Input parameters:
+ *	   dev - net_device structure
+ *
+ *  Return value:
+ *	   nothing
+ ********************************************************************* */
+static void umal_miipoll(struct net_device *dev)
+{
+	struct umal_softc *sc = netdev_priv(dev);
+	struct phy_device *phy_dev = sc->phy_dev;
+	unsigned long flags;
+	enum umal_fc fc;
+	int link_chg, speed_chg, duplex_chg, pause_chg, fc_chg;
+
+	link_chg = (sc->umal_link != phy_dev->link);
+	speed_chg = (sc->umal_speed != phy_dev->speed);
+	duplex_chg = (sc->umal_duplex != phy_dev->duplex);
+	pause_chg = (sc->umal_pause != phy_dev->pause);
+
+	if (!link_chg && !speed_chg && !duplex_chg && !pause_chg)
+		return;					/* Hmmm... */
+
+	if (!phy_dev->link) {
+		if (link_chg) {
+			sc->umal_link = phy_dev->link;
+			sc->umal_speed = umal_speed_none;
+			sc->umal_duplex = umal_duplex_none;
+			sc->umal_fc = umal_fc_disabled;
+			sc->umal_pause = -1;
+			pr_info("%s: link unavailable\n", dev->name);
+		}
+		return;
+	}
+
+	if (phy_dev->duplex == DUPLEX_FULL) {
+		if (phy_dev->pause)
+			fc = umal_fc_frame;
+		else
+			fc = umal_fc_disabled;
+	} else
+		fc = umal_fc_collision;
+	fc_chg = (sc->umal_fc != fc);
+
+	pr_info("%s: link available: %dbase-%cD\n", dev->name, phy_dev->speed,
+		phy_dev->duplex == DUPLEX_FULL ? 'F' : 'H');
+
+	spin_lock_irqsave(&sc->umal_lock, flags);
+
+	sc->umal_speed = phy_dev->speed;
+	sc->umal_duplex = phy_dev->duplex;
+	sc->umal_fc = fc;
+	sc->umal_pause = phy_dev->pause;
+	sc->umal_link = phy_dev->link;
+
+	if ((speed_chg || duplex_chg || fc_chg) &&
+		sc->umal_state != umal_state_off) {
+		/*
+		 * something changed, restart the channel
+		 */
+		umal_channel_stop(sc);
+		umal_channel_start(sc);
+	}
+
+	spin_unlock_irqrestore(&sc->umal_lock, flags);
+}
+
+static int umal_probe(struct platform_device *pldev)
+{
+	struct net_device *dev;
+	struct umal_softc *sc;
+	struct resource *res;
+	int err;
+
+	res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
+	BUG_ON(!res);
+
+	/*
+	 * Okay, cool.  Initialize this MAC.
+	 */
+	dev = alloc_etherdev(sizeof(struct umal_softc));
+	if (!dev) {
+		printk(KERN_ERR "%s: unable to allocate etherdev\n",
+		       dev_name(&pldev->dev));
+		err = -ENOMEM;
+		goto out_out;
+	}
+
+	dev_set_drvdata(&pldev->dev, dev);
+	SET_NETDEV_DEV(dev, &pldev->dev);
+
+	sc = netdev_priv(dev);
+
+	err = umal_init(pldev, res->start);
+	if (err)
+		goto out_kfree;
+
+	return 0;
+
+out_kfree:
+	free_netdev(dev);
+
+out_out:
+	return err;
+}
+
+static int __exit umal_remove(struct platform_device *pldev)
+{
+	struct net_device *dev = dev_get_drvdata(&pldev->dev);
+	struct umal_softc *sc = netdev_priv(dev);
+
+	unregister_netdev(dev);
+	umal_uninitctx(sc);
+	mdiobus_unregister(sc->mii_bus);
+	free_netdev(dev);
+
+	return 0;
+}
+
+#if CONFIG_PM
+static void umal_reset(struct net_device *ndev)
+{
+	UMAL_CFG1 = UMAL_CFG1_RESET;	/* reset MAC */
+	UMAL_CFG1 = 0;			/* clear the reset bit of MAC */
+	UMAL_IFCTRL = UMAL_IFCTRL_RESET; /* reset the MAC Interface */
+	UMAL_DMAIntrMask = 1;
+
+	UMAL_FIFOCFG0 = 0x000000ff;	/* reset FIFO */
+	UMAL_FIFOCFG1 = 0x0fff0fff;	/* request enable modules in fifo */
+	UMAL_FIFOCFG2 = 0x0aaa0555;	/* request enable modules in fifo */
+	UMAL_FIFOCFG3 = 0x02800fff;	/* set water mark register */
+	UMAL_FIFOCFG4 = 0x00000070;
+	UMAL_FIFOCFG5 = 0x0007ff8f;
+	UMAL_FIFOCFG0 = 0x0000ff00;	/* request enable modules in fifo */
+
+	UMAL_CFG2 = 0x7016;
+}
+
+static void umal_shutdown(struct net_device *ndev)
+{
+	/* not implemented*/
+	return;
+}
+
+static int umal_suspend(struct platform_device *pldev, pm_message_t state)
+{
+	struct net_device *ndev = platform_get_drvdata(pldev);
+
+	if (netif_running(ndev)) {
+		netif_device_detach(ndev);
+		umal_shutdown(ndev);
+	}
+	return 0;
+}
+
+static int umal_resume(struct platform_device *pldev)
+{
+	struct net_device *dev = platform_get_drvdata(pldev);
+
+	if (netif_running(dev)) {
+		umal_reset(dev);
+		netif_device_attach(dev);
+	}
+	return 0;
+}
+#else
+static int umal_suspend(struct platform_device *pldev, pm_message_t state) { }
+static int umal_resume(struct platform_device *pldev) { }
+#endif
+static struct platform_driver umal_driver = {
+	.probe = umal_probe,
+	.remove = __exit_p(umal_remove),
+	.driver = {
+		.name = umal_string,
+		.owner  = THIS_MODULE,
+	},
+	.suspend = umal_suspend,
+	.resume	 = umal_resume,
+};
+
+static int __init umal_init_module(void)
+{
+	return platform_driver_register(&umal_driver);
+}
+
+static void __exit umal_cleanup_module(void)
+{
+	platform_driver_unregister(&umal_driver);
+}
+
+module_init(umal_init_module);
+module_exit(umal_cleanup_module);

^ permalink raw reply related

* [net-next 0/4][pull request] Intel Wired LAN Driver Updates
From: Jeff Kirsher @ 2011-01-22 11:56 UTC (permalink / raw)
  To: David Miller, davem; +Cc: Jeff Kirsher, netdev, gospo, bphilips

The following series contains cleanups for e1000e and addition support
for the i340 adapter in igb.

The following are changes since commit bb134d2298b49f50cf6d9388410fba96272905dc:
  net: netif_setup_tc() is static

and are available in the git repository at:
  master.kernel.org:/pub/scm/linux/kernel/git/jkirsher/net-next-2.6 master

Bruce Allan (2):
  e1000e: reduce scope of some variables, remove unnecessary ones
  e1000e: Use kmemdup rather than duplicating its implementation

Carolyn Wyborny (1):
  igb: Add support for i340 Quad Port Fiber Adapter

Jeff Kirsher (1):
  e1000e: convert to stats64

 drivers/net/e1000e/e1000.h    |    5 ++-
 drivers/net/e1000e/ethtool.c  |   52 ++++++++-----------
 drivers/net/e1000e/ich8lan.c  |    3 +-
 drivers/net/e1000e/lib.c      |    4 +-
 drivers/net/e1000e/netdev.c   |  117 +++++++++++++++++++++++++++-------------
 drivers/net/e1000e/phy.c      |    8 ++--
 drivers/net/igb/e1000_82575.c |    1 +
 drivers/net/igb/e1000_hw.h    |    1 +
 drivers/net/igb/igb_main.c    |    1 +
 9 files changed, 116 insertions(+), 76 deletions(-)

-- 
1.7.3.4


^ permalink raw reply

* [PATCH 1/4] e1000e: convert to stats64
From: Jeff Kirsher @ 2011-01-22 11:56 UTC (permalink / raw)
  To: David Miller, davem
  Cc: Jeff Kirsher, netdev, gospo, bphilips, Flavio Leitner,
	Eric Dumazet
In-Reply-To: <1295697376-2984-1-git-send-email-jeffrey.t.kirsher@intel.com>

Based on the patch provided by Flavio Leitner <fleitner@redhat.com>
Provides accurate stats at the time user reads them.

v2: fixed whitespace/merging issues (by Jeff Kirsher)
v3: fixed namespacing issues (by Bruce Allan)

CC: Flavio Leitner <fleitner@redhat.com>
CC: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
---
 drivers/net/e1000e/e1000.h   |    5 ++-
 drivers/net/e1000e/ethtool.c |   37 +++++++++++----------
 drivers/net/e1000e/netdev.c  |   72 +++++++++++++++++++++++++++++++++---------
 3 files changed, 80 insertions(+), 34 deletions(-)

diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index e610e13..00bf595 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -364,6 +364,7 @@ struct e1000_adapter {
 	/* structs defined in e1000_hw.h */
 	struct e1000_hw hw;
 
+	spinlock_t stats64_lock;
 	struct e1000_hw_stats stats;
 	struct e1000_phy_info phy_info;
 	struct e1000_phy_stats phy_stats;
@@ -494,7 +495,9 @@ extern int e1000e_setup_rx_resources(struct e1000_adapter *adapter);
 extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter);
 extern void e1000e_free_rx_resources(struct e1000_adapter *adapter);
 extern void e1000e_free_tx_resources(struct e1000_adapter *adapter);
-extern void e1000e_update_stats(struct e1000_adapter *adapter);
+extern struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
+                                                    struct rtnl_link_stats64
+                                                    *stats);
 extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
 extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
 extern void e1000e_get_hw_control(struct e1000_adapter *adapter);
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index fa08b63..dfa44de 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -46,15 +46,15 @@ struct e1000_stats {
 };
 
 #define E1000_STAT(str, m) { \
-			.stat_string = str, \
-			.type = E1000_STATS, \
-			.sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \
-			.stat_offset = offsetof(struct e1000_adapter, m) }
+		.stat_string = str, \
+		.type = E1000_STATS, \
+		.sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \
+		.stat_offset = offsetof(struct e1000_adapter, m) }
 #define E1000_NETDEV_STAT(str, m) { \
-			.stat_string = str, \
-			.type = NETDEV_STATS, \
-			.sizeof_stat = sizeof(((struct net_device *)0)->m), \
-			.stat_offset = offsetof(struct net_device, m) }
+		.stat_string = str, \
+		.type = NETDEV_STATS, \
+		.sizeof_stat = sizeof(((struct rtnl_link_stats64 *)0)->m), \
+		.stat_offset = offsetof(struct rtnl_link_stats64, m) }
 
 static const struct e1000_stats e1000_gstrings_stats[] = {
 	E1000_STAT("rx_packets", stats.gprc),
@@ -65,21 +65,21 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
 	E1000_STAT("tx_broadcast", stats.bptc),
 	E1000_STAT("rx_multicast", stats.mprc),
 	E1000_STAT("tx_multicast", stats.mptc),
-	E1000_NETDEV_STAT("rx_errors", stats.rx_errors),
-	E1000_NETDEV_STAT("tx_errors", stats.tx_errors),
-	E1000_NETDEV_STAT("tx_dropped", stats.tx_dropped),
+	E1000_NETDEV_STAT("rx_errors", rx_errors),
+	E1000_NETDEV_STAT("tx_errors", tx_errors),
+	E1000_NETDEV_STAT("tx_dropped", tx_dropped),
 	E1000_STAT("multicast", stats.mprc),
 	E1000_STAT("collisions", stats.colc),
-	E1000_NETDEV_STAT("rx_length_errors", stats.rx_length_errors),
-	E1000_NETDEV_STAT("rx_over_errors", stats.rx_over_errors),
+	E1000_NETDEV_STAT("rx_length_errors", rx_length_errors),
+	E1000_NETDEV_STAT("rx_over_errors", rx_over_errors),
 	E1000_STAT("rx_crc_errors", stats.crcerrs),
-	E1000_NETDEV_STAT("rx_frame_errors", stats.rx_frame_errors),
+	E1000_NETDEV_STAT("rx_frame_errors", rx_frame_errors),
 	E1000_STAT("rx_no_buffer_count", stats.rnbc),
 	E1000_STAT("rx_missed_errors", stats.mpc),
 	E1000_STAT("tx_aborted_errors", stats.ecol),
 	E1000_STAT("tx_carrier_errors", stats.tncrs),
-	E1000_NETDEV_STAT("tx_fifo_errors", stats.tx_fifo_errors),
-	E1000_NETDEV_STAT("tx_heartbeat_errors", stats.tx_heartbeat_errors),
+	E1000_NETDEV_STAT("tx_fifo_errors", tx_fifo_errors),
+	E1000_NETDEV_STAT("tx_heartbeat_errors", tx_heartbeat_errors),
 	E1000_STAT("tx_window_errors", stats.latecol),
 	E1000_STAT("tx_abort_late_coll", stats.latecol),
 	E1000_STAT("tx_deferred_ok", stats.dc),
@@ -1982,14 +1982,15 @@ static void e1000_get_ethtool_stats(struct net_device *netdev,
 				    u64 *data)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct rtnl_link_stats64 net_stats;
 	int i;
 	char *p = NULL;
 
-	e1000e_update_stats(adapter);
+	e1000e_get_stats64(netdev, &net_stats);
 	for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
 		switch (e1000_gstrings_stats[i].type) {
 		case NETDEV_STATS:
-			p = (char *) netdev +
+			p = (char *) &net_stats +
 					e1000_gstrings_stats[i].stat_offset;
 			break;
 		case E1000_STATS:
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 1c18f26..1c2f33d 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -900,8 +900,6 @@ next_desc:
 
 	adapter->total_rx_bytes += total_rx_bytes;
 	adapter->total_rx_packets += total_rx_packets;
-	netdev->stats.rx_bytes += total_rx_bytes;
-	netdev->stats.rx_packets += total_rx_packets;
 	return cleaned;
 }
 
@@ -1057,8 +1055,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
 	}
 	adapter->total_tx_bytes += total_tx_bytes;
 	adapter->total_tx_packets += total_tx_packets;
-	netdev->stats.tx_bytes += total_tx_bytes;
-	netdev->stats.tx_packets += total_tx_packets;
 	return count < tx_ring->count;
 }
 
@@ -1245,8 +1241,6 @@ next_desc:
 
 	adapter->total_rx_bytes += total_rx_bytes;
 	adapter->total_rx_packets += total_rx_packets;
-	netdev->stats.rx_bytes += total_rx_bytes;
-	netdev->stats.rx_packets += total_rx_packets;
 	return cleaned;
 }
 
@@ -1426,8 +1420,6 @@ next_desc:
 
 	adapter->total_rx_bytes += total_rx_bytes;
 	adapter->total_rx_packets += total_rx_packets;
-	netdev->stats.rx_bytes += total_rx_bytes;
-	netdev->stats.rx_packets += total_rx_packets;
 	return cleaned;
 }
 
@@ -3338,6 +3330,8 @@ int e1000e_up(struct e1000_adapter *adapter)
 	return 0;
 }
 
+static void e1000e_update_stats(struct e1000_adapter *adapter);
+
 void e1000e_down(struct e1000_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -3372,6 +3366,11 @@ void e1000e_down(struct e1000_adapter *adapter)
 	del_timer_sync(&adapter->phy_info_timer);
 
 	netif_carrier_off(netdev);
+
+	spin_lock(&adapter->stats64_lock);
+	e1000e_update_stats(adapter);
+	spin_unlock(&adapter->stats64_lock);
+
 	adapter->link_speed = 0;
 	adapter->link_duplex = 0;
 
@@ -3413,6 +3412,8 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
 	adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
 	adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
 
+	spin_lock_init(&adapter->stats64_lock);
+
 	e1000e_set_interrupt_capability(adapter);
 
 	if (e1000_alloc_queues(adapter))
@@ -3886,7 +3887,7 @@ release:
  * e1000e_update_stats - Update the board statistics counters
  * @adapter: board private structure
  **/
-void e1000e_update_stats(struct e1000_adapter *adapter)
+static void e1000e_update_stats(struct e1000_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_hw *hw = &adapter->hw;
@@ -4285,7 +4286,9 @@ static void e1000_watchdog_task(struct work_struct *work)
 	}
 
 link_up:
+	spin_lock(&adapter->stats64_lock);
 	e1000e_update_stats(adapter);
+	spin_unlock(&adapter->stats64_lock);
 
 	mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
 	adapter->tpt_old = adapter->stats.tpt;
@@ -4897,16 +4900,55 @@ static void e1000_reset_task(struct work_struct *work)
 }
 
 /**
- * e1000_get_stats - Get System Network Statistics
+ * e1000_get_stats64 - Get System Network Statistics
  * @netdev: network interface device structure
+ * @stats: rtnl_link_stats64 pointer
  *
  * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
  **/
-static struct net_device_stats *e1000_get_stats(struct net_device *netdev)
+struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
+                                             struct rtnl_link_stats64 *stats)
 {
-	/* only return the current stats */
-	return &netdev->stats;
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+
+	memset(stats, 0, sizeof(struct rtnl_link_stats64));
+	spin_lock(&adapter->stats64_lock);
+	e1000e_update_stats(adapter);
+	/* Fill out the OS statistics structure */
+	stats->rx_bytes = adapter->stats.gorc;
+	stats->rx_packets = adapter->stats.gprc;
+	stats->tx_bytes = adapter->stats.gotc;
+	stats->tx_packets = adapter->stats.gptc;
+	stats->multicast = adapter->stats.mprc;
+	stats->collisions = adapter->stats.colc;
+
+	/* Rx Errors */
+
+	/*
+	 * RLEC on some newer hardware can be incorrect so build
+	 * our own version based on RUC and ROC
+	 */
+	stats->rx_errors = adapter->stats.rxerrc +
+		adapter->stats.crcerrs + adapter->stats.algnerrc +
+		adapter->stats.ruc + adapter->stats.roc +
+		adapter->stats.cexterr;
+	stats->rx_length_errors = adapter->stats.ruc +
+					      adapter->stats.roc;
+	stats->rx_crc_errors = adapter->stats.crcerrs;
+	stats->rx_frame_errors = adapter->stats.algnerrc;
+	stats->rx_missed_errors = adapter->stats.mpc;
+
+	/* Tx Errors */
+	stats->tx_errors = adapter->stats.ecol +
+				       adapter->stats.latecol;
+	stats->tx_aborted_errors = adapter->stats.ecol;
+	stats->tx_window_errors = adapter->stats.latecol;
+	stats->tx_carrier_errors = adapter->stats.tncrs;
+
+	/* Tx Dropped needs to be maintained elsewhere */
+
+	spin_unlock(&adapter->stats64_lock);
+	return stats;
 }
 
 /**
@@ -5675,7 +5717,7 @@ static const struct net_device_ops e1000e_netdev_ops = {
 	.ndo_open		= e1000_open,
 	.ndo_stop		= e1000_close,
 	.ndo_start_xmit		= e1000_xmit_frame,
-	.ndo_get_stats		= e1000_get_stats,
+	.ndo_get_stats64	= e1000e_get_stats64,
 	.ndo_set_multicast_list	= e1000_set_multi,
 	.ndo_set_mac_address	= e1000_set_mac,
 	.ndo_change_mtu		= e1000_change_mtu,
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH 2/4] e1000e: reduce scope of some variables, remove unnecessary ones
From: Jeff Kirsher @ 2011-01-22 11:56 UTC (permalink / raw)
  To: David Miller, davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1295697376-2984-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Bruce Allan <bruce.w.allan@intel.com>

Static analysis of the driver code found some variables for which the scope
can be reduced, or remove the variable altogether.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/e1000e/ethtool.c |    4 +--
 drivers/net/e1000e/ich8lan.c |    3 +-
 drivers/net/e1000e/lib.c     |    4 +-
 drivers/net/e1000e/netdev.c  |   45 ++++++++++++++++++++---------------------
 drivers/net/e1000e/phy.c     |    8 +++---
 5 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index dfa44de..323fd12 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -1255,7 +1255,6 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl_reg = 0;
-	u32 stat_reg = 0;
 	u16 phy_reg = 0;
 	s32 ret_val = 0;
 
@@ -1363,8 +1362,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
 		 * Set the ILOS bit on the fiber Nic if half duplex link is
 		 * detected.
 		 */
-		stat_reg = er32(STATUS);
-		if ((stat_reg & E1000_STATUS_FD) == 0)
+		if ((er32(STATUS) & E1000_STATUS_FD) == 0)
 			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
 	}
 
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index fb46974..232b42b 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -2104,7 +2104,6 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
 {
 	union ich8_hws_flash_status hsfsts;
 	s32 ret_val = -E1000_ERR_NVM;
-	s32 i = 0;
 
 	hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
 
@@ -2140,6 +2139,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
 		ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
 		ret_val = 0;
 	} else {
+		s32 i = 0;
+
 		/*
 		 * Otherwise poll for sometime so the current
 		 * cycle has a chance to end before giving up.
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index 68aa174..96921de 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -1978,15 +1978,15 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
 {
 	struct e1000_nvm_info *nvm = &hw->nvm;
 	u32 eecd = er32(EECD);
-	u16 timeout = 0;
 	u8 spi_stat_reg;
 
 	if (nvm->type == e1000_nvm_eeprom_spi) {
+		u16 timeout = NVM_MAX_RETRY_SPI;
+
 		/* Clear SK and CS */
 		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
 		ew32(EECD, eecd);
 		udelay(1);
-		timeout = NVM_MAX_RETRY_SPI;
 
 		/*
 		 * Read "Status Register" repeatedly until the LSB is cleared.
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 1c2f33d..5b916b0 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2720,7 +2720,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 rctl, rfctl;
-	u32 psrctl = 0;
 	u32 pages = 0;
 
 	/* Workaround Si errata on 82579 - configure jumbo frame flow */
@@ -2819,6 +2818,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
 		adapter->rx_ps_pages = 0;
 
 	if (adapter->rx_ps_pages) {
+		u32 psrctl = 0;
+
 		/* Configure extra packet-split registers */
 		rfctl = er32(RFCTL);
 		rfctl |= E1000_RFCTL_EXTEN;
@@ -3020,7 +3021,6 @@ static void e1000_set_multi(struct net_device *netdev)
 	struct netdev_hw_addr *ha;
 	u8  *mta_list;
 	u32 rctl;
-	int i;
 
 	/* Check for Promiscuous and All Multicast modes */
 
@@ -3043,12 +3043,13 @@ static void e1000_set_multi(struct net_device *netdev)
 	ew32(RCTL, rctl);
 
 	if (!netdev_mc_empty(netdev)) {
+		int i = 0;
+
 		mta_list = kmalloc(netdev_mc_count(netdev) * 6, GFP_ATOMIC);
 		if (!mta_list)
 			return;
 
 		/* prepare a packed array of only addresses. */
-		i = 0;
 		netdev_for_each_mc_addr(ha, netdev)
 			memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN);
 
@@ -3999,10 +4000,11 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_phy_regs *phy = &adapter->phy_regs;
-	int ret_val;
 
 	if ((er32(STATUS) & E1000_STATUS_LU) &&
 	    (adapter->hw.phy.media_type == e1000_media_type_copper)) {
+		int ret_val;
+
 		ret_val  = e1e_rphy(hw, PHY_CONTROL, &phy->bmcr);
 		ret_val |= e1e_rphy(hw, PHY_STATUS, &phy->bmsr);
 		ret_val |= e1e_rphy(hw, PHY_AUTONEG_ADV, &phy->advertise);
@@ -4148,7 +4150,6 @@ static void e1000_watchdog_task(struct work_struct *work)
 	struct e1000_ring *tx_ring = adapter->tx_ring;
 	struct e1000_hw *hw = &adapter->hw;
 	u32 link, tctl;
-	int tx_pending = 0;
 
 	link = e1000e_has_link(adapter);
 	if ((netif_carrier_ok(netdev)) && link) {
@@ -4302,21 +4303,18 @@ link_up:
 
 	e1000e_update_adaptive(&adapter->hw);
 
-	if (!netif_carrier_ok(netdev)) {
-		tx_pending = (e1000_desc_unused(tx_ring) + 1 <
-			       tx_ring->count);
-		if (tx_pending) {
-			/*
-			 * We've lost link, so the controller stops DMA,
-			 * but we've got queued Tx work that's never going
-			 * to get done, so reset controller to flush Tx.
-			 * (Do the reset outside of interrupt context).
-			 */
-			adapter->tx_timeout_count++;
-			schedule_work(&adapter->reset_task);
-			/* return immediately since reset is imminent */
-			return;
-		}
+	if (!netif_carrier_ok(netdev) &&
+	    (e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) {
+		/*
+		 * We've lost link, so the controller stops DMA,
+		 * but we've got queued Tx work that's never going
+		 * to get done, so reset controller to flush Tx.
+		 * (Do the reset outside of interrupt context).
+		 */
+		adapter->tx_timeout_count++;
+		schedule_work(&adapter->reset_task);
+		/* return immediately since reset is imminent */
+		return;
 	}
 
 	/* Simple mode for Interrupt Throttle Rate (ITR) */
@@ -4387,13 +4385,13 @@ static int e1000_tso(struct e1000_adapter *adapter,
 	u32 cmd_length = 0;
 	u16 ipcse = 0, tucse, mss;
 	u8 ipcss, ipcso, tucss, tucso, hdr_len;
-	int err;
 
 	if (!skb_is_gso(skb))
 		return 0;
 
 	if (skb_header_cloned(skb)) {
-		err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+		int err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+
 		if (err)
 			return err;
 	}
@@ -5518,9 +5516,10 @@ static irqreturn_t e1000_intr_msix(int irq, void *data)
 {
 	struct net_device *netdev = data;
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	int vector, msix_irq;
 
 	if (adapter->msix_entries) {
+		int vector, msix_irq;
+
 		vector = 0;
 		msix_irq = adapter->msix_entries[vector].vector;
 		disable_irq(msix_irq);
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
index 6bea051..6ae31fc 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/e1000e/phy.c
@@ -2409,9 +2409,7 @@ static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg)
 s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
 {
 	s32 ret_val;
-	u32 page_select = 0;
 	u32 page = offset >> IGP_PAGE_SHIFT;
-	u32 page_shift = 0;
 
 	ret_val = hw->phy.ops.acquire(hw);
 	if (ret_val)
@@ -2427,6 +2425,8 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
 	hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
 
 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
+		u32 page_shift, page_select;
+
 		/*
 		 * Page select is register 31 for phy address 1 and 22 for
 		 * phy address 2 and 3. Page select is shifted only for
@@ -2468,9 +2468,7 @@ out:
 s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
 {
 	s32 ret_val;
-	u32 page_select = 0;
 	u32 page = offset >> IGP_PAGE_SHIFT;
-	u32 page_shift = 0;
 
 	ret_val = hw->phy.ops.acquire(hw);
 	if (ret_val)
@@ -2486,6 +2484,8 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
 	hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
 
 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
+		u32 page_shift, page_select;
+
 		/*
 		 * Page select is register 31 for phy address 1 and 22 for
 		 * phy address 2 and 3. Page select is shifted only for
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH 4/4] igb: Add support for i340 Quad Port Fiber Adapter
From: Jeff Kirsher @ 2011-01-22 11:56 UTC (permalink / raw)
  To: David Miller, davem
  Cc: Carolyn Wyborny, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1295697376-2984-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Carolyn Wyborny <carolyn.wyborny@intel.com>

This patch enables support for Intel i340 Quad Port Fiber Adapter.

Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/igb/e1000_82575.c |    1 +
 drivers/net/igb/e1000_hw.h    |    1 +
 drivers/net/igb/igb_main.c    |    1 +
 3 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index 0a2368f..c1552b6 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -129,6 +129,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 		break;
 	case E1000_DEV_ID_82580_COPPER:
 	case E1000_DEV_ID_82580_FIBER:
+	case E1000_DEV_ID_82580_QUAD_FIBER:
 	case E1000_DEV_ID_82580_SERDES:
 	case E1000_DEV_ID_82580_SGMII:
 	case E1000_DEV_ID_82580_COPPER_DUAL:
diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h
index e2638af..281324e 100644
--- a/drivers/net/igb/e1000_hw.h
+++ b/drivers/net/igb/e1000_hw.h
@@ -54,6 +54,7 @@ struct e1000_hw;
 #define E1000_DEV_ID_82580_SERDES             0x1510
 #define E1000_DEV_ID_82580_SGMII              0x1511
 #define E1000_DEV_ID_82580_COPPER_DUAL        0x1516
+#define E1000_DEV_ID_82580_QUAD_FIBER         0x1527
 #define E1000_DEV_ID_DH89XXCC_SGMII           0x0438
 #define E1000_DEV_ID_DH89XXCC_SERDES          0x043A
 #define E1000_DEV_ID_DH89XXCC_BACKPLANE       0x043C
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 58c665b..200cc32 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -68,6 +68,7 @@ static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SGMII), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_FIBER), board_82575 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_QUAD_FIBER), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 },
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH 3/4] e1000e: Use kmemdup rather than duplicating its implementation
From: Jeff Kirsher @ 2011-01-22 11:56 UTC (permalink / raw)
  To: David Miller, davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1295697376-2984-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Bruce Allan <bruce.w.allan@intel.com>

The semantic patch that makes this output is available
in scripts/coccinelle/api/memdup.cocci.

More information about semantic patching is available at
http://coccinelle.lip6.fr/

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/e1000e/ethtool.c |   11 ++---------
 1 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 323fd12..daa7fe4 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -684,20 +684,13 @@ static int e1000_set_ringparam(struct net_device *netdev,
 	rx_old = adapter->rx_ring;
 
 	err = -ENOMEM;
-	tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+	tx_ring = kmemdup(tx_old, sizeof(struct e1000_ring), GFP_KERNEL);
 	if (!tx_ring)
 		goto err_alloc_tx;
-	/*
-	 * use a memcpy to save any previously configured
-	 * items like napi structs from having to be
-	 * reinitialized
-	 */
-	memcpy(tx_ring, tx_old, sizeof(struct e1000_ring));
 
-	rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+	rx_ring = kmemdup(rx_old, sizeof(struct e1000_ring), GFP_KERNEL);
 	if (!rx_ring)
 		goto err_alloc_rx;
-	memcpy(rx_ring, rx_old, sizeof(struct e1000_ring));
 
 	adapter->tx_ring = tx_ring;
 	adapter->rx_ring = rx_ring;
-- 
1.7.3.4


^ permalink raw reply related

* Re: [PATCH V9 08/13] posix clocks: cleanup the CLOCK_DISPTACH macro
From: Richard Cochran @ 2011-01-22 12:38 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, linux-api, netdev, Alan Cox, Arnd Bergmann,
	Christoph Lameter, David Miller, John Stultz, Krzysztof Halasa,
	Peter Zijlstra, Rodolfo Giometti
In-Reply-To: <alpine.LFD.2.00.1101131745400.2678@localhost6.localdomain6>

On Thu, Jan 13, 2011 at 06:03:24PM +0100, Thomas Gleixner wrote:
> On Thu, 13 Jan 2011, Richard Cochran wrote:
> >  int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *ts);
> >  int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *ts);
> > -int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *ts);
> > +int posix_cpu_clock_set(const clockid_t which_clock, struct timespec *ts);
> 
> Shouldn't we change the clock_set function to have *ts const in all places ?

The common_clock_set function calls:

    do_sys_settimeofday
        security_settime
            cap_settime
    do_settimeofday

so all their signatures must also change.

Should I add that into my patch set?

Thanks,
Richard

^ 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