Netdev List
 help / color / mirror / Atom feed
* Re: [net] ixgbe: Do not pad FCoE frames as this can cause issues with FCoE DDP
From: David Miller @ 2012-06-26 23:45 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: alexander.h.duyck, netdev, gospo, sassmann, stable
In-Reply-To: <1340697286-3047-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Tue, 26 Jun 2012 00:54:46 -0700

> From: Alexander Duyck <alexander.h.duyck@intel.com>
> 
> FCoE target mode was experiencing issues due to the fact that we were
> sending up data frames that were padded to 60 bytes after the DDP logic had
> already stripped the frame down to 52 or 56 depending on the use of VLANs.
> This was resulting in the FCoE DDP logic having issues since it thought the
> frame still had data in it due to the padding.
> 
> To resolve this, adding code so that we do not pad FCoE frames prior to
> handling them to the stack.
> 
> CC: <stable@vger.kernel.org>
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
> Tested-by: Ross Brattain <ross.b.brattain@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH] net: l2tp_eth: use LLTX to avoid LOCKDEP splats
From: David Miller @ 2012-06-26 23:43 UTC (permalink / raw)
  To: eric.dumazet; +Cc: denys, netdev, honkiko, jchapman, romieu
In-Reply-To: <1340638545.10893.70.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 25 Jun 2012 17:35:45 +0200

> From: Eric Dumazet <edumazet@google.com>
> 
> Denys Fedoryshchenko reported a LOCKDEP issue with l2tp code.
 ...
> It appears that like most virtual devices, l2tp should be converted to
> LLTX mode.
> 
> This patch takes care of statistics using atomic_long in both RX and TX
> paths, and fix a bug in l2tp_eth_dev_recv(), which was caching skb->data
> before a pskb_may_pull() call.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reported-by: Denys Fedoryshchenko <denys@visp.net.lb>
> Cc: James Chapman <jchapman@katalix.com>
> Cc: Hong zhi guo <honkiko@gmail.com>
> Cc: Francois Romieu <romieu@fr.zoreil.com>
> ---
> Should be applied after "net: l2tp_eth: fix l2tp_eth_dev_xmit race"

Applied, thanks Eric.

^ permalink raw reply

* Re: [PATCH] r8169: RxConfig hack for the 8168evl.
From: David Miller @ 2012-06-26 23:41 UTC (permalink / raw)
  To: romieu; +Cc: hayeswang, netdev, thomas.pi
In-Reply-To: <20120626092251.GA1854@electric-eye.fr.zoreil.com>

From: Francois Romieu <romieu@fr.zoreil.com>
Date: Tue, 26 Jun 2012 11:22:51 +0200

> hayeswang <hayeswang@realtek.com> :
> [...]
>> The definition of the IO 0x44 bit 14 is opposite for new chips.
>> For 8111C, 0 means fetching one Rx descriptor, and 1 means fetching
>> multi-descriptors.
>> For 8111D and the later chips, 0 means fetching multi-descriptors, and 1 means
>> fetching one Rx descriptor.
> 
> Ok. Is there much point fetching one Rx descriptor versus several ?

It can help if the chip accesses enough at a time to fill a full cache
line.

In drivers I've written for chips that can do this, I've had the code
only post RX descriptors in chunks rather than one at a time, to
facilitate this even further.

^ permalink raw reply

* [PATCH] ipv4: Cache ip_error() routes even when not forwarding.
From: David Miller @ 2012-06-26 23:37 UTC (permalink / raw)
  To: netdev


And account for the fact that, when we are not forwarding, we should
bump statistic counters rather than emit an ICMP response.

RP-filter rejected lookups are still not cached.

Since -EHOSTUNREACH and -ENETUNREACH can now no longer be seen in
ip_rcv_finish(), remove those checks.

Signed-off-by: David S. Miller <davem@davemloft.net>
---

It seems pretty clear to me that we should cache things consistently
regardless of whether we are forwarding on an interface or not.

I noticed this while monitoring the routing cache the other day.  If
you have some misconfigured host on your network (as I did :-), this
change increases diagnosability because you'll be able to see the
reject routes in /proc/net/rt_cache with the specific IPs involved.

It was actually a surprise to me that we do not cache RP-filtered
lookups.  It's probably a toss-up whether caching or not caching these
is better or not.  So I haven't touched that case for now.  If we do
start to cache those, it will be nice in that we can streamline the
logic of ip_rcv_finish() completely by removing all the special error
code checks and counter bumps.  Only the -EXDEV RP-filter one remains.

Committed to net-next

 net/ipv4/ip_input.c |    8 +-------
 net/ipv4/route.c    |   30 +++++++++++++++++++-----------
 2 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index bca2517..2a39204 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -342,13 +342,7 @@ static int ip_rcv_finish(struct sk_buff *skb)
 			err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
 						   iph->tos, skb->dev);
 			if (unlikely(err)) {
-				if (err == -EHOSTUNREACH)
-					IP_INC_STATS_BH(dev_net(skb->dev),
-							IPSTATS_MIB_INADDRERRORS);
-				else if (err == -ENETUNREACH)
-					IP_INC_STATS_BH(dev_net(skb->dev),
-							IPSTATS_MIB_INNOROUTES);
-				else if (err == -EXDEV)
+				if (err == -EXDEV)
 					NET_INC_STATS_BH(dev_net(skb->dev),
 							 LINUX_MIB_IPRPFILTER);
 				goto drop;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 846961c..81533e3 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1609,12 +1609,28 @@ void ip_rt_send_redirect(struct sk_buff *skb)
 
 static int ip_error(struct sk_buff *skb)
 {
+	struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
 	struct rtable *rt = skb_rtable(skb);
 	struct inet_peer *peer;
 	unsigned long now;
+	struct net *net;
 	bool send;
 	int code;
 
+	net = dev_net(rt->dst.dev);
+	if (!IN_DEV_FORWARD(in_dev)) {
+		switch (rt->dst.error) {
+		case EHOSTUNREACH:
+			IP_INC_STATS_BH(net, IPSTATS_MIB_INADDRERRORS);
+			break;
+
+		case ENETUNREACH:
+			IP_INC_STATS_BH(net, IPSTATS_MIB_INNOROUTES);
+			break;
+		}
+		goto out;
+	}
+
 	switch (rt->dst.error) {
 	case EINVAL:
 	default:
@@ -1624,8 +1640,7 @@ static int ip_error(struct sk_buff *skb)
 		break;
 	case ENETUNREACH:
 		code = ICMP_NET_UNREACH;
-		IP_INC_STATS_BH(dev_net(rt->dst.dev),
-				IPSTATS_MIB_INNOROUTES);
+		IP_INC_STATS_BH(net, IPSTATS_MIB_INNOROUTES);
 		break;
 	case EACCES:
 		code = ICMP_PKT_FILTERED;
@@ -2255,11 +2270,8 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	fl4.daddr = daddr;
 	fl4.saddr = saddr;
 	err = fib_lookup(net, &fl4, &res);
-	if (err != 0) {
-		if (!IN_DEV_FORWARD(in_dev))
-			goto e_hostunreach;
+	if (err != 0)
 		goto no_route;
-	}
 
 	RT_CACHE_STAT_INC(in_slow_tot);
 
@@ -2279,7 +2291,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	}
 
 	if (!IN_DEV_FORWARD(in_dev))
-		goto e_hostunreach;
+		goto no_route;
 	if (res.type != RTN_UNICAST)
 		goto martian_destination;
 
@@ -2367,10 +2379,6 @@ martian_destination:
 				     &daddr, &saddr, dev->name);
 #endif
 
-e_hostunreach:
-	err = -EHOSTUNREACH;
-	goto out;
-
 e_inval:
 	err = -EINVAL;
 	goto out;
-- 
1.7.10

^ permalink raw reply related

* Re: HSR: How to set IF_OPER_LOWERLAYERDOWN?
From: Stephen Hemminger @ 2012-06-26 22:33 UTC (permalink / raw)
  To: Arvid Brodin; +Cc: netdev@vger.kernel.org, Javier Boticario, Bruno Ferreira
In-Reply-To: <4FEA37A0.309@xdin.com>

On Tue, 26 Jun 2012 22:28:51 +0000
Arvid Brodin <Arvid.Brodin@xdin.com> wrote:

> Hi,
> 
> According to Documentation/networking/operstates.txt a network interface have an
> operational state and an administrative state.
> 
> If I understand things correctly the administrative state is the desired state set by
> userspace, and the operational state is the actual state which depends on things like the
> administrative state, whether a carrier is present, or (for virtual interfaces lite VLAN)
> whether the lower interface is available.
> 
> 
> In the driver I'm writing (for the "HSR" redundancy protocol) a hsr (virtual) interface is
> useable as long as any of its (physical) slaves are useable. I.e. the operstate of a hsr
> device might be set like this:
> 
> void hsr_set_operstate()
> {
> 	if (!is_admin_up(hsr_dev)) /* Check IFF_UP */ {
> 		set_operstate(hsr_dev, IF_OPER_DOWN);
> 		return;
> 	}
> 
> 	if (is_operstate_up(slave1) || is_operstate_up(slave2)) /* Check IF_OPER_UP */
> 		set_operstate(hsr_dev, IF_OPER_UP);
> 	else
> 		set_operstate(hsr_dev, IF_OPER_LOWERLAYERDOWN);
> }


According to 802.1X example in documentation to set it down you need to set IF_OPER_DORMANT
not IF_OPER_LOWERLAYERDOWN.  Probably a kernel bug in there somwhere.

^ permalink raw reply

* HSR: How to set IF_OPER_LOWERLAYERDOWN?
From: Arvid Brodin @ 2012-06-26 22:28 UTC (permalink / raw)
  To: netdev@vger.kernel.org, Stephen Hemminger
  Cc: Javier Boticario, Bruno Ferreira

Hi,

According to Documentation/networking/operstates.txt a network interface have an
operational state and an administrative state.

If I understand things correctly the administrative state is the desired state set by
userspace, and the operational state is the actual state which depends on things like the
administrative state, whether a carrier is present, or (for virtual interfaces lite VLAN)
whether the lower interface is available.


In the driver I'm writing (for the "HSR" redundancy protocol) a hsr (virtual) interface is
useable as long as any of its (physical) slaves are useable. I.e. the operstate of a hsr
device might be set like this:

void hsr_set_operstate()
{
	if (!is_admin_up(hsr_dev)) /* Check IFF_UP */ {
		set_operstate(hsr_dev, IF_OPER_DOWN);
		return;
	}

	if (is_operstate_up(slave1) || is_operstate_up(slave2)) /* Check IF_OPER_UP */
		set_operstate(hsr_dev, IF_OPER_UP);
	else
		set_operstate(hsr_dev, IF_OPER_LOWERLAYERDOWN);
}

However, the function set_operstate() (in net/core/rtnetlink.c) only accept transitions to
IF_OPER_UP and IF_OPER_DORMANT - other transitions are ignored. (There is a function
rfc2863_policy() (net/core/link_watch.c) that may return IF_OPER_LOWERLAYERDOWN iff
(!netif_carrier_ok(dev) && (dev->ifindex != dev->iflink)), but I don't know what that means.)

So how do I signal my interface as being IF_OPER_LOWERLAYERDOWN?


In another, related matter, I'm wondering if I should set the carrier state of my virtual
interface so that it shows netif_carrier_ok() when it is possible to get the interface to
IF_OPER_UP:

void hsr_set_carrier()
{
	if (is_operstate_up(slave1) || is_operstate_up(slave2))
		netif_carrier_on(hsr_dev);
	else
		netif_carrier_off(hsr_dev);
}


Thanks,
-- 
Arvid Brodin | Consultant (Linux)
XDIN AB | Jan Stenbecks Torg 17 | SE-164 40 Kista | Sweden | xdin.com

^ permalink raw reply

* Re: [PATCH net-next] udp: Add socket early demux support
From: David Miller @ 2012-06-26 21:34 UTC (permalink / raw)
  To: subramanian.vijay; +Cc: netdev, shemminger, eric.dumazet, alexander.h.duyck
In-Reply-To: <1340739826-3363-1-git-send-email-subramanian.vijay@gmail.com>


You can't do this.

If the UDP socket has wildcards, that means the source address of the
route will not be validated.  This means we will start accepting
spoofed packets.  It also means the route you are caching is going
to be the wrong route since the keys are variable.

You can only do an early demux where all the keys are fully specified
and there are no wildcards.  That why for TCP we only early demux for
established sockets.

^ permalink raw reply

* Re: [PATCH net-next] em_canid: Ematch rule to match CAN frames according to their CAN IDs
From: Thomas Graf @ 2012-06-26 21:32 UTC (permalink / raw)
  To: Oliver Hartkopp
  Cc: Rostislav Lisovy, Eric Dumazet, netdev, linux-can, lartc, pisa,
	sojkam1
In-Reply-To: <4FEA169C.1070709@hartkopp.net>

On Tue, Jun 26, 2012 at 10:07:56PM +0200, Oliver Hartkopp wrote:
> > With no extra filter/qdisc configured, median of the time spent in can_send()
> > was about 27 us -- with prio qdisc with 5 bands and 5 appropriate cls_can
> > filters (previous patch), it was about 30 us -- with prio qdisc with 5 bands
> > and 5 appropriate em_can filters (this patch), it was about 34 us.
> 
> 
> Hm that's more than twice the time consumed for classification ...
> 
> cls_can: 3 us more
> em_can:  7 us more
> 
> @Eric: Is this still the better approach then?

If there is overhead, we should get rid of that overhead and not
abandon an established subsystem.

Rostislav: Can you provide some details on where the time is spent?

> > +	/* Process EFF frame rules*/
> > +	for (i = 0; i < cm->rules_count; i++) {
> > +		if ((conf[i].can_id & CAN_EFF_FLAG) &&
> > +		    (conf[i].can_mask & CAN_EFF_FLAG)) {
> > +			memcpy(cm->rules_raw + cm->eff_rules_count,
> 
> 
> Oops. Shouldn't this be
> 
> cm->rules_raw + cm->eff_rules_count * sizeof(struct can_filter),
> 
> ???

Looks like correct pointer arithmetic to me. Your suggestion
would only be valid if rules_raw was a void pointer.

> > +static void em_canid_destroy(struct tcf_proto *tp, struct tcf_ematch *m)
> > +{
> > +	struct canid_match *cm = em_canid_priv(m);
> > +
> 
> 
> Check for cm == NULL not needed ?

kfree() has that check embeddded. Also, for destroy() can only be called
if the match was added to the tree and that requires a successful call
to ->change(). Therefore it will never be NULL.

> > +static int em_canid_dump(struct sk_buff *skb, struct tcf_ematch *m)
> > +{
> > +	struct canid_match *cm = em_canid_priv(m);
> > +
> 
> 
> Check for cm == NULL not needed ?
> 
> Can a dump happen before the matches are added??

Nope, ->dump() is only ever called if the match has been added to the tree.

> > +	/*
> > +	 * When configuring this ematch 'rules_count' is set not to exceed
> > +	 * 'rules_raw' array size
> > +	 */
> > +	if (nla_put_nohdr(skb, sizeof(cm->rules_raw[0]) * cm->rules_count,
> 
> 
> better sizeof(struct can_filter) instead of sizeof(cm->rules_raw[0]) ??
> 
> > +	    &cm->rules_raw) < 0)
> > +		goto nla_put_failure;

No need for a goto here, just return -EMSGSIZE.

^ permalink raw reply

* RE: [RFC] iwmc3200top: remove driver for unavailable hardware
From: Perez-Gonzalez, Inaky @ 2012-06-26 21:21 UTC (permalink / raw)
  To: John W. Linville, netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
  Cc: Ortiz, Samuel,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1340740397-18119-1-git-send-email-linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>

Hi  John

> From: John W. Linville [mailto:linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org]
> Subject: [RFC] iwmc3200top: remove driver for unavailable hardware
> 
> From: "John W. Linville" <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
> 
> This hardware never became available to normal humans.  Leaving this
> driver imposes unwelcome maintenance costs for no clear benefit.
> 
> Signed-off-by: John W. Linville <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
> ---
> Can't remove this just yet, as it is selected by the i2400m wimax
> driver.  The 3200 bits of that driver seem a bit intertwined with the
> rest of the driver.
> 
> Are there any other SDIO parts for i2400m?  Does anyone have any other
> guidance on how I can safely make i2400m be independent of iwmc3200
> support?

It should be pretty straight forward: remove the dependency. In fact, you
are very right--all the sdio code should be removed, as there are no SDIO
parts in the market, to the best of my knowledge.

Yank anything hitting a grep on sdio in i2400m/ (*sdio*) and the Makefile
entries, as well as the Kconfig. That should take care of it.

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

^ permalink raw reply

* RE: [PATCH 1/1] atl1c: fix issue of transmit queue 0 timed out
From: Huang, Xiong @ 2012-06-26 20:55 UTC (permalink / raw)
  To: Rodriguez, Luis
  Cc: Ren, Cloud, davem@davemloft.net, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, qca-linux-team, nic-devel
In-Reply-To: <20120626205436.GJ5070@tux>

Understand, thank you !

> -----Original Message-----
> From: Rodriguez, Luis
> Sent: Wednesday, June 27, 2012 4:55
> To: Huang, Xiong
> Cc: Ren, Cloud; davem@davemloft.net; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; qca-linux-team; nic-devel
> Subject: Re: [PATCH 1/1] atl1c: fix issue of transmit queue 0 timed out
> 
> On Tue, Jun 26, 2012 at 01:41:11PM -0700, Huang, Xiong wrote:
> > Luis
> >    It should be a stable fix, but as Ben Hutchings mentioned in
> > another mail, Maybe, removing netif_stop_queue when cable link down is a
> better choice.
> >
> >    Do you mean we need add 'cc:stable@vger.kernel.org'  just before 'some
> people report  ...' ?
> 
> Nope, see commit 4f7a67e2dd49fbfba002c453bc24bf00e701cc71
> as an example of how to do this. This is a random commit that has been
> marked as stable.
> 
> commit 4f7a67e2dd49fbfba002c453bc24bf00e701cc71
> Author: Ricardo Martins <rasm@fe.up.pt>
> Date:   Tue May 22 18:02:03 2012 +0100
> 
>     USB: fix PS3 EHCI systems
> 
>     After commit aaa0ef289afe9186f81e2340114ea413eef0492a "PS3 EHCI
> QH
>     read work-around", Terratec Grabby (em28xx) stopped working with AMD
>     Geode LX 800 (USB controller AMD CS5536). Since this is a PS3 only
>     fix, the following patch adds a conditional block around it.
> 
>     Signed-off-by: Ricardo Martins <rasm@fe.up.pt>
>     Acked-by: Alan Stern <stern@rowland.harvard.edu>
>     Cc: stable <stable@vger.kernel.org>
>     Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> 
> Sometimes it helps if you specify the oldest stable kernel to apply patches to,
> so for example:
> 
> commit 80b08a8d8829a58b5db14b1417151094cc28face
> Author: Felix Fietkau <nbd@openwrt.org>
> Date:   Fri Jun 15 03:04:53 2012 +0200
> 
>     ath9k: fix invalid pointer access in the tx path
> 
>     After setup_frame_info has been called, only info->control.rates is still
>     valid, other control fields have been overwritten by the ath_frame_info
>     data. Move the access to info->control.vif for checking short preamble
>     to setup_frame_info before it gets overwritten.
> 
>     This regression was introduced in commit d47a61aa
>     "ath9k: Fix multi-VIF BSS handling"
> 
>     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
>     Reported-by: Thomas Hühn <thomas@net.t-labs.tu-berlin.de>
>     Acked-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
>     Cc: stable@vger.kernel.org [3.4]
>     Signed-off-by: John W. Linville <linville@tuxdriver.com>
> 
> To be clear, this is not a Cc: in the e-mail but instead a Cc line in the commit
> log entry.
> 
>   Luis

^ permalink raw reply

* Re: [PATCH 1/1] atl1c: fix issue of transmit queue 0 timed out
From: Luis R. Rodriguez @ 2012-06-26 20:54 UTC (permalink / raw)
  To: Huang, Xiong
  Cc: Ren, Cloud, davem@davemloft.net, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, qca-linux-team, nic-devel
In-Reply-To: <157393863283F442885425D2C454285623DB49B7@NASANEXD02A.na.qualcomm.com>

On Tue, Jun 26, 2012 at 01:41:11PM -0700, Huang, Xiong wrote:
> Luis
>    It should be a stable fix, but as Ben Hutchings mentioned in another mail, 
> Maybe, removing netif_stop_queue when cable link down is a better choice.
> 
>    Do you mean we need add 'cc:stable@vger.kernel.org'  just before 'some people report  ...' ?

Nope, see commit 4f7a67e2dd49fbfba002c453bc24bf00e701cc71
as an example of how to do this. This is a random commit
that has been marked as stable.

commit 4f7a67e2dd49fbfba002c453bc24bf00e701cc71
Author: Ricardo Martins <rasm@fe.up.pt>
Date:   Tue May 22 18:02:03 2012 +0100

    USB: fix PS3 EHCI systems
    
    After commit aaa0ef289afe9186f81e2340114ea413eef0492a "PS3 EHCI QH
    read work-around", Terratec Grabby (em28xx) stopped working with AMD
    Geode LX 800 (USB controller AMD CS5536). Since this is a PS3 only
    fix, the following patch adds a conditional block around it.
    
    Signed-off-by: Ricardo Martins <rasm@fe.up.pt>
    Acked-by: Alan Stern <stern@rowland.harvard.edu>
    Cc: stable <stable@vger.kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Sometimes it helps if you specify the oldest stable kernel
to apply patches to, so for example:

commit 80b08a8d8829a58b5db14b1417151094cc28face
Author: Felix Fietkau <nbd@openwrt.org>
Date:   Fri Jun 15 03:04:53 2012 +0200

    ath9k: fix invalid pointer access in the tx path
    
    After setup_frame_info has been called, only info->control.rates is still
    valid, other control fields have been overwritten by the ath_frame_info
    data. Move the access to info->control.vif for checking short preamble
    to setup_frame_info before it gets overwritten.
    
    This regression was introduced in commit d47a61aa
    "ath9k: Fix multi-VIF BSS handling"
    
    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
    Reported-by: Thomas Hühn <thomas@net.t-labs.tu-berlin.de>
    Acked-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
    Cc: stable@vger.kernel.org [3.4]
    Signed-off-by: John W. Linville <linville@tuxdriver.com>

To be clear, this is not a Cc: in the e-mail but instead a
Cc line in the commit log entry.

  Luis

^ permalink raw reply

* Re: [PATCH net-next] udp: Add socket early demux support
From: Eric Dumazet @ 2012-06-26 20:49 UTC (permalink / raw)
  To: Vijay Subramanian; +Cc: netdev, davem, shemminger, alexander.h.duyck
In-Reply-To: <1340739826-3363-1-git-send-email-subramanian.vijay@gmail.com>

On Tue, 2012-06-26 at 12:43 -0700, Vijay Subramanian wrote:
> Based on the recent TCP socket early demux code, this patch provides similar
> support for UDP.
> 
> Signed-off-by: Vijay Subramanian <subramanian.vijay@gmail.com>
> ---
> This has been tested on x86 with UDP iperf flows and seemed to work. If this is
> accepted, I plan to submit one more patch moving common code from TCP and UDP
> early demux code into common helper functions.
> Thanks in advance for feedback.

Hmm... I cant see how it can work.

Have you tested a router can still route DNS packets if you also have a
DNS server on it, listening on 0.0.0.0:53 ?

Most UDP applications are using unconnected sockets.
(In fact few programmers are aware UDP sockets can be connected)

Try to bench how this is going to work with random IP sources, instead
of UDP iperf flows using a single IP ?

And what about multicast ?

^ permalink raw reply

* RE: [PATCH 1/1] atl1c: fix issue of transmit queue 0 timed out
From: Huang, Xiong @ 2012-06-26 20:41 UTC (permalink / raw)
  To: Rodriguez, Luis, Ren, Cloud
  Cc: davem@davemloft.net, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, qca-linux-team, nic-devel
In-Reply-To: <20120626180311.GC5070@tux>

Luis
   It should be a stable fix, but as Ben Hutchings mentioned in another mail, 
Maybe, removing netif_stop_queue when cable link down is a better choice.

   Do you mean we need add 'cc:stable@vger.kernel.org'  just before 'some people report  ...' ?

Thanks
Xiong

> -----Original Message-----
> From: Rodriguez, Luis
> Sent: Wednesday, June 27, 2012 2:03
> To: Ren, Cloud
> Cc: davem@davemloft.net; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; qca-linux-team; nic-devel; Huang, Xiong
> Subject: Re: [PATCH 1/1] atl1c: fix issue of transmit queue 0 timed out
> 
> On Tue, Jun 26, 2012 at 12:33:06PM -0300, Ren, Cloud wrote:
> > From: xiong <xiong@qca.qualcomm.com>
> >
> > some people report atl1c could cause system hang with following kernel
> > trace info:
> > ---------------------------------------
> > WARNING: at.../net/sched/sch_generic.c:258
> > dev_watchdog+0x1db/0x1d0()
> > ...
> > NETDEV WATCHDOG: eth0 (atl1c): transmit queue 0 timed out ...
> > ---------------------------------------
> > This is caused by netif_stop_queue calling when cable Link is down but
> > netif_wake_queue isn't called when cable Link is resume.
> >
> > Signed-off-by: xiong <xiong@qca.qualcomm.com>
> > Signed-off-by: Cloud Ren <cjren@qca.qualcomm.com>
> 
> If this fixes  a system hang then this could be a stable fix -- that is, this should
> be propagated to older stable kernels, no?
> 
> If so then please add to the commit log a line like this:
> 
> Cc: stable@vger.kernel.org [3.4]
> 
> Note: this is for the commit log! Right above the line below that has "---"
> 
>   Luis

^ permalink raw reply

* [PATCH] sctp: be mroe restrictive in transport selection on bundled sacks
From: Neil Horman @ 2012-06-26 20:31 UTC (permalink / raw)
  To: netdev; +Cc: Neil Horman, Vlad Yaseivch, David S. Miller, linux-sctp

It was noticed recently that when we send data on a transport, its possible that
we might bundle a sack that arrived on a different transport.  While this isn't
a major problem, it does go against the SHOULD requirement in section 6.4 of RFC
2960:

 An endpoint SHOULD transmit reply chunks (e.g., SACK, HEARTBEAT ACK,
   etc.) to the same destination transport address from which it
   received the DATA or control chunk to which it is replying.  This
   rule should also be followed if the endpoint is bundling DATA chunks
   together with the reply chunk.

This patch seeks to correct that.  It restricts the bundling of sack operations
to only those transports which have moved the ctsn of the association forward
since the last sack.  By doing this we guarantee that we only bundle outbound
saks on a transport that has received a chunk since the last sack.  This brings
us into stricter compliance with the RFC.

Vlad had initially suggested that we strictly allow only sack bundling on the
transport that last moved the ctsn forward.  While this makes sense, I was
concerned that doing so prevented us from bundling in the case where we had
received chunks that moved the ctsn on multiple transports.  In those cases, the
RFC allows us to select any of the transports having received chunks to bundle
the sack on.  so I've modified the approach to allow for that, by adding a state
variable to each transport that tracks weather it has moved the ctsn since the
last sack.  This I think keeps our behavior (and performance), close enough to
our current profile that I think we can do this without a sysctl knob to
enable/disable it.

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Vlad Yaseivch <vyasevich@gmail.com>
CC: David S. Miller <davem@davemloft.net>
CC: linux-sctp@vger.kernel.org
Reported-by: Michele Baldessari <michele@redhat.com>
Reported-by: sorin serban <sserban@redhat.com>
---
 include/net/sctp/structs.h |    5 ++++-
 include/net/sctp/tsnmap.h  |    3 ++-
 net/sctp/output.c          |    9 +++++++--
 net/sctp/sm_make_chunk.c   |    8 ++++++++
 net/sctp/sm_sideeffect.c   |    2 +-
 net/sctp/tsnmap.c          |    5 ++++-
 net/sctp/ulpevent.c        |    3 ++-
 net/sctp/ulpqueue.c        |    2 +-
 8 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index e4652fe..712bf09 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -910,7 +910,10 @@ struct sctp_transport {
 		pmtu_pending:1,
 
 		/* Is this structure kfree()able? */
-		malloced:1;
+		malloced:1,
+
+		/* Has this transport moved the ctsn since we last sacked */
+		moved_ctsn:1;
 
 	struct flowi fl;
 
diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h
index e7728bc..2c5d2b4 100644
--- a/include/net/sctp/tsnmap.h
+++ b/include/net/sctp/tsnmap.h
@@ -117,7 +117,8 @@ void sctp_tsnmap_free(struct sctp_tsnmap *map);
 int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn);
 
 /* Mark this TSN as seen.  */
-int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn);
+int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn,
+		     struct sctp_transport *trans);
 
 /* Mark this TSN and all lower as seen. */
 void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn);
diff --git a/net/sctp/output.c b/net/sctp/output.c
index f1b7d4b..c9f47b6 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -240,15 +240,20 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt,
 	 */
 	if (sctp_chunk_is_data(chunk) && !pkt->has_sack &&
 	    !pkt->has_cookie_echo) {
-		struct sctp_association *asoc;
 		struct timer_list *timer;
-		asoc = pkt->transport->asoc;
+		struct sctp_association *asoc = pkt->transport->asoc;
+		struct sctp_transport *trans;
+
 		timer = &asoc->timers[SCTP_EVENT_TIMEOUT_SACK];
 
 		/* If the SACK timer is running, we have a pending SACK */
 		if (timer_pending(timer)) {
 			struct sctp_chunk *sack;
 			asoc->a_rwnd = asoc->rwnd;
+
+			if (chunk->transport && !chunk->transport->moved_ctsn)
+				return retval;
+
 			sack = sctp_make_sack(asoc);
 			if (sack) {
 				retval = sctp_packet_append_chunk(pkt, sack);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index a85eeeb..bad469b 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -736,6 +736,7 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
 	__u16 num_gabs, num_dup_tsns;
 	struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
 	struct sctp_gap_ack_block gabs[SCTP_MAX_GABS];
+	struct sctp_transport *trans;
 
 	memset(gabs, 0, sizeof(gabs));
 	ctsn = sctp_tsnmap_get_ctsn(map);
@@ -805,6 +806,13 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
 		sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,
 				 sctp_tsnmap_get_dups(map));
 
+	/*
+	 * Once we have a sack generated, clear the moved_tsn information
+	 * from all the transports
+	 */
+	list_for_each_entry(trans, &asoc->peer.transport_addr_list, transports) {
+		trans->moved_ctsn = 0;
+	}
 nodata:
 	return retval;
 }
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index c96d1a8..8716da1 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1268,7 +1268,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 		case SCTP_CMD_REPORT_TSN:
 			/* Record the arrival of a TSN.  */
 			error = sctp_tsnmap_mark(&asoc->peer.tsn_map,
-						 cmd->obj.u32);
+						 cmd->obj.u32, NULL);
 			break;
 
 		case SCTP_CMD_REPORT_FWDTSN:
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c
index f1e40ceb..619c638 100644
--- a/net/sctp/tsnmap.c
+++ b/net/sctp/tsnmap.c
@@ -114,7 +114,8 @@ int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn)
 
 
 /* Mark this TSN as seen.  */
-int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
+int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn,
+		     struct sctp_transport *trans)
 {
 	u16 gap;
 
@@ -133,6 +134,8 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
 		 */
 		map->max_tsn_seen++;
 		map->cumulative_tsn_ack_point++;
+		if (trans)
+			trans->moved_ctsn = 1;
 		map->base_tsn++;
 	} else {
 		/* Either we already have a gap, or about to record a gap, so
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 8a84017..33d8947 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -715,7 +715,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
 	 * can mark it as received so the tsn_map is updated correctly.
 	 */
 	if (sctp_tsnmap_mark(&asoc->peer.tsn_map,
-			     ntohl(chunk->subh.data_hdr->tsn)))
+			     ntohl(chunk->subh.data_hdr->tsn),
+			     chunk->transport))
 		goto fail_mark;
 
 	/* First calculate the padding, so we don't inadvertently
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index f2d1de7..f5a6a4f 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -1051,7 +1051,7 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
 	if (chunk && (freed >= needed)) {
 		__u32 tsn;
 		tsn = ntohl(chunk->subh.data_hdr->tsn);
-		sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn);
+		sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport);
 		sctp_ulpq_tail_data(ulpq, chunk, gfp);
 
 		sctp_ulpq_partial_delivery(ulpq, chunk, gfp);
-- 
1.7.7.6

^ permalink raw reply related

* RE: [PATCH 1/1] atl1c: fix issue of transmit queue 0 timed out
From: Huang, Xiong @ 2012-06-26 20:26 UTC (permalink / raw)
  To: Ben Hutchings, Ren, Cloud
  Cc: davem@davemloft.net, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, qca-linux-team, nic-devel
In-Reply-To: <157393863283F442885425D2C454285623DB4982@NASANEXD02A.na.qualcomm.com>

Sorry, my mean , another fix is to remove netif_stop_queue when cable link is down.

Thanks
Xiong
> -----Original Message-----
> From: Huang, Xiong
> Sent: Wednesday, June 27, 2012 4:25
> To: Ben Hutchings; Ren, Cloud
> Cc: davem@davemloft.net; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; qca-linux-team; nic-devel
> Subject: RE: [PATCH 1/1] atl1c: fix issue of transmit queue 0 timed out
> 
> Yes, another fix to remove netif_stop_queue when cable link is down.
> 
> -Xiong
> 
> > -----Original Message-----
> > From: Ben Hutchings [mailto:bhutchings@solarflare.com]
> > Sent: Wednesday, June 27, 2012 4:24
> > To: Ren, Cloud
> > Cc: davem@davemloft.net; netdev@vger.kernel.org; linux-
> > kernel@vger.kernel.org; qca-linux-team; nic-devel; Huang, Xiong
> > Subject: Re: [PATCH 1/1] atl1c: fix issue of transmit queue 0 timed
> > out
> >
> > On Tue, 2012-06-26 at 12:33 -0300, Ren, Cloud wrote:
> > > From: xiong <xiong@qca.qualcomm.com>
> > >
> > > some people report atl1c could cause system hang with following
> > > kernel trace info:
> > > ---------------------------------------
> > > WARNING: at.../net/sched/sch_generic.c:258
> > > dev_watchdog+0x1db/0x1d0()
> > > ...
> > > NETDEV WATCHDOG: eth0 (atl1c): transmit queue 0 timed out ...
> > > ---------------------------------------
> > > This is caused by netif_stop_queue calling when cable Link is down
> > > but netif_wake_queue isn't called when cable Link is resume.
> > >
> > > Signed-off-by: xiong <xiong@qca.qualcomm.com>
> > > Signed-off-by: Cloud Ren <cjren@qca.qualcomm.com>
> > > ---
> > >  drivers/net/ethernet/atheros/atl1c/atl1c_main.c |    2 ++
> > >  1 files changed, 2 insertions(+), 0 deletions(-)
> > >
> > > diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> > > b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> > > index 85717cb..c2736c4 100644
> > > --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> > > +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> > > @@ -351,6 +351,8 @@ static void atl1c_common_task(struct work_struct
> > *work)
> > >  		atl1c_irq_disable(adapter);
> > >  		atl1c_check_link_status(adapter);
> > >  		atl1c_irq_enable(adapter);
> > > +		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev))
> > > +			netif_wake_queue(netdev);
> > >  	}
> > >  }
> > >
> >
> > Why explicitly stop/start the queue when the link changes?  That's
> > what link_watch is for.
> >
> > Ben.
> >
> > --
> > Ben Hutchings, Staff Engineer, Solarflare Not speaking for my
> > employer; that's the marketing department's job.
> > They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* RE: [PATCH 1/1] atl1c: fix issue of transmit queue 0 timed out
From: Huang, Xiong @ 2012-06-26 20:25 UTC (permalink / raw)
  To: Ben Hutchings, Ren, Cloud
  Cc: davem@davemloft.net, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, qca-linux-team, nic-devel
In-Reply-To: <1340742224.2644.1.camel@bwh-desktop.uk.solarflarecom.com>

Yes, another fix to remove netif_stop_queue when cable link is down.

-Xiong

> -----Original Message-----
> From: Ben Hutchings [mailto:bhutchings@solarflare.com]
> Sent: Wednesday, June 27, 2012 4:24
> To: Ren, Cloud
> Cc: davem@davemloft.net; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; qca-linux-team; nic-devel; Huang, Xiong
> Subject: Re: [PATCH 1/1] atl1c: fix issue of transmit queue 0 timed out
> 
> On Tue, 2012-06-26 at 12:33 -0300, Ren, Cloud wrote:
> > From: xiong <xiong@qca.qualcomm.com>
> >
> > some people report atl1c could cause system hang with following kernel
> > trace info:
> > ---------------------------------------
> > WARNING: at.../net/sched/sch_generic.c:258
> > dev_watchdog+0x1db/0x1d0()
> > ...
> > NETDEV WATCHDOG: eth0 (atl1c): transmit queue 0 timed out ...
> > ---------------------------------------
> > This is caused by netif_stop_queue calling when cable Link is down but
> > netif_wake_queue isn't called when cable Link is resume.
> >
> > Signed-off-by: xiong <xiong@qca.qualcomm.com>
> > Signed-off-by: Cloud Ren <cjren@qca.qualcomm.com>
> > ---
> >  drivers/net/ethernet/atheros/atl1c/atl1c_main.c |    2 ++
> >  1 files changed, 2 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> > b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> > index 85717cb..c2736c4 100644
> > --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> > +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> > @@ -351,6 +351,8 @@ static void atl1c_common_task(struct work_struct
> *work)
> >  		atl1c_irq_disable(adapter);
> >  		atl1c_check_link_status(adapter);
> >  		atl1c_irq_enable(adapter);
> > +		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev))
> > +			netif_wake_queue(netdev);
> >  	}
> >  }
> >
> 
> Why explicitly stop/start the queue when the link changes?  That's what
> link_watch is for.
> 
> Ben.
> 
> --
> Ben Hutchings, Staff Engineer, Solarflare Not speaking for my employer; that's
> the marketing department's job.
> They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* Re: [PATCH 1/1] atl1c: fix issue of transmit queue 0 timed out
From: Ben Hutchings @ 2012-06-26 20:23 UTC (permalink / raw)
  To: Ren, Cloud; +Cc: davem, netdev, linux-kernel, qca-linux-team, nic-devel, xiong
In-Reply-To: <1340724786-3819-1-git-send-email-cjren@qca.qualcomm.com>

On Tue, 2012-06-26 at 12:33 -0300, Ren, Cloud wrote:
> From: xiong <xiong@qca.qualcomm.com>
> 
> some people report atl1c could cause system hang with following
> kernel trace info:
> ---------------------------------------
> WARNING: at.../net/sched/sch_generic.c:258
> dev_watchdog+0x1db/0x1d0()
> ...
> NETDEV WATCHDOG: eth0 (atl1c): transmit queue 0 timed out
> ...
> ---------------------------------------
> This is caused by netif_stop_queue calling when cable Link is down
> but netif_wake_queue isn't called when cable Link is resume.
> 
> Signed-off-by: xiong <xiong@qca.qualcomm.com>
> Signed-off-by: Cloud Ren <cjren@qca.qualcomm.com>
> ---
>  drivers/net/ethernet/atheros/atl1c/atl1c_main.c |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> index 85717cb..c2736c4 100644
> --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> @@ -351,6 +351,8 @@ static void atl1c_common_task(struct work_struct *work)
>  		atl1c_irq_disable(adapter);
>  		atl1c_check_link_status(adapter);
>  		atl1c_irq_enable(adapter);
> +		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev))
> +			netif_wake_queue(netdev);
>  	}
>  }
>  

Why explicitly stop/start the queue when the link changes?  That's what
link_watch is for.

Ben.

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

^ permalink raw reply

* Re: [PATCH 11/16] netvm: Propagate page->pfmemalloc from skb_alloc_page to skb
From: Sebastian Andrzej Siewior @ 2012-06-26 20:13 UTC (permalink / raw)
  To: Mel Gorman
  Cc: Andrew Morton, Linux-MM, Linux-Netdev, LKML, David Miller,
	Neil Brown, Peter Zijlstra, Mike Christie, Eric B Munson,
	Eric Dumazet
In-Reply-To: <1340375443-22455-12-git-send-email-mgorman@suse.de>

On Fri, Jun 22, 2012 at 03:30:38PM +0100, Mel Gorman wrote:
>  drivers/net/ethernet/chelsio/cxgb4/sge.c          |    2 +-
>  drivers/net/ethernet/chelsio/cxgb4vf/sge.c        |    2 +-
>  drivers/net/ethernet/intel/igb/igb_main.c         |    2 +-
>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |    4 +-
>  drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |    3 +-
>  drivers/net/usb/cdc-phonet.c                      |    2 +-
>  drivers/usb/gadget/f_phonet.c                     |    2 +-

You did not touch all drivers which use alloc_page(s)() like e1000(e). Was
this on purpose?

Sebastian

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH net-next] em_canid: Ematch rule to match CAN frames according to their CAN IDs
From: Oliver Hartkopp @ 2012-06-26 20:07 UTC (permalink / raw)
  To: Rostislav Lisovy, Eric Dumazet; +Cc: netdev, linux-can, lartc, pisa, sojkam1
In-Reply-To: <1340022131-7827-1-git-send-email-lisovy@gmail.com>

Hello Rostislav,

thanks for the new patch. It got indeed pretty short now :-)

I found some time for a review. See details inline ...

On 18.06.2012 14:22, Rostislav Lisovy wrote:


> 
> With no extra filter/qdisc configured, median of the time spent in can_send()
> was about 27 us -- with prio qdisc with 5 bands and 5 appropriate cls_can
> filters (previous patch), it was about 30 us -- with prio qdisc with 5 bands
> and 5 appropriate em_can filters (this patch), it was about 34 us.


Hm that's more than twice the time consumed for classification ...

cls_can: 3 us more
em_can:  7 us more

@Eric: Is this still the better approach then?


> diff --git a/net/sched/Kconfig b/net/sched/Kconfig
> index 75b58f8..bc0ceab 100644
> --- a/net/sched/Kconfig
> +++ b/net/sched/Kconfig
> @@ -485,6 +485,16 @@ config NET_EMATCH_TEXT
>  	  To compile this code as a module, choose M here: the
>  	  module will be called em_text.
>  
> +config NET_EMATCH_CANID
> +	tristate "CAN ID"


i would prefer

tristate "Controller Area Network Identifier"

or at least

tristate "CAN Identifier"

> +	depends on NET_EMATCH && CAN
> +	---help---
> +          Say Y here if you want to be able to classify CAN frames based
> +          on CAN ID.


"on the CAN Identifier."

(..)

> +#include <net/pkt_cls.h>
> +#include <linux/can.h>
> +
> +#define EM_CAN_RULES_SIZE				32


Reduce the gap before '32' to one single space.

(..)

> +static int em_canid_match(struct sk_buff *skb, struct tcf_ematch *m,
> +			 struct tcf_pkt_info *info)
> +{
> +	struct canid_match *cm = em_canid_priv(m);
> +	canid_t can_id;
> +	unsigned int match = false;


You use test_bit() below which returns an int.

Better use int instead of unsigned int ...

int match = 0;


> +	int i;
> +
> +	can_id = em_canid_get_id(skb);
> +
> +	if (can_id & CAN_EFF_FLAG) {
> +		can_id &= CAN_EFF_MASK;
> +
> +		for (i = 0; i < cm->eff_rules_count; i++) {
> +			if (!(((cm->rules_raw[i].can_id ^ can_id) &
> +			    cm->rules_raw[i].can_mask) & CAN_EFF_MASK)) {


Looks really tricky. I'm still pondering if it does what it should do ...

> +				match = true;


match = 1;

> +				break;
> +			}
> +		}
> +	} else { /* SFF */
> +		can_id &= CAN_SFF_MASK;
> +		match = test_bit(can_id, cm->match_sff);
> +	}
> +


return match;


> +	if (match)
> +		return 1;
> +
> +	return 0;
> +}
> +
> +static int em_canid_change(struct tcf_proto *tp, void *data, int len,
> +			  struct tcf_ematch *m)
> +{
> +	struct can_filter *conf = data; /* Array with rules,
> +					 * fixed size EM_CAN_RULES_SIZE
> +					 */
> +	struct canid_match *cm;
> +	int err;
> +	int i;
> +
> +	if (len < sizeof(struct can_filter))
> +		return -EINVAL;


if (len % sizeof(struct can_filter))
	return -EINVAL;

if (len > sizeof(struct can_filter) * EM_CAN_RULES_SIZE)
	return -EINVAL;

All checks done before kzalloc() => no need for error cleanups at the end of
the function.

> +
> +	err = -ENOBUFS;


remove

> +	cm = kzalloc(sizeof(*cm), GFP_KERNEL);
> +	if (cm == NULL)


if (!cm)
	return -ENOMEM;

> +		goto errout;


The only user of errout - to be removed.

> +
> +	cm->sff_rules_count = 0;
> +	cm->eff_rules_count = 0;
> +	cm->rules_count = len/sizeof(struct can_filter);


> +	err = -EINVAL;

remove

> +
> +	/* Be sure to fit into the array */
> +	if (cm->rules_count > EM_CAN_RULES_SIZE)
> +		goto errout_free;


already checked before => remove

> +
> +	/*
> +	 * We need two for() loops for copying rules into
> +	 * two contiguous areas in rules_raw
> +	 */
> +
> +	/* Process EFF frame rules*/
> +	for (i = 0; i < cm->rules_count; i++) {
> +		if ((conf[i].can_id & CAN_EFF_FLAG) &&
> +		    (conf[i].can_mask & CAN_EFF_FLAG)) {
> +			memcpy(cm->rules_raw + cm->eff_rules_count,


Oops. Shouldn't this be

cm->rules_raw + cm->eff_rules_count * sizeof(struct can_filter),

???

> +				&conf[i],
> +				sizeof(struct can_filter));
> +
> +			cm->eff_rules_count++;
> +		} else {
> +			continue;
> +		}


omit { } around continue

> +	}
> +
> +	/* Process SFF frame rules */
> +	for (i = 0; i < cm->rules_count; i++) {
> +		if ((conf[i].can_id & CAN_EFF_FLAG) &&
> +		    (conf[i].can_mask & CAN_EFF_FLAG)) {


What if CAN_EFF_FLAG is set in can_id but not in can_mask ?

> +			continue;
> +		} else {
> +			memcpy(cm->rules_raw
> +				+ cm->eff_rules_count
> +				+ cm->sff_rules_count,


dito

cm->rules_raw + (cm->eff_rules_count + cm->sff_rules_count) * sizeof(struct
can_filter),

???


> +				&conf[i], sizeof(struct can_filter));
> +
> +			cm->sff_rules_count++;
> +
> +			em_canid_sff_match_add(cm,
> +				conf[i].can_id, conf[i].can_mask);
> +		}
> +	}
> +
> +	m->datalen = sizeof(*cm);
> +	m->data = (unsigned long) cm;
> +
> +	return 0;
> +
> +errout_free:
> +	kfree(cm);
> +errout:
> +	return err;


error handling can be removed with the above changes.

> +}
> +
> +static void em_canid_destroy(struct tcf_proto *tp, struct tcf_ematch *m)
> +{
> +	struct canid_match *cm = em_canid_priv(m);
> +


Check for cm == NULL not needed ?

> +	kfree(cm);
> +}
> +
> +static int em_canid_dump(struct sk_buff *skb, struct tcf_ematch *m)
> +{
> +	struct canid_match *cm = em_canid_priv(m);
> +


Check for cm == NULL not needed ?

Can a dump happen before the matches are added??

> +	/*
> +	 * When configuring this ematch 'rules_count' is set not to exceed
> +	 * 'rules_raw' array size
> +	 */
> +	if (nla_put_nohdr(skb, sizeof(cm->rules_raw[0]) * cm->rules_count,


better sizeof(struct can_filter) instead of sizeof(cm->rules_raw[0]) ??

> +	    &cm->rules_raw) < 0)
> +		goto nla_put_failure;
> +
> +	return 0;
> +
> +nla_put_failure:
> +	return -1;
> +}
> +
> +static struct tcf_ematch_ops em_canid_ops = {
> +	.kind	  = TCF_EM_CANID,
> +	.change	  = em_canid_change,
> +	.match	  = em_canid_match,
> +	.destroy  = em_canid_destroy,
> +	.dump	  = em_canid_dump,
> +	.owner	  = THIS_MODULE,
> +	.link	  = LIST_HEAD_INIT(em_canid_ops.link)
> +};
> +
> +static int __init init_em_canid(void)
> +{
> +	return tcf_em_register(&em_canid_ops);
> +}
> +
> +static void __exit exit_em_canid(void)
> +{
> +	tcf_em_unregister(&em_canid_ops);
> +}
> +
> +MODULE_LICENSE("GPL");
> +
> +module_init(init_em_canid);
> +module_exit(exit_em_canid);
> +
> +MODULE_ALIAS_TCF_EMATCH(TCF_EM_CANID);


Regards,
Oliver

^ permalink raw reply

* [RFC] iwmc3200top: remove driver for unavailable hardware
From: John W. Linville @ 2012-06-26 19:53 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: samuel.ortiz-ral2JQCrhuEAvxtiuMwx3w,
	inaky.perez-gonzalez-ral2JQCrhuEAvxtiuMwx3w,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA, John W. Linville

From: "John W. Linville" <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>

This hardware never became available to normal humans.  Leaving this
driver imposes unwelcome maintenance costs for no clear benefit.

Signed-off-by: John W. Linville <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
---
Can't remove this just yet, as it is selected by the i2400m wimax
driver.  The 3200 bits of that driver seem a bit intertwined with the
rest of the driver.

Are there any other SDIO parts for i2400m?  Does anyone have any other
guidance on how I can safely make i2400m be independent of iwmc3200
support?

 drivers/misc/Kconfig                   |    1 -
 drivers/misc/Makefile                  |    1 -
 drivers/misc/iwmc3200top/Kconfig       |   20 -
 drivers/misc/iwmc3200top/Makefile      |   29 --
 drivers/misc/iwmc3200top/debugfs.c     |  137 -------
 drivers/misc/iwmc3200top/debugfs.h     |   58 ---
 drivers/misc/iwmc3200top/fw-download.c |  358 -----------------
 drivers/misc/iwmc3200top/fw-msg.h      |  113 ------
 drivers/misc/iwmc3200top/iwmc3200top.h |  205 ----------
 drivers/misc/iwmc3200top/log.c         |  348 -----------------
 drivers/misc/iwmc3200top/log.h         |  171 ---------
 drivers/misc/iwmc3200top/main.c        |  662 --------------------------------
 12 files changed, 2103 deletions(-)
 delete mode 100644 drivers/misc/iwmc3200top/Kconfig
 delete mode 100644 drivers/misc/iwmc3200top/Makefile
 delete mode 100644 drivers/misc/iwmc3200top/debugfs.c
 delete mode 100644 drivers/misc/iwmc3200top/debugfs.h
 delete mode 100644 drivers/misc/iwmc3200top/fw-download.c
 delete mode 100644 drivers/misc/iwmc3200top/fw-msg.h
 delete mode 100644 drivers/misc/iwmc3200top/iwmc3200top.h
 delete mode 100644 drivers/misc/iwmc3200top/log.c
 delete mode 100644 drivers/misc/iwmc3200top/log.h
 delete mode 100644 drivers/misc/iwmc3200top/main.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2661f6e..154f3ef 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -511,7 +511,6 @@ config USB_SWITCH_FSA9480
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
-source "drivers/misc/iwmc3200top/Kconfig"
 source "drivers/misc/ti-st/Kconfig"
 source "drivers/misc/lis3lv02d/Kconfig"
 source "drivers/misc/carma/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 456972f..b88df7a 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -36,7 +36,6 @@ obj-$(CONFIG_EP93XX_PWM)	+= ep93xx_pwm.o
 obj-$(CONFIG_DS1682)		+= ds1682.o
 obj-$(CONFIG_TI_DAC7512)	+= ti_dac7512.o
 obj-$(CONFIG_C2PORT)		+= c2port/
-obj-$(CONFIG_IWMC3200TOP)      += iwmc3200top/
 obj-$(CONFIG_HMC6352)		+= hmc6352.o
 obj-y				+= eeprom/
 obj-y				+= cb710/
diff --git a/drivers/misc/iwmc3200top/Kconfig b/drivers/misc/iwmc3200top/Kconfig
deleted file mode 100644
index 9e4b88f..0000000
--- a/drivers/misc/iwmc3200top/Kconfig
+++ /dev/null
@@ -1,20 +0,0 @@
-config IWMC3200TOP
-        tristate "Intel Wireless MultiCom Top Driver"
-        depends on MMC && EXPERIMENTAL
-        select FW_LOADER
-	---help---
-	  Intel Wireless MultiCom 3200 Top driver is responsible for
-	  for firmware load and enabled coms enumeration
-
-config IWMC3200TOP_DEBUG
-	bool "Enable full debug output of iwmc3200top Driver"
-	depends on IWMC3200TOP
-	---help---
-	  Enable full debug output of iwmc3200top Driver
-
-config IWMC3200TOP_DEBUGFS
-	bool "Enable Debugfs debugging interface for iwmc3200top"
-	depends on IWMC3200TOP
-	---help---
-	  Enable creation of debugfs files for iwmc3200top
-
diff --git a/drivers/misc/iwmc3200top/Makefile b/drivers/misc/iwmc3200top/Makefile
deleted file mode 100644
index fbf53fb..0000000
--- a/drivers/misc/iwmc3200top/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-# iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
-# drivers/misc/iwmc3200top/Makefile
-#
-# Copyright (C) 2009 Intel Corporation. All rights reserved.
-#
-# 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.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-#
-#
-# Author Name: Maxim Grabarnik <maxim.grabarnink-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
-#  -
-#
-#
-
-obj-$(CONFIG_IWMC3200TOP)	+= iwmc3200top.o
-iwmc3200top-objs	:= main.o fw-download.o
-iwmc3200top-$(CONFIG_IWMC3200TOP_DEBUG) += log.o
-iwmc3200top-$(CONFIG_IWMC3200TOP_DEBUGFS) += debugfs.o
diff --git a/drivers/misc/iwmc3200top/debugfs.c b/drivers/misc/iwmc3200top/debugfs.c
deleted file mode 100644
index 62fbaec..0000000
--- a/drivers/misc/iwmc3200top/debugfs.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/debufs.c
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
- *  -
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio.h>
-#include <linux/debugfs.h>
-
-#include "iwmc3200top.h"
-#include "fw-msg.h"
-#include "log.h"
-#include "debugfs.h"
-
-
-
-/*      Constants definition        */
-#define HEXADECIMAL_RADIX	16
-
-/*      Functions definition        */
-
-
-#define DEBUGFS_ADD(name, parent) do {					\
-	dbgfs->dbgfs_##parent##_files.file_##name =			\
-	debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv,	\
-				&iwmct_dbgfs_##name##_ops);		\
-} while (0)
-
-#define DEBUGFS_RM(name)  do {		\
-	debugfs_remove(name);		\
-	name = NULL;			\
-} while (0)
-
-#define DEBUGFS_READ_FUNC(name)						\
-ssize_t iwmct_dbgfs_##name##_read(struct file *file,			\
-				  char __user *user_buf,		\
-				  size_t count, loff_t *ppos);
-
-#define DEBUGFS_WRITE_FUNC(name)					\
-ssize_t iwmct_dbgfs_##name##_write(struct file *file,			\
-				   const char __user *user_buf,		\
-				   size_t count, loff_t *ppos);
-
-#define DEBUGFS_READ_FILE_OPS(name)					\
-	DEBUGFS_READ_FUNC(name)						\
-	static const struct file_operations iwmct_dbgfs_##name##_ops = {  \
-		.read = iwmct_dbgfs_##name##_read,			\
-		.open = iwmct_dbgfs_open_file_generic,			\
-		.llseek = generic_file_llseek,				\
-	};
-
-#define DEBUGFS_WRITE_FILE_OPS(name)					\
-	DEBUGFS_WRITE_FUNC(name)					\
-	static const struct file_operations iwmct_dbgfs_##name##_ops = {  \
-		.write = iwmct_dbgfs_##name##_write,			\
-		.open = iwmct_dbgfs_open_file_generic,			\
-		.llseek = generic_file_llseek,				\
-	};
-
-#define DEBUGFS_READ_WRITE_FILE_OPS(name)				\
-	DEBUGFS_READ_FUNC(name)						\
-	DEBUGFS_WRITE_FUNC(name)					\
-	static const struct file_operations iwmct_dbgfs_##name##_ops = {\
-		.write = iwmct_dbgfs_##name##_write,			\
-		.read = iwmct_dbgfs_##name##_read,			\
-		.open = iwmct_dbgfs_open_file_generic,			\
-		.llseek = generic_file_llseek,				\
-	};
-
-
-/*      Debugfs file ops definitions        */
-
-/*
- * Create the debugfs files and directories
- *
- */
-void iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name)
-{
-	struct iwmct_debugfs *dbgfs;
-
-	dbgfs = kzalloc(sizeof(struct iwmct_debugfs), GFP_KERNEL);
-	if (!dbgfs) {
-		LOG_ERROR(priv, DEBUGFS, "failed to allocate %zd bytes\n",
-					sizeof(struct iwmct_debugfs));
-		return;
-	}
-
-	priv->dbgfs = dbgfs;
-	dbgfs->name = name;
-	dbgfs->dir_drv = debugfs_create_dir(name, NULL);
-	if (!dbgfs->dir_drv) {
-		LOG_ERROR(priv, DEBUGFS, "failed to create debugfs dir\n");
-		return;
-	}
-
-	return;
-}
-
-/**
- * Remove the debugfs files and directories
- *
- */
-void iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs)
-{
-	if (!dbgfs)
-		return;
-
-	DEBUGFS_RM(dbgfs->dir_drv);
-	kfree(dbgfs);
-	dbgfs = NULL;
-}
-
diff --git a/drivers/misc/iwmc3200top/debugfs.h b/drivers/misc/iwmc3200top/debugfs.h
deleted file mode 100644
index 71d4575..0000000
--- a/drivers/misc/iwmc3200top/debugfs.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/debufs.h
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
- *  -
- *
- */
-
-#ifndef __DEBUGFS_H__
-#define __DEBUGFS_H__
-
-
-#ifdef CONFIG_IWMC3200TOP_DEBUGFS
-
-struct iwmct_debugfs {
-	const char *name;
-	struct dentry *dir_drv;
-	struct dir_drv_files {
-	} dbgfs_drv_files;
-};
-
-void iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name);
-void iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs);
-
-#else /* CONFIG_IWMC3200TOP_DEBUGFS */
-
-struct iwmct_debugfs;
-
-static inline void
-iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name)
-{}
-
-static inline void
-iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs)
-{}
-
-#endif /* CONFIG_IWMC3200TOP_DEBUGFS */
-
-#endif /* __DEBUGFS_H__ */
-
diff --git a/drivers/misc/iwmc3200top/fw-download.c b/drivers/misc/iwmc3200top/fw-download.c
deleted file mode 100644
index e27afde..0000000
--- a/drivers/misc/iwmc3200top/fw-download.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/fw-download.c
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
- *  -
- *
- */
-
-#include <linux/firmware.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/slab.h>
-#include <asm/unaligned.h>
-
-#include "iwmc3200top.h"
-#include "log.h"
-#include "fw-msg.h"
-
-#define CHECKSUM_BYTES_NUM sizeof(u32)
-
-/**
-  init parser struct with file
- */
-static int iwmct_fw_parser_init(struct iwmct_priv *priv, const u8 *file,
-			      size_t file_size, size_t block_size)
-{
-	struct iwmct_parser *parser = &priv->parser;
-	struct iwmct_fw_hdr *fw_hdr = &parser->versions;
-
-	LOG_TRACE(priv, FW_DOWNLOAD, "-->\n");
-
-	LOG_INFO(priv, FW_DOWNLOAD, "file_size=%zd\n", file_size);
-
-	parser->file = file;
-	parser->file_size = file_size;
-	parser->cur_pos = 0;
-	parser->entry_point = 0;
-	parser->buf = kzalloc(block_size, GFP_KERNEL);
-	if (!parser->buf) {
-		LOG_ERROR(priv, FW_DOWNLOAD, "kzalloc error\n");
-		return -ENOMEM;
-	}
-	parser->buf_size = block_size;
-
-	/* extract fw versions */
-	memcpy(fw_hdr, parser->file, sizeof(struct iwmct_fw_hdr));
-	LOG_INFO(priv, FW_DOWNLOAD, "fw versions are:\n"
-		"top %u.%u.%u gps %u.%u.%u bt %u.%u.%u tic %s\n",
-		fw_hdr->top_major, fw_hdr->top_minor, fw_hdr->top_revision,
-		fw_hdr->gps_major, fw_hdr->gps_minor, fw_hdr->gps_revision,
-		fw_hdr->bt_major, fw_hdr->bt_minor, fw_hdr->bt_revision,
-		fw_hdr->tic_name);
-
-	parser->cur_pos += sizeof(struct iwmct_fw_hdr);
-
-	LOG_TRACE(priv, FW_DOWNLOAD, "<--\n");
-	return 0;
-}
-
-static bool iwmct_checksum(struct iwmct_priv *priv)
-{
-	struct iwmct_parser *parser = &priv->parser;
-	__le32 *file = (__le32 *)parser->file;
-	int i, pad, steps;
-	u32 accum = 0;
-	u32 checksum;
-	u32 mask = 0xffffffff;
-
-	pad = (parser->file_size - CHECKSUM_BYTES_NUM) % 4;
-	steps =  (parser->file_size - CHECKSUM_BYTES_NUM) / 4;
-
-	LOG_INFO(priv, FW_DOWNLOAD, "pad=%d steps=%d\n", pad, steps);
-
-	for (i = 0; i < steps; i++)
-		accum += le32_to_cpu(file[i]);
-
-	if (pad) {
-		mask <<= 8 * (4 - pad);
-		accum += le32_to_cpu(file[steps]) & mask;
-	}
-
-	checksum = get_unaligned_le32((__le32 *)(parser->file +
-			parser->file_size - CHECKSUM_BYTES_NUM));
-
-	LOG_INFO(priv, FW_DOWNLOAD,
-		"compare checksum accum=0x%x to checksum=0x%x\n",
-		accum, checksum);
-
-	return checksum == accum;
-}
-
-static int iwmct_parse_next_section(struct iwmct_priv *priv, const u8 **p_sec,
-				  size_t *sec_size, __le32 *sec_addr)
-{
-	struct iwmct_parser *parser = &priv->parser;
-	struct iwmct_dbg *dbg = &priv->dbg;
-	struct iwmct_fw_sec_hdr *sec_hdr;
-
-	LOG_TRACE(priv, FW_DOWNLOAD, "-->\n");
-
-	while (parser->cur_pos + sizeof(struct iwmct_fw_sec_hdr)
-		<= parser->file_size) {
-
-		sec_hdr = (struct iwmct_fw_sec_hdr *)
-				(parser->file + parser->cur_pos);
-		parser->cur_pos += sizeof(struct iwmct_fw_sec_hdr);
-
-		LOG_INFO(priv, FW_DOWNLOAD,
-			"sec hdr: type=%s addr=0x%x size=%d\n",
-			sec_hdr->type, sec_hdr->target_addr,
-			sec_hdr->data_size);
-
-		if (strcmp(sec_hdr->type, "ENT") == 0)
-			parser->entry_point = le32_to_cpu(sec_hdr->target_addr);
-		else if (strcmp(sec_hdr->type, "LBL") == 0)
-			strcpy(dbg->label_fw, parser->file + parser->cur_pos);
-		else if (((strcmp(sec_hdr->type, "TOP") == 0) &&
-			  (priv->barker & BARKER_DNLOAD_TOP_MSK)) ||
-			 ((strcmp(sec_hdr->type, "GPS") == 0) &&
-			  (priv->barker & BARKER_DNLOAD_GPS_MSK)) ||
-			 ((strcmp(sec_hdr->type, "BTH") == 0) &&
-			  (priv->barker & BARKER_DNLOAD_BT_MSK))) {
-			*sec_addr = sec_hdr->target_addr;
-			*sec_size = le32_to_cpu(sec_hdr->data_size);
-			*p_sec = parser->file + parser->cur_pos;
-			parser->cur_pos += le32_to_cpu(sec_hdr->data_size);
-			return 1;
-		} else if (strcmp(sec_hdr->type, "LOG") != 0)
-			LOG_WARNING(priv, FW_DOWNLOAD,
-				    "skipping section type %s\n",
-				    sec_hdr->type);
-
-		parser->cur_pos += le32_to_cpu(sec_hdr->data_size);
-		LOG_INFO(priv, FW_DOWNLOAD,
-			"finished with section cur_pos=%zd\n", parser->cur_pos);
-	}
-
-	LOG_TRACE(priv, INIT, "<--\n");
-	return 0;
-}
-
-static int iwmct_download_section(struct iwmct_priv *priv, const u8 *p_sec,
-				size_t sec_size, __le32 addr)
-{
-	struct iwmct_parser *parser = &priv->parser;
-	struct iwmct_fw_load_hdr *hdr = (struct iwmct_fw_load_hdr *)parser->buf;
-	const u8 *cur_block = p_sec;
-	size_t sent = 0;
-	int cnt = 0;
-	int ret = 0;
-	u32 cmd = 0;
-
-	LOG_TRACE(priv, FW_DOWNLOAD, "-->\n");
-	LOG_INFO(priv, FW_DOWNLOAD, "Download address 0x%x size 0x%zx\n",
-				addr, sec_size);
-
-	while (sent < sec_size) {
-		int i;
-		u32 chksm = 0;
-		u32 reset = atomic_read(&priv->reset);
-		/* actual FW data */
-		u32 data_size = min(parser->buf_size - sizeof(*hdr),
-				    sec_size - sent);
-		/* Pad to block size */
-		u32 trans_size = (data_size + sizeof(*hdr) +
-				  IWMC_SDIO_BLK_SIZE - 1) &
-				  ~(IWMC_SDIO_BLK_SIZE - 1);
-		++cnt;
-
-		/* in case of reset, interrupt FW DOWNLAOD */
-		if (reset) {
-			LOG_INFO(priv, FW_DOWNLOAD,
-				 "Reset detected. Abort FW download!!!");
-			ret = -ECANCELED;
-			goto exit;
-		}
-
-		memset(parser->buf, 0, parser->buf_size);
-		cmd |= IWMC_OPCODE_WRITE << CMD_HDR_OPCODE_POS;
-		cmd |= IWMC_CMD_SIGNATURE << CMD_HDR_SIGNATURE_POS;
-		cmd |= (priv->dbg.direct ? 1 : 0) << CMD_HDR_DIRECT_ACCESS_POS;
-		cmd |= (priv->dbg.checksum ? 1 : 0) << CMD_HDR_USE_CHECKSUM_POS;
-		hdr->data_size = cpu_to_le32(data_size);
-		hdr->target_addr = addr;
-
-		/* checksum is allowed for sizes divisible by 4 */
-		if (data_size & 0x3)
-			cmd &= ~CMD_HDR_USE_CHECKSUM_MSK;
-
-		memcpy(hdr->data, cur_block, data_size);
-
-
-		if (cmd & CMD_HDR_USE_CHECKSUM_MSK) {
-
-			chksm = data_size + le32_to_cpu(addr) + cmd;
-			for (i = 0; i < data_size >> 2; i++)
-				chksm += ((u32 *)cur_block)[i];
-
-			hdr->block_chksm = cpu_to_le32(chksm);
-			LOG_INFO(priv, FW_DOWNLOAD, "Checksum = 0x%X\n",
-				 hdr->block_chksm);
-		}
-
-		LOG_INFO(priv, FW_DOWNLOAD, "trans#%d, len=%d, sent=%zd, "
-				"sec_size=%zd, startAddress 0x%X\n",
-				cnt, trans_size, sent, sec_size, addr);
-
-		if (priv->dbg.dump)
-			LOG_HEXDUMP(FW_DOWNLOAD, parser->buf, trans_size);
-
-
-		hdr->cmd = cpu_to_le32(cmd);
-		/* send it down */
-		/* TODO: add more proper sending and error checking */
-		ret = iwmct_tx(priv, parser->buf, trans_size);
-		if (ret != 0) {
-			LOG_INFO(priv, FW_DOWNLOAD,
-				"iwmct_tx returned %d\n", ret);
-			goto exit;
-		}
-
-		addr = cpu_to_le32(le32_to_cpu(addr) + data_size);
-		sent += data_size;
-		cur_block = p_sec + sent;
-
-		if (priv->dbg.blocks && (cnt + 1) >= priv->dbg.blocks) {
-			LOG_INFO(priv, FW_DOWNLOAD,
-				"Block number limit is reached [%d]\n",
-				priv->dbg.blocks);
-			break;
-		}
-	}
-
-	if (sent < sec_size)
-		ret = -EINVAL;
-exit:
-	LOG_TRACE(priv, FW_DOWNLOAD, "<--\n");
-	return ret;
-}
-
-static int iwmct_kick_fw(struct iwmct_priv *priv, bool jump)
-{
-	struct iwmct_parser *parser = &priv->parser;
-	struct iwmct_fw_load_hdr *hdr = (struct iwmct_fw_load_hdr *)parser->buf;
-	int ret;
-	u32 cmd;
-
-	LOG_TRACE(priv, FW_DOWNLOAD, "-->\n");
-
-	memset(parser->buf, 0, parser->buf_size);
-	cmd = IWMC_CMD_SIGNATURE << CMD_HDR_SIGNATURE_POS;
-	if (jump) {
-		cmd |= IWMC_OPCODE_JUMP << CMD_HDR_OPCODE_POS;
-		hdr->target_addr = cpu_to_le32(parser->entry_point);
-		LOG_INFO(priv, FW_DOWNLOAD, "jump address 0x%x\n",
-				parser->entry_point);
-	} else {
-		cmd |= IWMC_OPCODE_LAST_COMMAND << CMD_HDR_OPCODE_POS;
-		LOG_INFO(priv, FW_DOWNLOAD, "last command\n");
-	}
-
-	hdr->cmd = cpu_to_le32(cmd);
-
-	LOG_HEXDUMP(FW_DOWNLOAD, parser->buf, sizeof(*hdr));
-	/* send it down */
-	/* TODO: add more proper sending and error checking */
-	ret = iwmct_tx(priv, parser->buf, IWMC_SDIO_BLK_SIZE);
-	if (ret)
-		LOG_INFO(priv, FW_DOWNLOAD, "iwmct_tx returned %d", ret);
-
-	LOG_TRACE(priv, FW_DOWNLOAD, "<--\n");
-	return 0;
-}
-
-int iwmct_fw_load(struct iwmct_priv *priv)
-{
-	const u8 *fw_name = FW_NAME(FW_API_VER);
-	const struct firmware *raw;
-	const u8 *pdata;
-	size_t len;
-	__le32 addr;
-	int ret;
-
-
-	LOG_INFO(priv, FW_DOWNLOAD, "barker download request 0x%x is:\n",
-			priv->barker);
-	LOG_INFO(priv, FW_DOWNLOAD, "*******  Top FW %s requested ********\n",
-			(priv->barker & BARKER_DNLOAD_TOP_MSK) ? "was" : "not");
-	LOG_INFO(priv, FW_DOWNLOAD, "*******  GPS FW %s requested ********\n",
-			(priv->barker & BARKER_DNLOAD_GPS_MSK) ? "was" : "not");
-	LOG_INFO(priv, FW_DOWNLOAD, "*******  BT FW %s requested ********\n",
-			(priv->barker & BARKER_DNLOAD_BT_MSK) ? "was" : "not");
-
-
-	/* get the firmware */
-	ret = request_firmware(&raw, fw_name, &priv->func->dev);
-	if (ret < 0) {
-		LOG_ERROR(priv, FW_DOWNLOAD, "%s request_firmware failed %d\n",
-			  fw_name, ret);
-		goto exit;
-	}
-
-	if (raw->size < sizeof(struct iwmct_fw_sec_hdr)) {
-		LOG_ERROR(priv, FW_DOWNLOAD, "%s smaller then (%zd) (%zd)\n",
-			  fw_name, sizeof(struct iwmct_fw_sec_hdr), raw->size);
-		goto exit;
-	}
-
-	LOG_INFO(priv, FW_DOWNLOAD, "Read firmware '%s'\n", fw_name);
-
-	/* clear parser struct */
-	ret = iwmct_fw_parser_init(priv, raw->data, raw->size, priv->trans_len);
-	if (ret < 0) {
-		LOG_ERROR(priv, FW_DOWNLOAD,
-			  "iwmct_parser_init failed: Reason %d\n", ret);
-		goto exit;
-	}
-
-	if (!iwmct_checksum(priv)) {
-		LOG_ERROR(priv, FW_DOWNLOAD, "checksum error\n");
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	/* download firmware to device */
-	while (iwmct_parse_next_section(priv, &pdata, &len, &addr)) {
-		ret = iwmct_download_section(priv, pdata, len, addr);
-		if (ret) {
-			LOG_ERROR(priv, FW_DOWNLOAD,
-				  "%s download section failed\n", fw_name);
-			goto exit;
-		}
-	}
-
-	ret = iwmct_kick_fw(priv, !!(priv->barker & BARKER_DNLOAD_JUMP_MSK));
-
-exit:
-	kfree(priv->parser.buf);
-	release_firmware(raw);
-	return ret;
-}
diff --git a/drivers/misc/iwmc3200top/fw-msg.h b/drivers/misc/iwmc3200top/fw-msg.h
deleted file mode 100644
index 9e26b75..0000000
--- a/drivers/misc/iwmc3200top/fw-msg.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/fw-msg.h
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
- *  -
- *
- */
-
-#ifndef __FWMSG_H__
-#define __FWMSG_H__
-
-#define COMM_TYPE_D2H           	0xFF
-#define COMM_TYPE_H2D           	0xEE
-
-#define COMM_CATEGORY_OPERATIONAL      	0x00
-#define COMM_CATEGORY_DEBUG            	0x01
-#define COMM_CATEGORY_TESTABILITY      	0x02
-#define COMM_CATEGORY_DIAGNOSTICS      	0x03
-
-#define OP_DBG_ZSTR_MSG			cpu_to_le16(0x1A)
-
-#define FW_LOG_SRC_MAX			32
-#define FW_LOG_SRC_ALL			255
-
-#define FW_STRING_TABLE_ADDR		cpu_to_le32(0x0C000000)
-
-#define CMD_DBG_LOG_LEVEL		cpu_to_le16(0x0001)
-#define CMD_TST_DEV_RESET		cpu_to_le16(0x0060)
-#define CMD_TST_FUNC_RESET		cpu_to_le16(0x0062)
-#define CMD_TST_IFACE_RESET		cpu_to_le16(0x0064)
-#define CMD_TST_CPU_UTILIZATION		cpu_to_le16(0x0065)
-#define CMD_TST_TOP_DEEP_SLEEP		cpu_to_le16(0x0080)
-#define CMD_TST_WAKEUP			cpu_to_le16(0x0081)
-#define CMD_TST_FUNC_WAKEUP		cpu_to_le16(0x0082)
-#define CMD_TST_FUNC_DEEP_SLEEP_REQUEST	cpu_to_le16(0x0083)
-#define CMD_TST_GET_MEM_DUMP		cpu_to_le16(0x0096)
-
-#define OP_OPR_ALIVE			cpu_to_le16(0x0010)
-#define OP_OPR_CMD_ACK			cpu_to_le16(0x001F)
-#define OP_OPR_CMD_NACK			cpu_to_le16(0x0020)
-#define OP_TST_MEM_DUMP			cpu_to_le16(0x0043)
-
-#define CMD_FLAG_PADDING_256		0x80
-
-#define FW_HCMD_BLOCK_SIZE      	256
-
-struct msg_hdr {
-	u8 type;
-	u8 category;
-	__le16 opcode;
-	u8 seqnum;
-	u8 flags;
-	__le16 length;
-} __attribute__((__packed__));
-
-struct log_hdr {
-	__le32 timestamp;
-	u8 severity;
-	u8 logsource;
-	__le16 reserved;
-} __attribute__((__packed__));
-
-struct mdump_hdr {
-	u8 dmpid;
-	u8 frag;
-	__le16 size;
-	__le32 addr;
-} __attribute__((__packed__));
-
-struct top_msg {
-	struct msg_hdr hdr;
-	union {
-		/* D2H messages */
-		struct {
-			struct log_hdr log_hdr;
-			u8 data[1];
-		} __attribute__((__packed__)) log;
-
-		struct {
-			struct log_hdr log_hdr;
-			struct mdump_hdr md_hdr;
-			u8 data[1];
-		} __attribute__((__packed__)) mdump;
-
-		/* H2D messages */
-		struct {
-			u8 logsource;
-			u8 sevmask;
-		} __attribute__((__packed__)) logdefs[FW_LOG_SRC_MAX];
-		struct mdump_hdr mdump_req;
-	} u;
-} __attribute__((__packed__));
-
-
-#endif /* __FWMSG_H__ */
diff --git a/drivers/misc/iwmc3200top/iwmc3200top.h b/drivers/misc/iwmc3200top/iwmc3200top.h
deleted file mode 100644
index 620973e..0000000
--- a/drivers/misc/iwmc3200top/iwmc3200top.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/iwmc3200top.h
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
- *  -
- *
- */
-
-#ifndef __IWMC3200TOP_H__
-#define __IWMC3200TOP_H__
-
-#include <linux/workqueue.h>
-
-#define DRV_NAME "iwmc3200top"
-#define FW_API_VER 1
-#define _FW_NAME(api) DRV_NAME "." #api ".fw"
-#define FW_NAME(api) _FW_NAME(api)
-
-#define IWMC_SDIO_BLK_SIZE			256
-#define IWMC_DEFAULT_TR_BLK			64
-#define IWMC_SDIO_DATA_ADDR			0x0
-#define IWMC_SDIO_INTR_ENABLE_ADDR		0x14
-#define IWMC_SDIO_INTR_STATUS_ADDR		0x13
-#define IWMC_SDIO_INTR_CLEAR_ADDR		0x13
-#define IWMC_SDIO_INTR_GET_SIZE_ADDR		0x2C
-
-#define COMM_HUB_HEADER_LENGTH 16
-#define LOGGER_HEADER_LENGTH   10
-
-
-#define BARKER_DNLOAD_BT_POS		0
-#define BARKER_DNLOAD_BT_MSK		BIT(BARKER_DNLOAD_BT_POS)
-#define BARKER_DNLOAD_GPS_POS		1
-#define BARKER_DNLOAD_GPS_MSK		BIT(BARKER_DNLOAD_GPS_POS)
-#define BARKER_DNLOAD_TOP_POS		2
-#define BARKER_DNLOAD_TOP_MSK		BIT(BARKER_DNLOAD_TOP_POS)
-#define BARKER_DNLOAD_RESERVED1_POS	3
-#define BARKER_DNLOAD_RESERVED1_MSK	BIT(BARKER_DNLOAD_RESERVED1_POS)
-#define BARKER_DNLOAD_JUMP_POS		4
-#define BARKER_DNLOAD_JUMP_MSK		BIT(BARKER_DNLOAD_JUMP_POS)
-#define BARKER_DNLOAD_SYNC_POS		5
-#define BARKER_DNLOAD_SYNC_MSK		BIT(BARKER_DNLOAD_SYNC_POS)
-#define BARKER_DNLOAD_RESERVED2_POS	6
-#define BARKER_DNLOAD_RESERVED2_MSK	(0x3 << BARKER_DNLOAD_RESERVED2_POS)
-#define BARKER_DNLOAD_BARKER_POS	8
-#define BARKER_DNLOAD_BARKER_MSK	(0xffffff << BARKER_DNLOAD_BARKER_POS)
-
-#define IWMC_BARKER_REBOOT 	(0xdeadbe << BARKER_DNLOAD_BARKER_POS)
-/* whole field barker */
-#define IWMC_BARKER_ACK 	0xfeedbabe
-
-#define IWMC_CMD_SIGNATURE 	0xcbbc
-
-#define CMD_HDR_OPCODE_POS		0
-#define CMD_HDR_OPCODE_MSK_MSK		(0xf << CMD_HDR_OPCODE_MSK_POS)
-#define CMD_HDR_RESPONSE_CODE_POS	4
-#define CMD_HDR_RESPONSE_CODE_MSK	(0xf << CMD_HDR_RESPONSE_CODE_POS)
-#define CMD_HDR_USE_CHECKSUM_POS	8
-#define CMD_HDR_USE_CHECKSUM_MSK	BIT(CMD_HDR_USE_CHECKSUM_POS)
-#define CMD_HDR_RESPONSE_REQUIRED_POS	9
-#define CMD_HDR_RESPONSE_REQUIRED_MSK	BIT(CMD_HDR_RESPONSE_REQUIRED_POS)
-#define CMD_HDR_DIRECT_ACCESS_POS	10
-#define CMD_HDR_DIRECT_ACCESS_MSK	BIT(CMD_HDR_DIRECT_ACCESS_POS)
-#define CMD_HDR_RESERVED_POS		11
-#define CMD_HDR_RESERVED_MSK		BIT(0x1f << CMD_HDR_RESERVED_POS)
-#define CMD_HDR_SIGNATURE_POS		16
-#define CMD_HDR_SIGNATURE_MSK		BIT(0xffff << CMD_HDR_SIGNATURE_POS)
-
-enum {
-	IWMC_OPCODE_PING = 0,
-	IWMC_OPCODE_READ = 1,
-	IWMC_OPCODE_WRITE = 2,
-	IWMC_OPCODE_JUMP = 3,
-	IWMC_OPCODE_REBOOT = 4,
-	IWMC_OPCODE_PERSISTENT_WRITE = 5,
-	IWMC_OPCODE_PERSISTENT_READ = 6,
-	IWMC_OPCODE_READ_MODIFY_WRITE = 7,
-	IWMC_OPCODE_LAST_COMMAND = 15
-};
-
-struct iwmct_fw_load_hdr {
-	__le32 cmd;
-	__le32 target_addr;
-	__le32 data_size;
-	__le32 block_chksm;
-	u8 data[0];
-};
-
-/**
- * struct iwmct_fw_hdr
- * holds all sw components versions
- */
-struct iwmct_fw_hdr {
-	u8 top_major;
-	u8 top_minor;
-	u8 top_revision;
-	u8 gps_major;
-	u8 gps_minor;
-	u8 gps_revision;
-	u8 bt_major;
-	u8 bt_minor;
-	u8 bt_revision;
-	u8 tic_name[31];
-};
-
-/**
- * struct iwmct_fw_sec_hdr
- * @type: function type
- * @data_size: section's data size
- * @target_addr: download address
- */
-struct iwmct_fw_sec_hdr {
-	u8 type[4];
-	__le32 data_size;
-	__le32 target_addr;
-};
-
-/**
- * struct iwmct_parser
- * @file: fw image
- * @file_size: fw size
- * @cur_pos: position in file
- * @buf: temp buf for download
- * @buf_size: size of buf
- * @entry_point: address to jump in fw kick-off
- */
-struct iwmct_parser {
-	const u8 *file;
-	size_t file_size;
-	size_t cur_pos;
-	u8 *buf;
-	size_t buf_size;
-	u32 entry_point;
-	struct iwmct_fw_hdr versions;
-};
-
-
-struct iwmct_work_struct {
-	struct list_head list;
-	ssize_t iosize;
-};
-
-struct iwmct_dbg {
-	int blocks;
-	bool dump;
-	bool jump;
-	bool direct;
-	bool checksum;
-	bool fw_download;
-	int block_size;
-	int download_trans_blks;
-
-	char label_fw[256];
-};
-
-struct iwmct_debugfs;
-
-struct iwmct_priv {
-	struct sdio_func *func;
-	struct iwmct_debugfs *dbgfs;
-	struct iwmct_parser parser;
-	atomic_t reset;
-	atomic_t dev_sync;
-	u32 trans_len;
-	u32 barker;
-	struct iwmct_dbg dbg;
-
-	/* drivers work items */
-	struct work_struct bus_rescan_worker;
-	struct work_struct isr_worker;
-
-	/* drivers wait queue */
-	wait_queue_head_t wait_q;
-
-	/* rx request list */
-	struct list_head read_req_list;
-};
-
-extern int iwmct_tx(struct iwmct_priv *priv, void *src, int count);
-extern int iwmct_fw_load(struct iwmct_priv *priv);
-
-extern void iwmct_dbg_init_params(struct iwmct_priv *drv);
-extern void iwmct_dbg_init_drv_attrs(struct device_driver *drv);
-extern void iwmct_dbg_remove_drv_attrs(struct device_driver *drv);
-extern int iwmct_send_hcmd(struct iwmct_priv *priv, u8 *cmd, u16 len);
-
-#endif  /*  __IWMC3200TOP_H__  */
diff --git a/drivers/misc/iwmc3200top/log.c b/drivers/misc/iwmc3200top/log.c
deleted file mode 100644
index a36a55a..0000000
--- a/drivers/misc/iwmc3200top/log.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/log.c
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
- *  -
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/slab.h>
-#include <linux/ctype.h>
-#include "fw-msg.h"
-#include "iwmc3200top.h"
-#include "log.h"
-
-/* Maximal hexadecimal string size of the FW memdump message */
-#define LOG_MSG_SIZE_MAX		12400
-
-/* iwmct_logdefs is a global used by log macros */
-u8 iwmct_logdefs[LOG_SRC_MAX];
-static u8 iwmct_fw_logdefs[FW_LOG_SRC_MAX];
-
-
-static int _log_set_log_filter(u8 *logdefs, int size, u8 src, u8 logmask)
-{
-	int i;
-
-	if (src < size)
-		logdefs[src] = logmask;
-	else if (src == LOG_SRC_ALL)
-		for (i = 0; i < size; i++)
-			logdefs[i] = logmask;
-	else
-		return -1;
-
-	return 0;
-}
-
-
-int iwmct_log_set_filter(u8 src, u8 logmask)
-{
-	return _log_set_log_filter(iwmct_logdefs, LOG_SRC_MAX, src, logmask);
-}
-
-
-int iwmct_log_set_fw_filter(u8 src, u8 logmask)
-{
-	return _log_set_log_filter(iwmct_fw_logdefs,
-				   FW_LOG_SRC_MAX, src, logmask);
-}
-
-
-static int log_msg_format_hex(char *str, int slen, u8 *ibuf,
-			      int ilen, char *pref)
-{
-	int pos = 0;
-	int i;
-	int len;
-
-	for (pos = 0, i = 0; pos < slen - 2 && pref[i] != '\0'; i++, pos++)
-		str[pos] = pref[i];
-
-	for (i = 0; pos < slen - 2 && i < ilen; pos += len, i++)
-		len = snprintf(&str[pos], slen - pos - 1, " %2.2X", ibuf[i]);
-
-	if (i < ilen)
-		return -1;
-
-	return 0;
-}
-
-/*	NOTE: This function is not thread safe.
-	Currently it's called only from sdio rx worker - no race there
-*/
-void iwmct_log_top_message(struct iwmct_priv *priv, u8 *buf, int len)
-{
-	struct top_msg *msg;
-	static char logbuf[LOG_MSG_SIZE_MAX];
-
-	msg = (struct top_msg *)buf;
-
-	if (len < sizeof(msg->hdr) + sizeof(msg->u.log.log_hdr)) {
-		LOG_ERROR(priv, FW_MSG, "Log message from TOP "
-			  "is too short %d (expected %zd)\n",
-			  len, sizeof(msg->hdr) + sizeof(msg->u.log.log_hdr));
-		return;
-	}
-
-	if (!(iwmct_fw_logdefs[msg->u.log.log_hdr.logsource] &
-		BIT(msg->u.log.log_hdr.severity)) ||
-	    !(iwmct_logdefs[LOG_SRC_FW_MSG] & BIT(msg->u.log.log_hdr.severity)))
-		return;
-
-	switch (msg->hdr.category) {
-	case COMM_CATEGORY_TESTABILITY:
-		if (!(iwmct_logdefs[LOG_SRC_TST] &
-		      BIT(msg->u.log.log_hdr.severity)))
-			return;
-		if (log_msg_format_hex(logbuf, LOG_MSG_SIZE_MAX, buf,
-				       le16_to_cpu(msg->hdr.length) +
-				       sizeof(msg->hdr), "<TST>"))
-			LOG_WARNING(priv, TST,
-				  "TOP TST message is too long, truncating...");
-		LOG_WARNING(priv, TST, "%s\n", logbuf);
-		break;
-	case COMM_CATEGORY_DEBUG:
-		if (msg->hdr.opcode == OP_DBG_ZSTR_MSG)
-			LOG_INFO(priv, FW_MSG, "%s %s", "<DBG>",
-				       ((u8 *)msg) + sizeof(msg->hdr)
-					+ sizeof(msg->u.log.log_hdr));
-		else {
-			if (log_msg_format_hex(logbuf, LOG_MSG_SIZE_MAX, buf,
-					le16_to_cpu(msg->hdr.length)
-						+ sizeof(msg->hdr),
-					"<DBG>"))
-				LOG_WARNING(priv, FW_MSG,
-					"TOP DBG message is too long,"
-					"truncating...");
-			LOG_WARNING(priv, FW_MSG, "%s\n", logbuf);
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-static int _log_get_filter_str(u8 *logdefs, int logdefsz, char *buf, int size)
-{
-	int i, pos, len;
-	for (i = 0, pos = 0; (pos < size-1) && (i < logdefsz); i++) {
-		len = snprintf(&buf[pos], size - pos - 1, "0x%02X%02X,",
-				i, logdefs[i]);
-		pos += len;
-	}
-	buf[pos-1] = '\n';
-	buf[pos] = '\0';
-
-	if (i < logdefsz)
-		return -1;
-	return 0;
-}
-
-int log_get_filter_str(char *buf, int size)
-{
-	return _log_get_filter_str(iwmct_logdefs, LOG_SRC_MAX, buf, size);
-}
-
-int log_get_fw_filter_str(char *buf, int size)
-{
-	return _log_get_filter_str(iwmct_fw_logdefs, FW_LOG_SRC_MAX, buf, size);
-}
-
-#define HEXADECIMAL_RADIX	16
-#define LOG_SRC_FORMAT		7 /* log level is in format of "0xXXXX," */
-
-ssize_t show_iwmct_log_level(struct device *d,
-				struct device_attribute *attr, char *buf)
-{
-	struct iwmct_priv *priv = dev_get_drvdata(d);
-	char *str_buf;
-	int buf_size;
-	ssize_t ret;
-
-	buf_size = (LOG_SRC_FORMAT * LOG_SRC_MAX) + 1;
-	str_buf = kzalloc(buf_size, GFP_KERNEL);
-	if (!str_buf) {
-		LOG_ERROR(priv, DEBUGFS,
-			"failed to allocate %d bytes\n", buf_size);
-		ret = -ENOMEM;
-		goto exit;
-	}
-
-	if (log_get_filter_str(str_buf, buf_size) < 0) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	ret = sprintf(buf, "%s", str_buf);
-
-exit:
-	kfree(str_buf);
-	return ret;
-}
-
-ssize_t store_iwmct_log_level(struct device *d,
-			struct device_attribute *attr,
-			const char *buf, size_t count)
-{
-	struct iwmct_priv *priv = dev_get_drvdata(d);
-	char *token, *str_buf = NULL;
-	long val;
-	ssize_t ret = count;
-	u8 src, mask;
-
-	if (!count)
-		goto exit;
-
-	str_buf = kzalloc(count, GFP_KERNEL);
-	if (!str_buf) {
-		LOG_ERROR(priv, DEBUGFS,
-			"failed to allocate %zd bytes\n", count);
-		ret = -ENOMEM;
-		goto exit;
-	}
-
-	memcpy(str_buf, buf, count);
-
-	while ((token = strsep(&str_buf, ",")) != NULL) {
-		while (isspace(*token))
-			++token;
-		if (strict_strtol(token, HEXADECIMAL_RADIX, &val)) {
-			LOG_ERROR(priv, DEBUGFS,
-				  "failed to convert string to long %s\n",
-				  token);
-			ret = -EINVAL;
-			goto exit;
-		}
-
-		mask  = val & 0xFF;
-		src = (val & 0XFF00) >> 8;
-		iwmct_log_set_filter(src, mask);
-	}
-
-exit:
-	kfree(str_buf);
-	return ret;
-}
-
-ssize_t show_iwmct_log_level_fw(struct device *d,
-			struct device_attribute *attr, char *buf)
-{
-	struct iwmct_priv *priv = dev_get_drvdata(d);
-	char *str_buf;
-	int buf_size;
-	ssize_t ret;
-
-	buf_size = (LOG_SRC_FORMAT * FW_LOG_SRC_MAX) + 2;
-
-	str_buf = kzalloc(buf_size, GFP_KERNEL);
-	if (!str_buf) {
-		LOG_ERROR(priv, DEBUGFS,
-			"failed to allocate %d bytes\n", buf_size);
-		ret = -ENOMEM;
-		goto exit;
-	}
-
-	if (log_get_fw_filter_str(str_buf, buf_size) < 0) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	ret = sprintf(buf, "%s", str_buf);
-
-exit:
-	kfree(str_buf);
-	return ret;
-}
-
-ssize_t store_iwmct_log_level_fw(struct device *d,
-			struct device_attribute *attr,
-			const char *buf, size_t count)
-{
-	struct iwmct_priv *priv = dev_get_drvdata(d);
-	struct top_msg cmd;
-	char *token, *str_buf = NULL;
-	ssize_t ret = count;
-	u16 cmdlen = 0;
-	int i;
-	long val;
-	u8 src, mask;
-
-	if (!count)
-		goto exit;
-
-	str_buf = kzalloc(count, GFP_KERNEL);
-	if (!str_buf) {
-		LOG_ERROR(priv, DEBUGFS,
-			"failed to allocate %zd bytes\n", count);
-		ret = -ENOMEM;
-		goto exit;
-	}
-
-	memcpy(str_buf, buf, count);
-
-	cmd.hdr.type = COMM_TYPE_H2D;
-	cmd.hdr.category = COMM_CATEGORY_DEBUG;
-	cmd.hdr.opcode = CMD_DBG_LOG_LEVEL;
-
-	for (i = 0; ((token = strsep(&str_buf, ",")) != NULL) &&
-		     (i < FW_LOG_SRC_MAX); i++) {
-
-		while (isspace(*token))
-			++token;
-
-		if (strict_strtol(token, HEXADECIMAL_RADIX, &val)) {
-			LOG_ERROR(priv, DEBUGFS,
-				  "failed to convert string to long %s\n",
-				  token);
-			ret = -EINVAL;
-			goto exit;
-		}
-
-		mask  = val & 0xFF; /* LSB */
-		src = (val & 0XFF00) >> 8; /* 2nd least significant byte. */
-		iwmct_log_set_fw_filter(src, mask);
-
-		cmd.u.logdefs[i].logsource = src;
-		cmd.u.logdefs[i].sevmask = mask;
-	}
-
-	cmd.hdr.length = cpu_to_le16(i * sizeof(cmd.u.logdefs[0]));
-	cmdlen = (i * sizeof(cmd.u.logdefs[0]) + sizeof(cmd.hdr));
-
-	ret = iwmct_send_hcmd(priv, (u8 *)&cmd, cmdlen);
-	if (ret) {
-		LOG_ERROR(priv, DEBUGFS,
-			  "Failed to send %d bytes of fwcmd, ret=%zd\n",
-			  cmdlen, ret);
-		goto exit;
-	} else
-		LOG_INFO(priv, DEBUGFS, "fwcmd sent (%d bytes)\n", cmdlen);
-
-	ret = count;
-
-exit:
-	kfree(str_buf);
-	return ret;
-}
-
diff --git a/drivers/misc/iwmc3200top/log.h b/drivers/misc/iwmc3200top/log.h
deleted file mode 100644
index 4434bb1..0000000
--- a/drivers/misc/iwmc3200top/log.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/log.h
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
- *  -
- *
- */
-
-#ifndef __LOG_H__
-#define __LOG_H__
-
-
-/* log severity:
- * The log levels here match FW log levels
- * so values need to stay as is */
-#define LOG_SEV_CRITICAL		0
-#define LOG_SEV_ERROR			1
-#define LOG_SEV_WARNING			2
-#define LOG_SEV_INFO			3
-#define LOG_SEV_INFOEX			4
-
-/* Log levels not defined for FW */
-#define LOG_SEV_TRACE			5
-#define LOG_SEV_DUMP			6
-
-#define LOG_SEV_FW_FILTER_ALL		\
-	(BIT(LOG_SEV_CRITICAL)	|	\
-	 BIT(LOG_SEV_ERROR)	|	\
-	 BIT(LOG_SEV_WARNING)	| 	\
-	 BIT(LOG_SEV_INFO)	|	\
-	 BIT(LOG_SEV_INFOEX))
-
-#define LOG_SEV_FILTER_ALL		\
-	(BIT(LOG_SEV_CRITICAL)	|	\
-	 BIT(LOG_SEV_ERROR)	|	\
-	 BIT(LOG_SEV_WARNING)	| 	\
-	 BIT(LOG_SEV_INFO)	|	\
-	 BIT(LOG_SEV_INFOEX)	|	\
-	 BIT(LOG_SEV_TRACE)	|	\
-	 BIT(LOG_SEV_DUMP))
-
-/* log source */
-#define LOG_SRC_INIT			0
-#define LOG_SRC_DEBUGFS			1
-#define LOG_SRC_FW_DOWNLOAD		2
-#define LOG_SRC_FW_MSG			3
-#define LOG_SRC_TST			4
-#define LOG_SRC_IRQ			5
-
-#define	LOG_SRC_MAX			6
-#define	LOG_SRC_ALL			0xFF
-
-/**
- * Default intitialization runtime log level
- */
-#ifndef LOG_SEV_FILTER_RUNTIME
-#define LOG_SEV_FILTER_RUNTIME			\
-	(BIT(LOG_SEV_CRITICAL)	|		\
-	 BIT(LOG_SEV_ERROR)	|		\
-	 BIT(LOG_SEV_WARNING))
-#endif
-
-#ifndef FW_LOG_SEV_FILTER_RUNTIME
-#define FW_LOG_SEV_FILTER_RUNTIME	LOG_SEV_FILTER_ALL
-#endif
-
-#ifdef CONFIG_IWMC3200TOP_DEBUG
-/**
- * Log macros
- */
-
-#define priv2dev(priv) (&(priv->func)->dev)
-
-#define LOG_CRITICAL(priv, src, fmt, args...)				\
-do {									\
-	if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_CRITICAL))	\
-		dev_crit(priv2dev(priv), "%s %d: " fmt,			\
-			__func__, __LINE__, ##args);			\
-} while (0)
-
-#define LOG_ERROR(priv, src, fmt, args...)				\
-do {									\
-	if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_ERROR))	\
-		dev_err(priv2dev(priv), "%s %d: " fmt,			\
-			__func__, __LINE__, ##args);			\
-} while (0)
-
-#define LOG_WARNING(priv, src, fmt, args...)				\
-do {									\
-	if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_WARNING))	\
-		dev_warn(priv2dev(priv), "%s %d: " fmt,			\
-			 __func__, __LINE__, ##args);			\
-} while (0)
-
-#define LOG_INFO(priv, src, fmt, args...)				\
-do {									\
-	if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_INFO))		\
-		dev_info(priv2dev(priv), "%s %d: " fmt,			\
-			 __func__, __LINE__, ##args);			\
-} while (0)
-
-#define LOG_TRACE(priv, src, fmt, args...)				\
-do {									\
-	if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_TRACE))	\
-		dev_dbg(priv2dev(priv), "%s %d: " fmt,			\
-			 __func__, __LINE__, ##args);			\
-} while (0)
-
-#define LOG_HEXDUMP(src, ptr, len)					\
-do {									\
-	if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_DUMP))	\
-		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE,	\
-				16, 1, ptr, len, false);		\
-} while (0)
-
-void iwmct_log_top_message(struct iwmct_priv *priv, u8 *buf, int len);
-
-extern u8 iwmct_logdefs[];
-
-int iwmct_log_set_filter(u8 src, u8 logmask);
-int iwmct_log_set_fw_filter(u8 src, u8 logmask);
-
-ssize_t show_iwmct_log_level(struct device *d,
-			struct device_attribute *attr, char *buf);
-ssize_t store_iwmct_log_level(struct device *d,
-			struct device_attribute *attr,
-			const char *buf, size_t count);
-ssize_t show_iwmct_log_level_fw(struct device *d,
-			struct device_attribute *attr, char *buf);
-ssize_t store_iwmct_log_level_fw(struct device *d,
-			struct device_attribute *attr,
-			const char *buf, size_t count);
-
-#else
-
-#define LOG_CRITICAL(priv, src, fmt, args...)
-#define LOG_ERROR(priv, src, fmt, args...)
-#define LOG_WARNING(priv, src, fmt, args...)
-#define LOG_INFO(priv, src, fmt, args...)
-#define LOG_TRACE(priv, src, fmt, args...)
-#define LOG_HEXDUMP(src, ptr, len)
-
-static inline void iwmct_log_top_message(struct iwmct_priv *priv,
-					 u8 *buf, int len) {}
-static inline int iwmct_log_set_filter(u8 src, u8 logmask) { return 0; }
-static inline int iwmct_log_set_fw_filter(u8 src, u8 logmask) { return 0; }
-
-#endif /* CONFIG_IWMC3200TOP_DEBUG */
-
-int log_get_filter_str(char *buf, int size);
-int log_get_fw_filter_str(char *buf, int size);
-
-#endif /* __LOG_H__ */
diff --git a/drivers/misc/iwmc3200top/main.c b/drivers/misc/iwmc3200top/main.c
deleted file mode 100644
index 701eb60..0000000
--- a/drivers/misc/iwmc3200top/main.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/main.c
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
- *  -
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/debugfs.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio.h>
-
-#include "iwmc3200top.h"
-#include "log.h"
-#include "fw-msg.h"
-#include "debugfs.h"
-
-
-#define DRIVER_DESCRIPTION "Intel(R) IWMC 3200 Top Driver"
-#define DRIVER_COPYRIGHT "Copyright (c) 2008 Intel Corporation."
-
-#define DRIVER_VERSION  "0.1.62"
-
-MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR(DRIVER_COPYRIGHT);
-MODULE_FIRMWARE(FW_NAME(FW_API_VER));
-
-
-static inline int __iwmct_tx(struct iwmct_priv *priv, void *src, int count)
-{
-	return sdio_memcpy_toio(priv->func, IWMC_SDIO_DATA_ADDR, src, count);
-
-}
-int iwmct_tx(struct iwmct_priv *priv, void *src, int count)
-{
-	int ret;
-	sdio_claim_host(priv->func);
-	ret =  __iwmct_tx(priv, src, count);
-	sdio_release_host(priv->func);
-	return ret;
-}
-/*
- * This workers main task is to wait for OP_OPR_ALIVE
- * from TOP FW until ALIVE_MSG_TIMOUT timeout is elapsed.
- * When OP_OPR_ALIVE received it will issue
- * a call to "bus_rescan_devices".
- */
-static void iwmct_rescan_worker(struct work_struct *ws)
-{
-	struct iwmct_priv *priv;
-	int ret;
-
-	priv = container_of(ws, struct iwmct_priv, bus_rescan_worker);
-
-	LOG_INFO(priv, FW_MSG, "Calling bus_rescan\n");
-
-	ret = bus_rescan_devices(priv->func->dev.bus);
-	if (ret < 0)
-		LOG_INFO(priv, INIT, "bus_rescan_devices FAILED!!!\n");
-}
-
-static void op_top_message(struct iwmct_priv *priv, struct top_msg *msg)
-{
-	switch (msg->hdr.opcode) {
-	case OP_OPR_ALIVE:
-		LOG_INFO(priv, FW_MSG, "Got ALIVE from device, wake rescan\n");
-		schedule_work(&priv->bus_rescan_worker);
-		break;
-	default:
-		LOG_INFO(priv, FW_MSG, "Received msg opcode 0x%X\n",
-			msg->hdr.opcode);
-		break;
-	}
-}
-
-
-static void handle_top_message(struct iwmct_priv *priv, u8 *buf, int len)
-{
-	struct top_msg *msg;
-
-	msg = (struct top_msg *)buf;
-
-	if (msg->hdr.type != COMM_TYPE_D2H) {
-		LOG_ERROR(priv, FW_MSG,
-			"Message from TOP with invalid message type 0x%X\n",
-			msg->hdr.type);
-		return;
-	}
-
-	if (len < sizeof(msg->hdr)) {
-		LOG_ERROR(priv, FW_MSG,
-			"Message from TOP is too short for message header "
-			"received %d bytes, expected at least %zd bytes\n",
-			len, sizeof(msg->hdr));
-		return;
-	}
-
-	if (len < le16_to_cpu(msg->hdr.length) + sizeof(msg->hdr)) {
-		LOG_ERROR(priv, FW_MSG,
-			"Message length (%d bytes) is shorter than "
-			"in header (%d bytes)\n",
-			len, le16_to_cpu(msg->hdr.length));
-		return;
-	}
-
-	switch (msg->hdr.category) {
-	case COMM_CATEGORY_OPERATIONAL:
-		op_top_message(priv, (struct top_msg *)buf);
-		break;
-
-	case COMM_CATEGORY_DEBUG:
-	case COMM_CATEGORY_TESTABILITY:
-	case COMM_CATEGORY_DIAGNOSTICS:
-		iwmct_log_top_message(priv, buf, len);
-		break;
-
-	default:
-		LOG_ERROR(priv, FW_MSG,
-			"Message from TOP with unknown category 0x%X\n",
-			msg->hdr.category);
-		break;
-	}
-}
-
-int iwmct_send_hcmd(struct iwmct_priv *priv, u8 *cmd, u16 len)
-{
-	int ret;
-	u8 *buf;
-
-	LOG_TRACE(priv, FW_MSG, "Sending hcmd:\n");
-
-	/* add padding to 256 for IWMC */
-	((struct top_msg *)cmd)->hdr.flags |= CMD_FLAG_PADDING_256;
-
-	LOG_HEXDUMP(FW_MSG, cmd, len);
-
-	if (len > FW_HCMD_BLOCK_SIZE) {
-		LOG_ERROR(priv, FW_MSG, "size %d exceeded hcmd max size %d\n",
-			  len, FW_HCMD_BLOCK_SIZE);
-		return -1;
-	}
-
-	buf = kzalloc(FW_HCMD_BLOCK_SIZE, GFP_KERNEL);
-	if (!buf) {
-		LOG_ERROR(priv, FW_MSG, "kzalloc error, buf size %d\n",
-			  FW_HCMD_BLOCK_SIZE);
-		return -1;
-	}
-
-	memcpy(buf, cmd, len);
-	ret = iwmct_tx(priv, buf, FW_HCMD_BLOCK_SIZE);
-
-	kfree(buf);
-	return ret;
-}
-
-
-static void iwmct_irq_read_worker(struct work_struct *ws)
-{
-	struct iwmct_priv *priv;
-	struct iwmct_work_struct *read_req;
-	__le32 *buf = NULL;
-	int ret;
-	int iosize;
-	u32 barker;
-	bool is_barker;
-
-	priv = container_of(ws, struct iwmct_priv, isr_worker);
-
-	LOG_TRACE(priv, IRQ, "enter iwmct_irq_read_worker %p\n", ws);
-
-	/* --------------------- Handshake with device -------------------- */
-	sdio_claim_host(priv->func);
-
-	/* all list manipulations have to be protected by
-	 * sdio_claim_host/sdio_release_host */
-	if (list_empty(&priv->read_req_list)) {
-		LOG_ERROR(priv, IRQ, "read_req_list empty in read worker\n");
-		goto exit_release;
-	}
-
-	read_req = list_entry(priv->read_req_list.next,
-			      struct iwmct_work_struct, list);
-
-	list_del(&read_req->list);
-	iosize = read_req->iosize;
-	kfree(read_req);
-
-	buf = kzalloc(iosize, GFP_KERNEL);
-	if (!buf) {
-		LOG_ERROR(priv, IRQ, "kzalloc error, buf size %d\n", iosize);
-		goto exit_release;
-	}
-
-	LOG_INFO(priv, IRQ, "iosize=%d, buf=%p, func=%d\n",
-				iosize, buf, priv->func->num);
-
-	/* read from device */
-	ret = sdio_memcpy_fromio(priv->func, buf, IWMC_SDIO_DATA_ADDR, iosize);
-	if (ret) {
-		LOG_ERROR(priv, IRQ, "error %d reading buffer\n", ret);
-		goto exit_release;
-	}
-
-	LOG_HEXDUMP(IRQ, (u8 *)buf, iosize);
-
-	barker = le32_to_cpu(buf[0]);
-
-	/* Verify whether it's a barker and if not - treat as regular Rx */
-	if (barker == IWMC_BARKER_ACK ||
-	    (barker & BARKER_DNLOAD_BARKER_MSK) == IWMC_BARKER_REBOOT) {
-
-		/* Valid Barker is equal on first 4 dwords */
-		is_barker = (buf[1] == buf[0]) &&
-			    (buf[2] == buf[0]) &&
-			    (buf[3] == buf[0]);
-
-		if (!is_barker) {
-			LOG_WARNING(priv, IRQ,
-				"Potentially inconsistent barker "
-				"%08X_%08X_%08X_%08X\n",
-				le32_to_cpu(buf[0]), le32_to_cpu(buf[1]),
-				le32_to_cpu(buf[2]), le32_to_cpu(buf[3]));
-		}
-	} else {
-		is_barker = false;
-	}
-
-	/* Handle Top CommHub message */
-	if (!is_barker) {
-		sdio_release_host(priv->func);
-		handle_top_message(priv, (u8 *)buf, iosize);
-		goto exit;
-	} else if (barker == IWMC_BARKER_ACK) { /* Handle barkers */
-		if (atomic_read(&priv->dev_sync) == 0) {
-			LOG_ERROR(priv, IRQ,
-				  "ACK barker arrived out-of-sync\n");
-			goto exit_release;
-		}
-
-		/* Continuing to FW download (after Sync is completed)*/
-		atomic_set(&priv->dev_sync, 0);
-		LOG_INFO(priv, IRQ, "ACK barker arrived "
-				"- starting FW download\n");
-	} else { /* REBOOT barker */
-		LOG_INFO(priv, IRQ, "Received reboot barker: %x\n", barker);
-		priv->barker = barker;
-
-		if (barker & BARKER_DNLOAD_SYNC_MSK) {
-			/* Send the same barker back */
-			ret = __iwmct_tx(priv, buf, iosize);
-			if (ret) {
-				LOG_ERROR(priv, IRQ,
-					 "error %d echoing barker\n", ret);
-				goto exit_release;
-			}
-			LOG_INFO(priv, IRQ, "Echoing barker to device\n");
-			atomic_set(&priv->dev_sync, 1);
-			goto exit_release;
-		}
-
-		/* Continuing to FW download (without Sync) */
-		LOG_INFO(priv, IRQ, "No sync requested "
-				    "- starting FW download\n");
-	}
-
-	sdio_release_host(priv->func);
-
-	if (priv->dbg.fw_download)
-		iwmct_fw_load(priv);
-	else
-		LOG_ERROR(priv, IRQ, "FW download not allowed\n");
-
-	goto exit;
-
-exit_release:
-	sdio_release_host(priv->func);
-exit:
-	kfree(buf);
-	LOG_TRACE(priv, IRQ, "exit iwmct_irq_read_worker\n");
-}
-
-static void iwmct_irq(struct sdio_func *func)
-{
-	struct iwmct_priv *priv;
-	int val, ret;
-	int iosize;
-	int addr = IWMC_SDIO_INTR_GET_SIZE_ADDR;
-	struct iwmct_work_struct *read_req;
-
-	priv = sdio_get_drvdata(func);
-
-	LOG_TRACE(priv, IRQ, "enter iwmct_irq\n");
-
-	/* read the function's status register */
-	val = sdio_readb(func, IWMC_SDIO_INTR_STATUS_ADDR, &ret);
-
-	LOG_TRACE(priv, IRQ, "iir value = %d, ret=%d\n", val, ret);
-
-	if (!val) {
-		LOG_ERROR(priv, IRQ, "iir = 0, exiting ISR\n");
-		goto exit_clear_intr;
-	}
-
-
-	/*
-	 * read 2 bytes of the transaction size
-	 * IMPORTANT: sdio transaction size has to be read before clearing
-	 * sdio interrupt!!!
-	 */
-	val = sdio_readb(priv->func, addr++, &ret);
-	iosize = val;
-	val = sdio_readb(priv->func, addr++, &ret);
-	iosize += val << 8;
-
-	LOG_INFO(priv, IRQ, "READ size %d\n", iosize);
-
-	if (iosize == 0) {
-		LOG_ERROR(priv, IRQ, "READ size %d, exiting ISR\n", iosize);
-		goto exit_clear_intr;
-	}
-
-	/* allocate a work structure to pass iosize to the worker */
-	read_req = kzalloc(sizeof(struct iwmct_work_struct), GFP_KERNEL);
-	if (!read_req) {
-		LOG_ERROR(priv, IRQ, "failed to allocate read_req, exit ISR\n");
-		goto exit_clear_intr;
-	}
-
-	INIT_LIST_HEAD(&read_req->list);
-	read_req->iosize = iosize;
-
-	list_add_tail(&priv->read_req_list, &read_req->list);
-
-	/* clear the function's interrupt request bit (write 1 to clear) */
-	sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret);
-
-	schedule_work(&priv->isr_worker);
-
-	LOG_TRACE(priv, IRQ, "exit iwmct_irq\n");
-
-	return;
-
-exit_clear_intr:
-	/* clear the function's interrupt request bit (write 1 to clear) */
-	sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret);
-}
-
-
-static int blocks;
-module_param(blocks, int, 0604);
-MODULE_PARM_DESC(blocks, "max_blocks_to_send");
-
-static bool dump;
-module_param(dump, bool, 0604);
-MODULE_PARM_DESC(dump, "dump_hex_content");
-
-static bool jump = 1;
-module_param(jump, bool, 0604);
-
-static bool direct = 1;
-module_param(direct, bool, 0604);
-
-static bool checksum = 1;
-module_param(checksum, bool, 0604);
-
-static bool fw_download = 1;
-module_param(fw_download, bool, 0604);
-
-static int block_size = IWMC_SDIO_BLK_SIZE;
-module_param(block_size, int, 0404);
-
-static int download_trans_blks = IWMC_DEFAULT_TR_BLK;
-module_param(download_trans_blks, int, 0604);
-
-static bool rubbish_barker;
-module_param(rubbish_barker, bool, 0604);
-
-#ifdef CONFIG_IWMC3200TOP_DEBUG
-static int log_level[LOG_SRC_MAX];
-static unsigned int log_level_argc;
-module_param_array(log_level, int, &log_level_argc, 0604);
-MODULE_PARM_DESC(log_level, "log_level");
-
-static int log_level_fw[FW_LOG_SRC_MAX];
-static unsigned int log_level_fw_argc;
-module_param_array(log_level_fw, int, &log_level_fw_argc, 0604);
-MODULE_PARM_DESC(log_level_fw, "log_level_fw");
-#endif
-
-void iwmct_dbg_init_params(struct iwmct_priv *priv)
-{
-#ifdef CONFIG_IWMC3200TOP_DEBUG
-	int i;
-
-	for (i = 0; i < log_level_argc; i++) {
-		dev_notice(&priv->func->dev, "log_level[%d]=0x%X\n",
-						i, log_level[i]);
-		iwmct_log_set_filter((log_level[i] >> 8) & 0xFF,
-			       log_level[i] & 0xFF);
-	}
-	for (i = 0; i < log_level_fw_argc; i++) {
-		dev_notice(&priv->func->dev, "log_level_fw[%d]=0x%X\n",
-						i, log_level_fw[i]);
-		iwmct_log_set_fw_filter((log_level_fw[i] >> 8) & 0xFF,
-				  log_level_fw[i] & 0xFF);
-	}
-#endif
-
-	priv->dbg.blocks = blocks;
-	LOG_INFO(priv, INIT, "blocks=%d\n", blocks);
-	priv->dbg.dump = (bool)dump;
-	LOG_INFO(priv, INIT, "dump=%d\n", dump);
-	priv->dbg.jump = (bool)jump;
-	LOG_INFO(priv, INIT, "jump=%d\n", jump);
-	priv->dbg.direct = (bool)direct;
-	LOG_INFO(priv, INIT, "direct=%d\n", direct);
-	priv->dbg.checksum = (bool)checksum;
-	LOG_INFO(priv, INIT, "checksum=%d\n", checksum);
-	priv->dbg.fw_download = (bool)fw_download;
-	LOG_INFO(priv, INIT, "fw_download=%d\n", fw_download);
-	priv->dbg.block_size = block_size;
-	LOG_INFO(priv, INIT, "block_size=%d\n", block_size);
-	priv->dbg.download_trans_blks = download_trans_blks;
-	LOG_INFO(priv, INIT, "download_trans_blks=%d\n", download_trans_blks);
-}
-
-/*****************************************************************************
- *
- * sysfs attributes
- *
- *****************************************************************************/
-static ssize_t show_iwmct_fw_version(struct device *d,
-				  struct device_attribute *attr, char *buf)
-{
-	struct iwmct_priv *priv = dev_get_drvdata(d);
-	return sprintf(buf, "%s\n", priv->dbg.label_fw);
-}
-static DEVICE_ATTR(cc_label_fw, S_IRUGO, show_iwmct_fw_version, NULL);
-
-#ifdef CONFIG_IWMC3200TOP_DEBUG
-static DEVICE_ATTR(log_level, S_IWUSR | S_IRUGO,
-		   show_iwmct_log_level, store_iwmct_log_level);
-static DEVICE_ATTR(log_level_fw, S_IWUSR | S_IRUGO,
-		   show_iwmct_log_level_fw, store_iwmct_log_level_fw);
-#endif
-
-static struct attribute *iwmct_sysfs_entries[] = {
-	&dev_attr_cc_label_fw.attr,
-#ifdef CONFIG_IWMC3200TOP_DEBUG
-	&dev_attr_log_level.attr,
-	&dev_attr_log_level_fw.attr,
-#endif
-	NULL
-};
-
-static struct attribute_group iwmct_attribute_group = {
-	.name = NULL,		/* put in device directory */
-	.attrs = iwmct_sysfs_entries,
-};
-
-
-static int iwmct_probe(struct sdio_func *func,
-			   const struct sdio_device_id *id)
-{
-	struct iwmct_priv *priv;
-	int ret;
-	int val = 1;
-	int addr = IWMC_SDIO_INTR_ENABLE_ADDR;
-
-	dev_dbg(&func->dev, "enter iwmct_probe\n");
-
-	dev_dbg(&func->dev, "IRQ polling period id %u msecs, HZ is %d\n",
-		jiffies_to_msecs(2147483647), HZ);
-
-	priv = kzalloc(sizeof(struct iwmct_priv), GFP_KERNEL);
-	if (!priv) {
-		dev_err(&func->dev, "kzalloc error\n");
-		return -ENOMEM;
-	}
-	priv->func = func;
-	sdio_set_drvdata(func, priv);
-
-	INIT_WORK(&priv->bus_rescan_worker, iwmct_rescan_worker);
-	INIT_WORK(&priv->isr_worker, iwmct_irq_read_worker);
-
-	init_waitqueue_head(&priv->wait_q);
-
-	sdio_claim_host(func);
-	/* FIXME: Remove after it is fixed in the Boot ROM upgrade */
-	func->enable_timeout = 10;
-
-	/* In our HW, setting the block size also wakes up the boot rom. */
-	ret = sdio_set_block_size(func, priv->dbg.block_size);
-	if (ret) {
-		LOG_ERROR(priv, INIT,
-			"sdio_set_block_size() failure: %d\n", ret);
-		goto error_sdio_enable;
-	}
-
-	ret = sdio_enable_func(func);
-	if (ret) {
-		LOG_ERROR(priv, INIT, "sdio_enable_func() failure: %d\n", ret);
-		goto error_sdio_enable;
-	}
-
-	/* init reset and dev_sync states */
-	atomic_set(&priv->reset, 0);
-	atomic_set(&priv->dev_sync, 0);
-
-	/* init read req queue */
-	INIT_LIST_HEAD(&priv->read_req_list);
-
-	/* process configurable parameters */
-	iwmct_dbg_init_params(priv);
-	ret = sysfs_create_group(&func->dev.kobj, &iwmct_attribute_group);
-	if (ret) {
-		LOG_ERROR(priv, INIT, "Failed to register attributes and "
-			 "initialize module_params\n");
-		goto error_dev_attrs;
-	}
-
-	iwmct_dbgfs_register(priv, DRV_NAME);
-
-	if (!priv->dbg.direct && priv->dbg.download_trans_blks > 8) {
-		LOG_INFO(priv, INIT,
-			 "Reducing transaction to 8 blocks = 2K (from %d)\n",
-			 priv->dbg.download_trans_blks);
-		priv->dbg.download_trans_blks = 8;
-	}
-	priv->trans_len = priv->dbg.download_trans_blks * priv->dbg.block_size;
-	LOG_INFO(priv, INIT, "Transaction length = %d\n", priv->trans_len);
-
-	ret = sdio_claim_irq(func, iwmct_irq);
-	if (ret) {
-		LOG_ERROR(priv, INIT, "sdio_claim_irq() failure: %d\n", ret);
-		goto error_claim_irq;
-	}
-
-
-	/* Enable function's interrupt */
-	sdio_writeb(priv->func, val, addr, &ret);
-	if (ret) {
-		LOG_ERROR(priv, INIT, "Failure writing to "
-			  "Interrupt Enable Register (%d): %d\n", addr, ret);
-		goto error_enable_int;
-	}
-
-	sdio_release_host(func);
-
-	LOG_INFO(priv, INIT, "exit iwmct_probe\n");
-
-	return ret;
-
-error_enable_int:
-	sdio_release_irq(func);
-error_claim_irq:
-	sdio_disable_func(func);
-error_dev_attrs:
-	iwmct_dbgfs_unregister(priv->dbgfs);
-	sysfs_remove_group(&func->dev.kobj, &iwmct_attribute_group);
-error_sdio_enable:
-	sdio_release_host(func);
-	return ret;
-}
-
-static void iwmct_remove(struct sdio_func *func)
-{
-	struct iwmct_work_struct *read_req;
-	struct iwmct_priv *priv = sdio_get_drvdata(func);
-
-	LOG_INFO(priv, INIT, "enter\n");
-
-	sdio_claim_host(func);
-	sdio_release_irq(func);
-	sdio_release_host(func);
-
-	/* Make sure works are finished */
-	flush_work_sync(&priv->bus_rescan_worker);
-	flush_work_sync(&priv->isr_worker);
-
-	sdio_claim_host(func);
-	sdio_disable_func(func);
-	sysfs_remove_group(&func->dev.kobj, &iwmct_attribute_group);
-	iwmct_dbgfs_unregister(priv->dbgfs);
-	sdio_release_host(func);
-
-	/* free read requests */
-	while (!list_empty(&priv->read_req_list)) {
-		read_req = list_entry(priv->read_req_list.next,
-			struct iwmct_work_struct, list);
-
-		list_del(&read_req->list);
-		kfree(read_req);
-	}
-
-	kfree(priv);
-}
-
-
-static const struct sdio_device_id iwmct_ids[] = {
-	/* Intel Wireless MultiCom 3200 Top Driver */
-	{ SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1404)},
-	{ },	/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(sdio, iwmct_ids);
-
-static struct sdio_driver iwmct_driver = {
-	.probe		= iwmct_probe,
-	.remove		= iwmct_remove,
-	.name		= DRV_NAME,
-	.id_table	= iwmct_ids,
-};
-
-static int __init iwmct_init(void)
-{
-	int rc;
-
-	/* Default log filter settings */
-	iwmct_log_set_filter(LOG_SRC_ALL, LOG_SEV_FILTER_RUNTIME);
-	iwmct_log_set_filter(LOG_SRC_FW_MSG, LOG_SEV_FW_FILTER_ALL);
-	iwmct_log_set_fw_filter(LOG_SRC_ALL, FW_LOG_SEV_FILTER_RUNTIME);
-
-	rc = sdio_register_driver(&iwmct_driver);
-
-	return rc;
-}
-
-static void __exit iwmct_exit(void)
-{
-	sdio_unregister_driver(&iwmct_driver);
-}
-
-module_init(iwmct_init);
-module_exit(iwmct_exit);

^ permalink raw reply related

* Re: [PATCH 5/6] tuntap: per queue 64 bit stats\
From: Michael S. Tsirkin @ 2012-06-26 19:46 UTC (permalink / raw)
  To: Jason Wang
  Cc: Eric Dumazet, akong, habanero, tahm, haixiao, jwhan,
	ernesto.martin, mashirle, davem, netdev, linux-kernel, krkumar2,
	shemminger, edumazet
In-Reply-To: <4FE95015.7000707@redhat.com>

On Tue, Jun 26, 2012 at 02:00:53PM +0800, Jason Wang wrote:
> On 06/25/2012 08:52 PM, Eric Dumazet wrote:
> >On Mon, 2012-06-25 at 19:59 +0800, Jason Wang wrote:
> >>As we've added multiqueue support for tun/tap, this patch convert the statistics
> >>to use per-queue 64 bit statistics.
> >LLTX means you can have several cpus calling TX path in parallel.
> >
> >So tx stats are wrong (even before this patch), and racy after this
> >patch (if several cpu access same queue, it seems to be possible)
> >
> >        u64_stats_update_begin(&tfile->stats.tx_syncp);
> >        tfile->stats.tx_packets++;
> >        tfile->stats.tx_bytes += total;
> >        u64_stats_update_end(&tfile->stats.tx_syncp);
> >
> >This can break horribly if several cpus run this code using same 'tfile'
> >pointer.
> 
> Yes, looks like it's hard to use NETIF_F_LLTX without breaking the
> u64 statistics, may worth to use tx lock and alloc_netdev_mq().

Or make them per cpu as most everyone did.


> >I suggest this patch comes before 'tuntap: multiqueue support' in the
> >serie.
> 
> Sure, thanks.
> >
> >
> >

^ permalink raw reply

* [PATCH net-next] udp: Add socket early demux support
From: Vijay Subramanian @ 2012-06-26 19:43 UTC (permalink / raw)
  To: netdev
  Cc: davem, shemminger, eric.dumazet, alexander.h.duyck,
	Vijay Subramanian

Based on the recent TCP socket early demux code, this patch provides similar
support for UDP.

Signed-off-by: Vijay Subramanian <subramanian.vijay@gmail.com>
---
This has been tested on x86 with UDP iperf flows and seemed to work. If this is
accepted, I plan to submit one more patch moving common code from TCP and UDP
early demux code into common helper functions.
Thanks in advance for feedback.

 include/net/udp.h  |    1 +
 net/ipv4/af_inet.c |    1 +
 net/ipv4/udp.c     |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/include/net/udp.h b/include/net/udp.h
index 065f379..e0ed11d 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -175,6 +175,7 @@ extern int udp_lib_get_port(struct sock *sk, unsigned short snum,
 			    unsigned int hash2_nulladdr);
 
 /* net/ipv4/udp.c */
+extern int udp_v4_early_demux(struct sk_buff *skb);
 extern int udp_get_port(struct sock *sk, unsigned short snum,
 			int (*saddr_cmp)(const struct sock *,
 					 const struct sock *));
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 07a02f6..c7d40db 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1531,6 +1531,7 @@ static const struct net_protocol tcp_protocol = {
 };
 
 static const struct net_protocol udp_protocol = {
+	.early_demux =	udp_v4_early_demux,
 	.handler =	udp_rcv,
 	.err_handler =	udp_err,
 	.gso_send_check = udp4_ufo_send_check,
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index db017ef..bd85cd8 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -520,10 +520,10 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
 						 __be16 sport, __be16 dport,
 						 struct udp_table *udptable)
 {
-	struct sock *sk;
+	struct sock *sk = skb_steal_sock(skb);
 	const struct iphdr *iph = ip_hdr(skb);
 
-	if (unlikely(sk = skb_steal_sock(skb)))
+	if (sk)
 		return sk;
 	else
 		return __udp4_lib_lookup(dev_net(skb_dst(skb)->dev), iph->saddr, sport,
@@ -1403,6 +1403,19 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 	int rc;
 	int is_udplite = IS_UDPLITE(sk);
 
+	if (sk->sk_rx_dst) {
+		struct dst_entry *dst = sk->sk_rx_dst;
+		if (unlikely(dst->obsolete)) {
+			if (dst->ops->check(dst, 0) == NULL) {
+				dst_release(dst);
+				sk->sk_rx_dst = NULL;
+			}
+		}
+	}
+
+	if (unlikely(sk->sk_rx_dst == NULL))
+		sk->sk_rx_dst = dst_clone(skb_dst(skb));
+
 	/*
 	 *	Charge it to the socket, dropping if the queue is full.
 	 */
@@ -1622,6 +1635,56 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,
 	return 0;
 }
 
+int udp_v4_early_demux(struct sk_buff *skb)
+{
+	struct net *net = dev_net(skb->dev);
+	const struct iphdr *iph;
+	const struct udphdr *uh;
+	struct net_device *dev;
+	struct sock *sk;
+	unsigned short ulen;
+	int err;
+
+	err = -ENOENT;
+	if (skb->pkt_type != PACKET_HOST)
+		goto out_err;
+
+	if (!pskb_may_pull(skb, ip_hdrlen(skb) + sizeof(struct udphdr)))
+		goto out_err;
+
+	iph = ip_hdr(skb);
+	uh = (struct udphdr *)((char *)iph + ip_hdrlen(skb));
+	ulen = ntohs(uh->len);
+
+	if (ulen > skb->len)
+		goto out_err;
+
+	dev = skb->dev;
+
+	sk = udp4_lib_lookup(net, iph->saddr, uh->source, iph->daddr,
+			     uh->dest, dev->ifindex);
+
+	if (sk) {
+		struct dst_entry *dst = sk->sk_rx_dst;
+		skb->sk = sk;
+		skb->destructor = sock_edemux;
+
+		if (dst)
+			dst = dst_check(dst, 0);
+		if (dst) {
+			struct rtable *rt = (struct rtable *)dst;
+
+			if (rt->rt_iif == dev->ifindex) {
+				skb_dst_set_noref(skb, dst);
+				err = 0;
+			}
+		}
+	}
+
+out_err:
+	return err;
+}
+
 /*
  *	All we need to do is get the socket, and then do a checksum.
  */
-- 
1.7.0.4

^ permalink raw reply related

* Re: [RFC net-next (v2) 12/14] ixgbe: set maximal number of default RSS queues
From: Eilon Greenstein @ 2012-06-26 18:23 UTC (permalink / raw)
  To: Alexander Duyck; +Cc: Yuval Mintz, davem, netdev, Jeff Kirsher, John Fastabend
In-Reply-To: <4FE9DB88.5070208@intel.com>

On Tue, 2012-06-26 at 08:55 -0700, Alexander Duyck wrote:
> One thing that just occurred to me though is that this is going to lock
> the upper limit for us and we won't be able to override it if we
> implement the set channels code.  I believe the same thing goes for the
> igb driver as well.
> 
> Is there any chance you could just bypass the ixgbe and igb drivers for
> now and give us time to come up with a more complete solution that would
> allow us to add the set_channels calls.  One issue is I have a number of
> ixgbe patches that are going to be completely rewriting this code anyway
> so I could probably just add set_channels support and support for your
> function once it is included in net-next.

Alex,

I share your concern. I actually brought it up originally when
discussing this RFC:
http://marc.info/?l=linux-netdev&m=133991625809201&w=2

>From my end, if you would like to add the Intel side support that would
be great. Unless anyone object, we will leave the ixgbe and igb out of
this patch series.

Thanks,
Eilon

^ permalink raw reply

* Re: [PATCH 1/1] atl1c: fix issue of transmit queue 0 timed out
From: Luis R. Rodriguez @ 2012-06-26 18:03 UTC (permalink / raw)
  To: Ren, Cloud; +Cc: davem, netdev, linux-kernel, qca-linux-team, nic-devel, xiong
In-Reply-To: <1340724786-3819-1-git-send-email-cjren@qca.qualcomm.com>

On Tue, Jun 26, 2012 at 12:33:06PM -0300, Ren, Cloud wrote:
> From: xiong <xiong@qca.qualcomm.com>
> 
> some people report atl1c could cause system hang with following
> kernel trace info:
> ---------------------------------------
> WARNING: at.../net/sched/sch_generic.c:258
> dev_watchdog+0x1db/0x1d0()
> ...
> NETDEV WATCHDOG: eth0 (atl1c): transmit queue 0 timed out
> ...
> ---------------------------------------
> This is caused by netif_stop_queue calling when cable Link is down
> but netif_wake_queue isn't called when cable Link is resume.
> 
> Signed-off-by: xiong <xiong@qca.qualcomm.com>
> Signed-off-by: Cloud Ren <cjren@qca.qualcomm.com>

If this fixes  a system hang then this could be a stable
fix -- that is, this should be propagated to older stable
kernels, no?

If so then please add to the commit log a line like this:

Cc: stable@vger.kernel.org [3.4]

Note: this is for the commit log! Right above the line below
that has "---"

  Luis

^ permalink raw reply

* Re: BUG: No init found on NFSROOT
From: Fengguang Wu @ 2012-06-26 17:29 UTC (permalink / raw)
  To: Trond Myklebust
  Cc: J. Bruce Fields, linux-nfs-u79uwXL29TY76Z2rM5mHXA, LKML, netdev
In-Reply-To: <20120626145432.GA15289@localhost>

On Tue, Jun 26, 2012 at 10:54:32PM +0800, Fengguang Wu wrote:
> Hi Trond,
> 
> It's found that this commit in linux-next leads to the below boot hang.
> 
> da660bb2774ff21c7263b4061198c5abe0629cb4 is the first bad commit
> commit da660bb2774ff21c7263b4061198c5abe0629cb4
> Author: Trond Myklebust <Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA@public.gmane.org>
> Date:   Thu Jun 21 14:53:10 2012 -0400
> 
>     SUNRPC: Clean up xdr_read_pages and xdr_enter_page
> 
>     Move the page alignment code into a separate helper.
> 
>     Signed-off-by: Trond Myklebust <Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA@public.gmane.org>
> 
> :040000 040000 742f2939849ea8ff2e4b954316e6ea2933e7e018 6809fe8bd11b9f2459168d6e1dac92b0c5a74eef M      net
> bisect run success
> 
> The "held lock freed" message may or may not appear in the tests.

Ah that seem to be an independent bug. It's still there when reverting
the above commit on top of linux-next. Will try to bisect it.

> However the "No init found." message reliably appears in all test runs.

That "No init found" disappears after reverting the commit.

Thanks,
Fengguang

> [  133.909702] =========================
> [  133.910694] [ BUG: held lock freed! ]
> [  133.911700] 3.5.0-rc4+ #5 Not tainted
> [  133.912672] -------------------------
> [  133.912969] swapper/0/0 is freeing memory ffff88001233ce08-ffff88001233de07, with a lock still held there!
> [  133.912969]  (slock-AF_INET-RPC/1){+.-...}, at: [<ffffffff82ae84ee>] tcp_v4_rcv+0x28b/0x6fc
> [  133.912969] 3 locks held by swapper/0/0:
> [  133.912969]  #0:  (rcu_read_lock){.+.+..}, at: [<ffffffff82a1ea8a>] rcu_lock_acquire+0x0/0x29
> [  133.912969]  #1:  (rcu_read_lock){.+.+..}, at: [<ffffffff82aca483>] rcu_lock_acquire.constprop.14+0x0/0x30
> [  133.912969]  #2:  (slock-AF_INET-RPC/1){+.-...}, at: [<ffffffff82ae84ee>] tcp_v4_rcv+0x28b/0x6fc
> [  133.912969] 
> [  133.912969] stack backtrace:
> [  133.912969] Pid: 0, comm: swapper/0 Not tainted 3.5.0-rc4+ #5
> [  133.912969] Call Trace:
> [  133.912969]  <IRQ>  [<ffffffff810e09ae>] debug_check_no_locks_freed+0x109/0x14b
> [  133.912969]  [<ffffffff811774e0>] kmem_cache_free+0x2e/0xa7
> [  133.912969]  [<ffffffff82a191e5>] __kfree_skb+0x7f/0x83
> [  133.912969]  [<ffffffff82adeccd>] tcp_ack+0x45d/0xc6a
> [  133.912969]  [<ffffffff810c22ae>] ? local_clock+0x3b/0x52
> [  133.912969]  [<ffffffff82adff44>] tcp_rcv_state_process+0x15a/0x7c6
> [  133.912969]  [<ffffffff82ae79e7>] tcp_v4_do_rcv+0x341/0x390
> [  133.912969]  [<ffffffff82ae88db>] tcp_v4_rcv+0x678/0x6fc
> [  133.912969]  [<ffffffff82aca618>] ip_local_deliver_finish+0x165/0x1e4
> [  133.912969]  [<ffffffff82acab4a>] ip_local_deliver+0x53/0x84
> [  133.912969]  [<ffffffff810c228c>] ? local_clock+0x19/0x52
> [  133.912969]  [<ffffffff82aca9c6>] ip_rcv_finish+0x32f/0x367
> [  133.912969]  [<ffffffff82acad8b>] ip_rcv+0x210/0x269
> [  133.912969]  [<ffffffff82a1eab1>] ? rcu_lock_acquire+0x27/0x29
> [  133.912969]  [<ffffffff82a1ea8a>] ? softnet_seq_show+0x68/0x68
> [  133.912969]  [<ffffffff82a21ede>] __netif_receive_skb+0x3cd/0x464
> [  133.912969]  [<ffffffff82a21fda>] netif_receive_skb+0x65/0x9c
> [  133.912969]  [<ffffffff82a227c5>] ? __napi_gro_receive+0xf2/0xff
> [  133.912969]  [<ffffffff82a2209e>] napi_skb_finish+0x26/0x58
> [  133.912969]  [<ffffffff810c228c>] ? local_clock+0x19/0x52
> [  133.912969]  [<ffffffff82a228c5>] napi_gro_receive+0x2f/0x34
> [  133.912969]  [<ffffffff81e36d12>] e1000_receive_skb+0x57/0x60
> [  133.912969]  [<ffffffff81e39b23>] e1000_clean_rx_irq+0x2f2/0x387
> [  133.912969]  [<ffffffff81e390f3>] e1000_clean+0x541/0x695
> [  133.912969]  [<ffffffff8106c57b>] ? kvm_clock_read+0x2e/0x36
> [  133.912969]  [<ffffffff82a22402>] ? net_rx_action+0x1b3/0x1f8
> [  133.912969]  [<ffffffff82a22302>] net_rx_action+0xb3/0x1f8
> [  133.912969]  [<ffffffff810984ab>] ? __do_softirq+0x76/0x1e8
> [  133.912969]  [<ffffffff81098515>] __do_softirq+0xe0/0x1e8
> [  133.912969]  [<ffffffff81122190>] ? time_hardirqs_off+0x26/0x2a
> [  133.912969]  [<ffffffff82ea7fec>] call_softirq+0x1c/0x30
> [  133.912969]  [<ffffffff81049cc8>] do_softirq+0x4a/0xa2
> [  133.912969]  [<ffffffff8109888e>] irq_exit+0x51/0xbc
> [  133.912969]  [<ffffffff82ea88ae>] do_IRQ+0x8e/0xa5
> [  133.912969]  [<ffffffff82ea002f>] common_interrupt+0x6f/0x6f
> [  133.912969]  <EOI>  [<ffffffff8106c76b>] ? native_safe_halt+0x6/0x8
> [  133.912969]  [<ffffffff810e08a3>] ? trace_hardirqs_on+0xd/0xf
> [  133.912969]  [<ffffffff8104f384>] default_idle+0x53/0x90
> [  133.912969]  [<ffffffff8104fc09>] cpu_idle+0xcc/0x123
> [  133.912969]  [<ffffffff82d1d8dd>] rest_init+0xd1/0xda
> [  133.912969]  [<ffffffff82d1d80c>] ? csum_partial_copy_generic+0x16c/0x16c
> [  133.912969]  [<ffffffff8460dbbc>] start_kernel+0x3da/0x3e7
> [  133.912969]  [<ffffffff8460d5ea>] ? repair_env_string+0x5a/0x5a
> [  133.912969]  [<ffffffff8460d2d6>] x86_64_start_reservations+0xb1/0xb5
> [  133.912969]  [<ffffffff8460d3d8>] x86_64_start_kernel+0xfe/0x10b
> [  134.024230] VFS: Mounted root (nfs filesystem) on device 0:14.
> [  134.025782] debug: unmapping init [mem 0xffffffff84437000-0xffffffff8480efff]
> [  134.027686] Write protecting the kernel read-only data: 49152k
> [  134.029956] debug: unmapping init [mem 0xffff880002eb0000-0xffff880002ffffff]
> [  134.031745] debug: unmapping init [mem 0xffff880003e95000-0xffff880003ffffff]
> [  134.059408] request_module: runaway loop modprobe binfmt-0000
> [  134.062946] kworker/u:0 (2781) used greatest stack depth: 3432 bytes left
> [  134.069553] Kernel panic - not syncing: No init found.  Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.
> [  134.072742] Pid: 1, comm: swapper/0 Not tainted 3.5.0-rc4+ #5
> [  134.074200] Call Trace:
> [  134.074971]  [<ffffffff82e4fc90>] panic+0xbd/0x1d0
> [  134.076237]  [<ffffffff82e4ccc7>] init_post+0xc8/0xc8
> [  134.077636]  [<ffffffff8460dd8e>] kernel_init+0x1c5/0x1c5
> [  134.078979]  [<ffffffff8460d590>] ? do_early_param+0x8c/0x8c
> [  134.080408]  [<ffffffff82ea7ef4>] kernel_thread_helper+0x4/0x10
> [  134.082038]  [<ffffffff82ea00f0>] ? retint_restore_args+0x13/0x13
> [  134.083514]  [<ffffffff8460dbc9>] ? start_kernel+0x3e7/0x3e7
> [  134.084997]  [<ffffffff82ea7ef0>] ? gs_change+0x13/0x13
> 
> Thanks,
> Fengguang
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply


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