* Re: [Xen-devel] [PATCH] xen/netfront: handle compound page fragments on transmit
From: Jan Beulich @ 2012-11-20 12:28 UTC (permalink / raw)
To: Ian Campbell
Cc: Stefan Bader, Sander Eikelenboom, Eric Dumazet,
Konrad Rzeszutek Wilk, xen-devel, ANNIE LI, netdev
In-Reply-To: <1353411606-15940-1-git-send-email-ian.campbell@citrix.com>
>>> On 20.11.12 at 12:40, Ian Campbell <ian.campbell@citrix.com> wrote:
> An SKB paged fragment can consist of a compound page with order > 0.
> However the netchannel protocol deals only in PAGE_SIZE frames.
>
> Handle this in xennet_make_frags by iterating over the frames which
> make up the page.
>
> This is the netfront equivalent to 6a8ed462f16b for netback.
Wouldn't you need to be at least a little more conservative here
with respect to resource use: I realize that get_id_from_freelist()
return values were never checked, and failure of
gnttab_claim_grant_reference() was always dealt with via
BUG_ON(), but considering that netfront_tx_slot_available()
doesn't account for compound page fragments, I think this (lack
of) error handling needs improvement in the course of the
change here (regardless of - I think - someone having said that
usually the sum of all pages referenced from an skb's fragments
would not exceed MAX_SKB_FRAGS - "usually" just isn't enough
imo).
Jan
> Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> Cc: netdev@vger.kernel.org
> Cc: xen-devel@lists.xen.org
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Konrad Rzeszutek Wilk <konrad@kernel.org>
> Cc: ANNIE LI <annie.li@oracle.com>
> Cc: Sander Eikelenboom <linux@eikelenboom.it>
> Cc: Stefan Bader <stefan.bader@canonical.com>
> ---
> drivers/net/xen-netfront.c | 58 +++++++++++++++++++++++++++++++++----------
> 1 files changed, 44 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
> index caa0110..a12b99a 100644
> --- a/drivers/net/xen-netfront.c
> +++ b/drivers/net/xen-netfront.c
> @@ -452,24 +452,54 @@ static void xennet_make_frags(struct sk_buff *skb,
> struct net_device *dev,
> /* Grant backend access to each skb fragment page. */
> for (i = 0; i < frags; i++) {
> skb_frag_t *frag = skb_shinfo(skb)->frags + i;
> + struct page *page = skb_frag_page(frag);
> + unsigned long size = skb_frag_size(frag);
> + unsigned long offset = frag->page_offset;
>
> - tx->flags |= XEN_NETTXF_more_data;
> + /* Data must not cross a page boundary. */
> + BUG_ON(size + offset > PAGE_SIZE<<compound_order(page));
>
> - id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
> - np->tx_skbs[id].skb = skb_get(skb);
> - tx = RING_GET_REQUEST(&np->tx, prod++);
> - tx->id = id;
> - ref = gnttab_claim_grant_reference(&np->gref_tx_head);
> - BUG_ON((signed short)ref < 0);
> + /* Skip unused frames from start of page */
> + page += offset >> PAGE_SHIFT;
> + offset &= ~PAGE_MASK;
>
> - mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag)));
> - gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
> - mfn, GNTMAP_readonly);
> + while (size > 0) {
> + unsigned long bytes;
>
> - tx->gref = np->grant_tx_ref[id] = ref;
> - tx->offset = frag->page_offset;
> - tx->size = skb_frag_size(frag);
> - tx->flags = 0;
> + BUG_ON(offset >= PAGE_SIZE);
> +
> + bytes = PAGE_SIZE - offset;
> + if (bytes > size)
> + bytes = size;
> +
> + tx->flags |= XEN_NETTXF_more_data;
> +
> + id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
> + np->tx_skbs[id].skb = skb_get(skb);
> + tx = RING_GET_REQUEST(&np->tx, prod++);
> + tx->id = id;
> + ref = gnttab_claim_grant_reference(&np->gref_tx_head);
> + BUG_ON((signed short)ref < 0);
> +
> + mfn = pfn_to_mfn(page_to_pfn(page));
> + gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
> + mfn, GNTMAP_readonly);
> +
> + tx->gref = np->grant_tx_ref[id] = ref;
> + tx->offset = offset;
> + tx->size = bytes;
> + tx->flags = 0;
> +
> + offset += bytes;
> + size -= bytes;
> +
> + /* Next frame */
> + if (offset == PAGE_SIZE && size) {
> + BUG_ON(!PageCompound(page));
> + page++;
> + offset = 0;
> + }
> + }
> }
>
> np->tx.req_prod_pvt = prod;
> --
> 1.7.2.5
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
^ permalink raw reply
* Re: [PATCH v2] checkpatch: add double empty line check
From: Andy Whitcroft @ 2012-11-20 11:52 UTC (permalink / raw)
To: Eilon Greenstein; +Cc: Joe Perches, David Rientjes, linux-kernel, netdev
In-Reply-To: <1353151057.14327.18.camel@lb-tlvb-eilong.il.broadcom.com>
On Sat, Nov 17, 2012 at 01:17:37PM +0200, Eilon Greenstein wrote:
> Changes from previous attempt:
> - Use CHK instead of WARN
> - Issue only one warning per empty lines block
>
> Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
> ---
> scripts/checkpatch.pl | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
> index 21a9f5d..13d264f 100755
> --- a/scripts/checkpatch.pl
> +++ b/scripts/checkpatch.pl
> @@ -3579,6 +3579,14 @@ sub process {
> WARN("EXPORTED_WORLD_WRITABLE",
> "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
> }
> +
> +# check for double empty lines
> + if ($line =~ /^\+\s*$/ &&
> + ($rawlines[$linenr] =~ /^\s*$/ ||
> + $prevline =~ /^\+?\s*$/ && $rawlines[$linenr] !~ /^\+\s*$/)) {
> + CHK("DOUBLE_EMPTY_LINE",
> + "One empty line should be sufficient. Consider removing this one.\n" . $herecurr);
> + }
> }
>
> # If we have no input at all, then there is nothing to report on
In your previous version you indicated you would be emiting one per group
of lines, I do not see how this does that. Also this fails if the fragment
is at the top of the hunk emiting a perl warning. We should probabally
use the suppress approach.
How about something like the below.
-apw
>From 848ebffa8656a1ff96a91788ec0f1c04dab9c3e9 Mon Sep 17 00:00:00 2001
From: Andy Whitcroft <apw@canonical.com>
Date: Sat, 17 Nov 2012 13:17:37 +0200
Subject: [PATCH] checkpatch: strict warning for multiple blank lines
Signed-off-by: Andy Whitcroft <apw@canonical.com>
---
scripts/checkpatch.pl | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index f18750e..dbc68f3 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1411,6 +1411,7 @@ sub process {
my %suppress_whiletrailers;
my %suppress_export;
my $suppress_statement = 0;
+ my $suppress_multipleblank = -1;
# Pre-scan the patch sanitizing the lines.
# Pre-scan the patch looking for any __setup documentation.
@@ -1521,6 +1522,7 @@ sub process {
%suppress_whiletrailers = ();
%suppress_export = ();
$suppress_statement = 0;
+ $suppress_multipleblank = -1;
next;
# track the line number as we move through the hunk, note that
@@ -1930,6 +1932,15 @@ sub process {
"use the SSYNC() macro in asm/blackfin.h\n" . $herevet);
}
+# multiple blank lines.
+ if ($line =~ /^-/ || ($suppress_multipleblank == $linenr && $line =~ /^[ \+]\s*$/)) {
+ $suppress_multipleblank++;
+ } elsif ($prevline =~ /^\+\s*$/ and $line =~ /^\+\s*$/) {
+ $suppress_multipleblank = $linenr + 1;
+ CHK("MULTIPLE_EMPTY_LINE",
+ "One empty line should be sufficient. Consider removing this one.\n" . $herecurr);
+ }
+
# Check for potential 'bare' types
my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
$realline_next);
--
1.7.10.4
^ permalink raw reply related
* [PATCH] xen/netfront: handle compound page fragments on transmit
From: Ian Campbell @ 2012-11-20 11:40 UTC (permalink / raw)
To: netdev
Cc: Ian Campbell, xen-devel, Eric Dumazet, Konrad Rzeszutek Wilk,
ANNIE LI, Sander Eikelenboom, Stefan Bader
In-Reply-To: <1353403286.18229.159.camel@zakaz.uk.xensource.com>
An SKB paged fragment can consist of a compound page with order > 0.
However the netchannel protocol deals only in PAGE_SIZE frames.
Handle this in xennet_make_frags by iterating over the frames which
make up the page.
This is the netfront equivalent to 6a8ed462f16b for netback.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: netdev@vger.kernel.org
Cc: xen-devel@lists.xen.org
Cc: Eric Dumazet <edumazet@google.com>
Cc: Konrad Rzeszutek Wilk <konrad@kernel.org>
Cc: ANNIE LI <annie.li@oracle.com>
Cc: Sander Eikelenboom <linux@eikelenboom.it>
Cc: Stefan Bader <stefan.bader@canonical.com>
---
drivers/net/xen-netfront.c | 58 +++++++++++++++++++++++++++++++++----------
1 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index caa0110..a12b99a 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -452,24 +452,54 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
/* Grant backend access to each skb fragment page. */
for (i = 0; i < frags; i++) {
skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+ struct page *page = skb_frag_page(frag);
+ unsigned long size = skb_frag_size(frag);
+ unsigned long offset = frag->page_offset;
- tx->flags |= XEN_NETTXF_more_data;
+ /* Data must not cross a page boundary. */
+ BUG_ON(size + offset > PAGE_SIZE<<compound_order(page));
- id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
- np->tx_skbs[id].skb = skb_get(skb);
- tx = RING_GET_REQUEST(&np->tx, prod++);
- tx->id = id;
- ref = gnttab_claim_grant_reference(&np->gref_tx_head);
- BUG_ON((signed short)ref < 0);
+ /* Skip unused frames from start of page */
+ page += offset >> PAGE_SHIFT;
+ offset &= ~PAGE_MASK;
- mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag)));
- gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
- mfn, GNTMAP_readonly);
+ while (size > 0) {
+ unsigned long bytes;
- tx->gref = np->grant_tx_ref[id] = ref;
- tx->offset = frag->page_offset;
- tx->size = skb_frag_size(frag);
- tx->flags = 0;
+ BUG_ON(offset >= PAGE_SIZE);
+
+ bytes = PAGE_SIZE - offset;
+ if (bytes > size)
+ bytes = size;
+
+ tx->flags |= XEN_NETTXF_more_data;
+
+ id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
+ np->tx_skbs[id].skb = skb_get(skb);
+ tx = RING_GET_REQUEST(&np->tx, prod++);
+ tx->id = id;
+ ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+ BUG_ON((signed short)ref < 0);
+
+ mfn = pfn_to_mfn(page_to_pfn(page));
+ gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
+ mfn, GNTMAP_readonly);
+
+ tx->gref = np->grant_tx_ref[id] = ref;
+ tx->offset = offset;
+ tx->size = bytes;
+ tx->flags = 0;
+
+ offset += bytes;
+ size -= bytes;
+
+ /* Next frame */
+ if (offset == PAGE_SIZE && size) {
+ BUG_ON(!PageCompound(page));
+ page++;
+ offset = 0;
+ }
+ }
}
np->tx.req_prod_pvt = prod;
--
1.7.2.5
^ permalink raw reply related
* PROBLEM: losing addresses if reusing interface names too fast
From: Jan Dvořák @ 2012-11-20 11:38 UTC (permalink / raw)
To: netdev
(re-sent with proper subject)
Summary: If I reuse interface names too fast, I end up losing newly
configured addresses on the new interface.
Detailed Description:
I have noticed a surprising behavior when removing virtual interfaces.
For example, removing a bridge with configured IP addresses and then
quickly creating another interface with identical name will cause the
addresses to be removed from the new interface a second or so later.
How To Reproduce:
brctl addbr foobar
ip addr add 10.20.30.40/24 dev foobar
ip addr show dev foobar
# 40: foobar: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
# link/ether 12:12:f5:1b:c6:8e brd ff:ff:ff:ff:ff:ff
# inet 10.20.30.40/24 scope global foobar
sleep 1
ip link set down dev foobar
brctl delbr foobar
ip link add name foobar link em1 type vlan id 42
ip addr add 10.20.30.40/24 dev foobar
ip addr show dev foobar
# 41: foobar@em1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN
# link/ether 00:21:cc:63:ec:3c brd ff:ff:ff:ff:ff:ff
# inet 10.20.30.40/24 scope global foobar
sleep 3
ip addr show dev foobar
# 41: foobar@em1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN
# link/ether 00:21:cc:63:ec:3c brd ff:ff:ff:ff:ff:ff
ip link del foobar type vlan
Other Relevant Observations:
If you monitor udev during course of this script, you will get
following sequence, spaces where sleeps were:
KERNEL[457506.286789] add /devices/virtual/net/foobar (net)
KERNEL[457507.298630] remove /devices/virtual/net/foobar (net)
KERNEL[457507.309597] add /devices/virtual/net/foobar (net)
KERNEL[457510.324433] remove /devices/virtual/net/foobar (net)
This means that I can't event wait for the bridge to get completely
removed, kernel tells me it's gone as soon as I delete it.
Could you please advise a workaround or confirm this as a bug?
Best regards,
Jan Dvorak
^ permalink raw reply
* Re: [Xen-devel] compound skb frag pages appearing in start_xmit
From: Ian Campbell @ 2012-11-20 11:36 UTC (permalink / raw)
To: Stefan Bader
Cc: Eric Dumazet, Konrad Rzeszutek Wilk, netdev@vger.kernel.org,
Marcos E. Matsunaga, xen-devel, Sander Eikelenboom, ANNIE LI,
Eric Dumazet
In-Reply-To: <1353403286.18229.159.camel@zakaz.uk.xensource.com>
On Tue, 2012-11-20 at 09:21 +0000, Ian Campbell wrote:
> On Tue, 2012-11-20 at 08:30 +0000, Stefan Bader wrote:
> > >> When I tried to rebase my persistent grant netfront/netback patch on
> > >> latest kernel, netperf/netserver test never succeeded. I did some test
> > >> to find out that v3.6-rc7 works fine, but v3.7-rc1, v3.7-rc2 and
> > >> v3.7-rc4 does not succeed in netperf/netserver test. So I keep my
> > >> persistent grant patch only based on v3.4-rc3 now.
> > >
> > >> Konrad thought about commit 6a8ed462f16b8455eec5ae00eb6014159a6721f0 in
> > >> v3.7-rc1, and suggested me to test your debug patch in netfront. This
> > >> BUG_ON happens soon after running the netperf/netserver test case.
> > >
> > >> Thanks
> > >> Annie
> > >
> > > Is there any progression with this bug (rc6 is out the door, so the
> > release of 3.7-final seems to be eminent and this bug completely
> > cripples any networking with guests) ?
> > >
> >
> > +1 on that. I was testing yesterday with a PVM domU running 3.7-rc5 on Xen 4.2
> > (but also reported from EC2 running Xen 3.4.3) c with one VCPU. I actually can
> > trigger it by just ssh'ing into the domU (from another machine) and then run
> > "find /". Output starts to stutter and then stops completely. When this happens
> > a new connection still can be made and as long as only shorter output is
> > generated the ssh connection is ok. From a dump taken it looks like user-space
> > is waiting in some select call (without any warnon I rather won't see the tx path).
>
> Annie, are you still looking into this or shall I?
I'll assume that silence == No. Will post a patch shortly.
Ian.
^ permalink raw reply
* Re: [PATCH 3/3] net: mvneta: adjust multiline comments to net/ style
From: Sergei Shtylyov @ 2012-11-20 11:22 UTC (permalink / raw)
To: Thomas Petazzoni
Cc: Jason Cooper, Lior Amsalem, Andrew Lunn, netdev, Gregory Clement,
David S. Miller, linux-arm-kernel
In-Reply-To: <20121119135609.3808b1c7@skate>
Hello.
On 19-11-2012 16:56, Thomas Petazzoni wrote:
>>> -/*
>>> - * The two bytes Marvell header. Either contains a special value used
>>> +/* The two bytes Marvell header. Either contains a special value used
>>
>> Why the heck you're doing this? It's the preferred style, see
>> Documentation/CodingStyle, chapter 8.
> No. Please read Documentation/CodingStyle, chapter 8 entirely:
> ===============================================================
> The preferred style for long (multi-line) comments is:
>
> /*
> * This is the preferred style for multi-line
> * comments in the Linux kernel source code.
> * Please use it consistently.
> *
> * Description: A column of asterisks on the left side,
> * with beginning and ending almost-blank lines.
> */
>
> For files in net/ and drivers/net/ the preferred style for long
> (multi-line) comments is a little different.
>
> /* The preferred comment style for files in net/ and drivers/net
> * looks like this.
> *
> * It is nearly the same as the generally preferred comment style,
> * but there is no initial almost-blank line.
> */
> ===============================================================
> Seen the second part?
Not until now probably. Sorry for the noise then. :-/
WBR, Sergei
^ permalink raw reply
* RE: [PATCH 1/1] caif: Remove redundant null check before kfree in cfctrl.c
From: Sjur BRENDELAND @ 2012-11-20 11:04 UTC (permalink / raw)
To: Sachin Kamat, netdev@vger.kernel.org
Cc: davem@davemloft.net, patches@linaro.org
In-Reply-To: <1353408838-28678-1-git-send-email-sachin.kamat@linaro.org>
> kfree on a null pointer is a no-op.
>
> Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Acked-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
^ permalink raw reply
* [PATCH 1/2] net: Remove redundant null check before kfree in dev.c
From: Sachin Kamat @ 2012-11-20 10:57 UTC (permalink / raw)
To: netdev; +Cc: davem, edumazet, sachin.kamat, patches
kfree on a null pointer is a no-op.
Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
---
net/core/dev.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 83232a1..c380913 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1075,10 +1075,8 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len)
return -EINVAL;
if (!len) {
- if (dev->ifalias) {
- kfree(dev->ifalias);
- dev->ifalias = NULL;
- }
+ kfree(dev->ifalias);
+ dev->ifalias = NULL;
return 0;
}
--
1.7.4.1
^ permalink raw reply related
* [PATCH 1/1] caif: Remove redundant null check before kfree in cfctrl.c
From: Sachin Kamat @ 2012-11-20 10:53 UTC (permalink / raw)
To: netdev; +Cc: davem, sjur.brandeland, sachin.kamat, patches
kfree on a null pointer is a no-op.
Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
---
net/caif/cfctrl.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c
index 44f270f..a376ec1 100644
--- a/net/caif/cfctrl.c
+++ b/net/caif/cfctrl.c
@@ -515,8 +515,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
client_layer : NULL);
}
- if (req != NULL)
- kfree(req);
+ kfree(req);
spin_unlock_bh(&cfctrl->info_list_lock);
}
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH v5] can: kvaser_usb: Add support for Kvaser CAN/USB devices
From: Marc Kleine-Budde @ 2012-11-20 10:59 UTC (permalink / raw)
To: Olivier Sobrie; +Cc: Wolfgang Grandegger, linux-can, netdev, linux-usb
In-Reply-To: <20121120084626.GA14897@hposo>
[-- Attachment #1: Type: text/plain, Size: 5252 bytes --]
On 11/20/2012 09:46 AM, Olivier Sobrie wrote:
[...]
>>> +static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
>>> + struct net_device *netdev)
>>> +{
>>> + struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
>>> + struct kvaser_usb *dev = priv->dev;
>>> + struct net_device_stats *stats = &netdev->stats;
>>> + struct can_frame *cf = (struct can_frame *)skb->data;
>>> + struct kvaser_usb_tx_urb_context *context = NULL;
>>> + struct urb *urb;
>>> + void *buf;
>>> + struct kvaser_msg *msg;
>>> + int i, err;
>>> + int ret = NETDEV_TX_OK;
>>> +
>>> + if (can_dropped_invalid_skb(netdev, skb))
>>> + return NETDEV_TX_OK;
>>> +
>>> + urb = usb_alloc_urb(0, GFP_ATOMIC);
>>> + if (!urb) {
>>> + netdev_err(netdev, "No memory left for URBs\n");
>>> + stats->tx_dropped++;
>>
>> Move the dev_kfree_skb to the end and goto there.
>
> I assume you mean doing something like that at the end of the function:
Yes.
> releasebuf:
> kfree(buf);
> nobufmem:
> usb_free_urb(urb);
> nourbmem:
> dev_kfree_skb(skb);
> return ret;
>
> If I do that it will give problems when the 'releasebuf' condition is
> reached. The skb buffer will be freed twice. The skb is already freed
> by the function can_free_echo_skb().
Okay. dev_kfree_skb(skb) will work with skb == NULL. So just set skb to
NULL after can_free_echo_skb(). Maybe along with a short comment: "set
to NULL to avoid double free in dev_kfree_skb(skb)".
>
>>
>>> + dev_kfree_skb(skb);
>>> + return NETDEV_TX_OK;
>>> + }
>>> +
>>> + buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
>>> + if (!buf) {
>>> + netdev_err(netdev, "No memory left for USB buffer\n");
>>> + stats->tx_dropped++;
>> You cann usb_free_urb twice...here and in the error handling at the end.
>
> Indeed thanks.
>
>>
>>> + dev_kfree_skb(skb);
>>> + usb_free_urb(urb);
>>> + goto nobufmem;
>>> + }
>>> +
>>> + msg = buf;
>>> + msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_tx_can);
>>> + msg->u.tx_can.flags = 0;
>>> + msg->u.tx_can.channel = priv->channel;
>>> +
>>> + if (cf->can_id & CAN_EFF_FLAG) {
>>> + msg->id = CMD_TX_EXT_MESSAGE;
>>> + msg->u.tx_can.msg[0] = (cf->can_id >> 24) & 0x1f;
>>> + msg->u.tx_can.msg[1] = (cf->can_id >> 18) & 0x3f;
>>> + msg->u.tx_can.msg[2] = (cf->can_id >> 14) & 0x0f;
>>> + msg->u.tx_can.msg[3] = (cf->can_id >> 6) & 0xff;
>>> + msg->u.tx_can.msg[4] = cf->can_id & 0x3f;
>>> + } else {
>>> + msg->id = CMD_TX_STD_MESSAGE;
>>> + msg->u.tx_can.msg[0] = (cf->can_id >> 6) & 0x1f;
>>> + msg->u.tx_can.msg[1] = cf->can_id & 0x3f;
>>> + }
>>> +
>>> + msg->u.tx_can.msg[5] = cf->can_dlc;
>>> + memcpy(&msg->u.tx_can.msg[6], cf->data, cf->can_dlc);
>>> +
>>> + if (cf->can_id & CAN_RTR_FLAG)
>>> + msg->u.tx_can.flags |= MSG_FLAG_REMOTE_FRAME;
>>> +
>>> + for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++) {
>>> + if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
>>> + context = &priv->tx_contexts[i];
>>> + break;
>>> + }
>>> + }
>>> +
>>> + if (!context) {
>>> + netdev_warn(netdev, "cannot find free context\n");
>>> + ret = NETDEV_TX_BUSY;
>>> + goto releasebuf;
>>> + }
>>> +
>>> + context->priv = priv;
>>> + context->echo_index = i;
>>> + context->dlc = cf->can_dlc;
>>> +
>>> + msg->u.tx_can.tid = context->echo_index;
>>> +
>>> + usb_fill_bulk_urb(urb, dev->udev,
>>> + usb_sndbulkpipe(dev->udev,
>>> + dev->bulk_out->bEndpointAddress),
>>> + buf, msg->len,
>>> + kvaser_usb_write_bulk_callback, context);
>>> + usb_anchor_urb(urb, &priv->tx_submitted);
>>> +
>>> + can_put_echo_skb(skb, netdev, context->echo_index);
>>> +
>>> + atomic_inc(&priv->active_tx_urbs);
>>> +
>>> + if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
>>> + netif_stop_queue(netdev);
>>> +
>>> + err = usb_submit_urb(urb, GFP_ATOMIC);
>>> + if (unlikely(err)) {
>>> + can_free_echo_skb(netdev, context->echo_index);
>>> +
skb = NULL; /* +comment */
>>> + atomic_dec(&priv->active_tx_urbs);
>>> + usb_unanchor_urb(urb);
>>> +
>>> + stats->tx_dropped++;
>>> +
>>> + if (err == -ENODEV)
>>> + netif_device_detach(netdev);
>>> + else
>>> + netdev_warn(netdev, "Failed tx_urb %d\n", err);
>>> +
>>> + goto releasebuf;
>>> + }
>>> +
>>> + usb_free_urb(urb);
>>> +
>>> + return NETDEV_TX_OK;
>>> +
>>> +releasebuf:
>>> + kfree(buf);
>>> +nobufmem:
>>> + usb_free_urb(urb);
>>> + return ret;
>>> +}
[...]
>>> +static struct usb_driver kvaser_usb_driver = {
>>> + .name = "kvaser_usb",
>>> + .probe = kvaser_usb_probe,
>>> + .disconnect = kvaser_usb_disconnect,
>>> + .id_table = kvaser_usb_table
>> ^^^
>> nitpick, please add a "," there.
>
> Ok.
>
>>> +};
>>>
>> can you please add MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
>
> It is already present just after the kvaser_usb_table structure.
:) You're right.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 261 bytes --]
^ permalink raw reply
* Re: [PATCH 136/493] ethernet: remove use of __devexit_p
From: Nicolas Ferre @ 2012-11-20 9:31 UTC (permalink / raw)
To: Bill Pemberton
Cc: gregkh, linux-mips, Chris Snook, David Dillow, Jaroslav Kysela,
Daniele Venzano, Samuel Chessman, Stephen Hemminger, John Linn,
Russell King, e1000-devel, Guo-Fu Tseng, linux-acenic,
Francois Romieu, Steve Glendinning, Jes Sorensen, Jay Cliburn,
Realtek linux nic maintainers, Grant Grundler, Wan ZongShun
In-Reply-To: <1353349642-3677-136-git-send-email-wfp5p@virginia.edu>
On 11/19/2012 07:21 PM, Bill Pemberton :
> CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
> needed.
>
> Signed-off-by: Bill Pemberton <wfp5p@virginia.edu>
> Cc: Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
> Cc: David Dillow <dave@thedillows.org>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Kristoffer Glembo <kristoffer@gaisler.com>
> Cc: Jes Sorensen <jes@trained-monkey.org>
> Cc: Don Fry <pcnet32@frontier.com>
> Cc: Jay Cliburn <jcliburn@gmail.com>
> Cc: Chris Snook <chris.snook@gmail.com>
> Cc: Grant Grundler <grundler@parisc-linux.org>
> Cc: Jaroslav Kysela <perex@perex.cz>
> Cc: Francois Romieu <romieu@fr.zoreil.com>
> Cc: Sorbica Shieh <sorbica@icplus.com.tw>
> Cc: Guo-Fu Tseng <cooldavid@cooldavid.org>
> Cc: Mirko Lindner <mlindner@marvell.com>
> Cc: Stephen Hemminger <shemminger@vyatta.com>
> Cc: Wan ZongShun <mcuos.com@gmail.com>
> Cc: Olof Johansson <olof@lixom.net>
> Cc: Florian Fainelli <florian@openwrt.org>
> Cc: Realtek linux nic maintainers <nic_swsd@realtek.com>
> Cc: Ralf Baechle <ralf@linux-mips.org>
> Cc: Daniele Venzano <venza@brownhat.org>
> Cc: Steve Glendinning <steve.glendinning@shawell.net>
> Cc: Samuel Chessman <chessman@tux.org>
> Cc: Roger Luethi <rl@hellgate.ch>
> Cc: Anirudha Sarangi <anirudh@xilinx.com>
> Cc: John Linn <John.Linn@xilinx.com>
> Cc: netdev@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: uclinux-dist-devel@blackfin.uclinux.org
> Cc: linux-acenic@sunsite.dk
> Cc: e1000-devel@lists.sourceforge.net
> Cc: linux-mips@linux-mips.org
> ---
> drivers/net/ethernet/cadence/at91_ether.c | 2 +-
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c
> index 1a8eef2..7d7cd67 100644
> --- a/drivers/net/ethernet/3com/3c509.c
> +++ b/drivers/net/ethernet/3com/3c509.c
> @@ -382,7 +382,7 @@ static int el3_isa_resume(struct device *dev, unsigned int n)
>
> static struct isa_driver el3_isa_driver = {
> .match = el3_isa_match,
> - .remove = __devexit_p(el3_isa_remove),
> + .remove = el3_isa_remove,
> #ifdef CONFIG_PM
> .suspend = el3_isa_suspend,
> .resume = el3_isa_resume,
> @@ -467,7 +467,7 @@ static struct pnp_driver el3_pnp_driver = {
> .name = "3c509",
> .id_table = el3_pnp_ids,
> .probe = el3_pnp_probe,
> - .remove = __devexit_p(el3_pnp_remove),
> + .remove = el3_pnp_remove,
> #ifdef CONFIG_PM
> .suspend = el3_pnp_suspend,
> .resume = el3_pnp_resume,
> @@ -496,7 +496,7 @@ static struct eisa_driver el3_eisa_driver = {
> .driver = {
> .name = "3c579",
> .probe = el3_eisa_probe,
> - .remove = __devexit_p (el3_device_remove),
> + .remove = el3_device_remove,
> .suspend = el3_suspend,
> .resume = el3_resume,
> }
> diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
> index e463d10..7cff8b8 100644
> --- a/drivers/net/ethernet/3com/3c59x.c
> +++ b/drivers/net/ethernet/3com/3c59x.c
> @@ -962,7 +962,7 @@ static struct eisa_driver vortex_eisa_driver = {
> .driver = {
> .name = "3c59x",
> .probe = vortex_eisa_probe,
> - .remove = __devexit_p(vortex_eisa_remove)
> + .remove = vortex_eisa_remove
> }
> };
>
> @@ -3265,7 +3265,7 @@ static void __devexit vortex_remove_one(struct pci_dev *pdev)
> static struct pci_driver vortex_driver = {
> .name = "3c59x",
> .probe = vortex_init_one,
> - .remove = __devexit_p(vortex_remove_one),
> + .remove = vortex_remove_one,
> .id_table = vortex_pci_tbl,
> .driver.pm = VORTEX_PM_OPS,
> };
> diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
> index bb9670f..e11b27f 100644
> --- a/drivers/net/ethernet/3com/typhoon.c
> +++ b/drivers/net/ethernet/3com/typhoon.c
> @@ -2533,7 +2533,7 @@ static struct pci_driver typhoon_driver = {
> .name = KBUILD_MODNAME,
> .id_table = typhoon_pci_tbl,
> .probe = typhoon_init_one,
> - .remove = __devexit_p(typhoon_remove_one),
> + .remove = typhoon_remove_one,
> #ifdef CONFIG_PM
> .suspend = typhoon_suspend,
> .resume = typhoon_resume,
> diff --git a/drivers/net/ethernet/8390/etherh.c b/drivers/net/ethernet/8390/etherh.c
> index 8322c54..96ed50d 100644
> --- a/drivers/net/ethernet/8390/etherh.c
> +++ b/drivers/net/ethernet/8390/etherh.c
> @@ -839,7 +839,7 @@ static const struct ecard_id etherh_ids[] = {
>
> static struct ecard_driver etherh_driver = {
> .probe = etherh_probe,
> - .remove = __devexit_p(etherh_remove),
> + .remove = etherh_remove,
> .id_table = etherh_ids,
> .drv = {
> .name = DRV_NAME,
> diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c
> index 5e8845f..8f09fd99 100644
> --- a/drivers/net/ethernet/8390/ne2k-pci.c
> +++ b/drivers/net/ethernet/8390/ne2k-pci.c
> @@ -696,7 +696,7 @@ static int ne2k_pci_resume (struct pci_dev *pdev)
> static struct pci_driver ne2k_driver = {
> .name = DRV_NAME,
> .probe = ne2k_pci_init_one,
> - .remove = __devexit_p(ne2k_pci_remove_one),
> + .remove = ne2k_pci_remove_one,
> .id_table = ne2k_pci_tbl,
> #ifdef CONFIG_PM
> .suspend = ne2k_pci_suspend,
> diff --git a/drivers/net/ethernet/8390/ne3210.c b/drivers/net/ethernet/8390/ne3210.c
> index e3f5742..8579e2f 100644
> --- a/drivers/net/ethernet/8390/ne3210.c
> +++ b/drivers/net/ethernet/8390/ne3210.c
> @@ -324,7 +324,7 @@ static struct eisa_driver ne3210_eisa_driver = {
> .driver = {
> .name = "ne3210",
> .probe = ne3210_eisa_probe,
> - .remove = __devexit_p (ne3210_eisa_remove),
> + .remove = ne3210_eisa_remove,
> },
> };
>
> diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c
> index 7818e63..9a041a6 100644
> --- a/drivers/net/ethernet/8390/zorro8390.c
> +++ b/drivers/net/ethernet/8390/zorro8390.c
> @@ -432,7 +432,7 @@ static struct zorro_driver zorro8390_driver = {
> .name = "zorro8390",
> .id_table = zorro8390_zorro_tbl,
> .probe = zorro8390_init_one,
> - .remove = __devexit_p(zorro8390_remove_one),
> + .remove = zorro8390_remove_one,
> };
>
> static int __init zorro8390_init_module(void)
> diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
> index 5b65992c..e986818 100644
> --- a/drivers/net/ethernet/adaptec/starfire.c
> +++ b/drivers/net/ethernet/adaptec/starfire.c
> @@ -2018,7 +2018,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev)
> static struct pci_driver starfire_driver = {
> .name = DRV_NAME,
> .probe = starfire_init_one,
> - .remove = __devexit_p(starfire_remove_one),
> + .remove = starfire_remove_one,
> #ifdef CONFIG_PM
> .suspend = starfire_suspend,
> .resume = starfire_resume,
> diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
> index f1c458d..cfcce5b 100644
> --- a/drivers/net/ethernet/adi/bfin_mac.c
> +++ b/drivers/net/ethernet/adi/bfin_mac.c
> @@ -1881,7 +1881,7 @@ static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
>
> static struct platform_driver bfin_mii_bus_driver = {
> .probe = bfin_mii_bus_probe,
> - .remove = __devexit_p(bfin_mii_bus_remove),
> + .remove = bfin_mii_bus_remove,
> .driver = {
> .name = "bfin_mii_bus",
> .owner = THIS_MODULE,
> @@ -1890,7 +1890,7 @@ static struct platform_driver bfin_mii_bus_driver = {
>
> static struct platform_driver bfin_mac_driver = {
> .probe = bfin_mac_probe,
> - .remove = __devexit_p(bfin_mac_remove),
> + .remove = bfin_mac_remove,
> .resume = bfin_mac_resume,
> .suspend = bfin_mac_suspend,
> .driver = {
> diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
> index 9c77c73..3629690 100644
> --- a/drivers/net/ethernet/aeroflex/greth.c
> +++ b/drivers/net/ethernet/aeroflex/greth.c
> @@ -1619,7 +1619,7 @@ static struct platform_driver greth_of_driver = {
> .of_match_table = greth_of_match,
> },
> .probe = greth_of_probe,
> - .remove = __devexit_p(greth_of_remove),
> + .remove = greth_of_remove,
> };
>
> module_platform_driver(greth_of_driver);
> diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c
> index 7219123..9cb94b3 100644
> --- a/drivers/net/ethernet/alteon/acenic.c
> +++ b/drivers/net/ethernet/alteon/acenic.c
> @@ -699,7 +699,7 @@ static struct pci_driver acenic_pci_driver = {
> .name = "acenic",
> .id_table = acenic_pci_tbl,
> .probe = acenic_probe_one,
> - .remove = __devexit_p(acenic_remove_one),
> + .remove = acenic_remove_one,
> };
>
> static int __init acenic_init(void)
> diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c
> index 689dfca..2745c0a 100644
> --- a/drivers/net/ethernet/amd/a2065.c
> +++ b/drivers/net/ethernet/amd/a2065.c
> @@ -656,7 +656,7 @@ static struct zorro_driver a2065_driver = {
> .name = "a2065",
> .id_table = a2065_zorro_tbl,
> .probe = a2065_init_one,
> - .remove = __devexit_p(a2065_remove_one),
> + .remove = a2065_remove_one,
> };
>
> static const struct net_device_ops lance_netdev_ops = {
> diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c
> index 3491d43..5891636 100644
> --- a/drivers/net/ethernet/amd/amd8111e.c
> +++ b/drivers/net/ethernet/amd/amd8111e.c
> @@ -1976,7 +1976,7 @@ static struct pci_driver amd8111e_driver = {
> .name = MODULE_NAME,
> .id_table = amd8111e_pci_tbl,
> .probe = amd8111e_probe_one,
> - .remove = __devexit_p(amd8111e_remove_one),
> + .remove = amd8111e_remove_one,
> .suspend = amd8111e_suspend,
> .resume = amd8111e_resume
> };
> diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c
> index f2958df9..72b56a8 100644
> --- a/drivers/net/ethernet/amd/ariadne.c
> +++ b/drivers/net/ethernet/amd/ariadne.c
> @@ -774,7 +774,7 @@ static struct zorro_driver ariadne_driver = {
> .name = "ariadne",
> .id_table = ariadne_zorro_tbl,
> .probe = ariadne_init_one,
> - .remove = __devexit_p(ariadne_remove_one),
> + .remove = ariadne_remove_one,
> };
>
> static int __init ariadne_init_module(void)
> diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
> index f195acf..cbbfdc9 100644
> --- a/drivers/net/ethernet/amd/au1000_eth.c
> +++ b/drivers/net/ethernet/amd/au1000_eth.c
> @@ -1340,7 +1340,7 @@ static int __devexit au1000_remove(struct platform_device *pdev)
>
> static struct platform_driver au1000_eth_driver = {
> .probe = au1000_probe,
> - .remove = __devexit_p(au1000_remove),
> + .remove = au1000_remove,
> .driver = {
> .name = "au1000-eth",
> .owner = THIS_MODULE,
> diff --git a/drivers/net/ethernet/amd/depca.c b/drivers/net/ethernet/amd/depca.c
> index c771de7..8a86c06 100644
> --- a/drivers/net/ethernet/amd/depca.c
> +++ b/drivers/net/ethernet/amd/depca.c
> @@ -338,7 +338,7 @@ static struct eisa_driver depca_eisa_driver = {
> .driver = {
> .name = depca_string,
> .probe = depca_eisa_probe,
> - .remove = __devexit_p (depca_device_remove)
> + .remove = depca_device_remove
> }
> };
> #endif
> @@ -352,7 +352,7 @@ static int __devexit depca_isa_remove(struct platform_device *pdev)
>
> static struct platform_driver depca_isa_driver = {
> .probe = depca_isa_probe,
> - .remove = __devexit_p(depca_isa_remove),
> + .remove = depca_isa_remove,
> .driver = {
> .name = depca_string,
> },
> diff --git a/drivers/net/ethernet/amd/hplance.c b/drivers/net/ethernet/amd/hplance.c
> index 8baff4e..1b2d4a1 100644
> --- a/drivers/net/ethernet/amd/hplance.c
> +++ b/drivers/net/ethernet/amd/hplance.c
> @@ -66,7 +66,7 @@ static struct dio_driver hplance_driver = {
> .name = "hplance",
> .id_table = hplance_dio_tbl,
> .probe = hplance_init_one,
> - .remove = __devexit_p(hplance_remove_one),
> + .remove = hplance_remove_one,
> };
>
> static const struct net_device_ops hplance_netdev_ops = {
> diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
> index 86b6d8e..d16fcd8 100644
> --- a/drivers/net/ethernet/amd/pcnet32.c
> +++ b/drivers/net/ethernet/amd/pcnet32.c
> @@ -2844,7 +2844,7 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
> static struct pci_driver pcnet32_driver = {
> .name = DRV_NAME,
> .probe = pcnet32_probe_pci,
> - .remove = __devexit_p(pcnet32_remove_one),
> + .remove = pcnet32_remove_one,
> .id_table = pcnet32_pci_tbl,
> .suspend = pcnet32_pm_suspend,
> .resume = pcnet32_pm_resume,
> diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c
> index d7a3533..d794921 100644
> --- a/drivers/net/ethernet/amd/sunlance.c
> +++ b/drivers/net/ethernet/amd/sunlance.c
> @@ -1536,7 +1536,7 @@ static struct platform_driver sunlance_sbus_driver = {
> .of_match_table = sunlance_sbus_match,
> },
> .probe = sunlance_sbus_probe,
> - .remove = __devexit_p(sunlance_sbus_remove),
> + .remove = sunlance_sbus_remove,
> };
>
> module_platform_driver(sunlance_sbus_driver);
> diff --git a/drivers/net/ethernet/apple/macmace.c b/drivers/net/ethernet/apple/macmace.c
> index a92ddee7..c2e9ef6 100644
> --- a/drivers/net/ethernet/apple/macmace.c
> +++ b/drivers/net/ethernet/apple/macmace.c
> @@ -768,7 +768,7 @@ static int __devexit mac_mace_device_remove (struct platform_device *pdev)
>
> static struct platform_driver mac_mace_driver = {
> .probe = mace_probe,
> - .remove = __devexit_p(mac_mace_device_remove),
> + .remove = mac_mace_device_remove,
> .driver = {
> .name = mac_mace_string,
> .owner = THIS_MODULE,
> diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> index d19f82f..edb5d6e 100644
> --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> @@ -2697,7 +2697,7 @@ static struct pci_driver atl1c_driver = {
> .name = atl1c_driver_name,
> .id_table = atl1c_pci_tbl,
> .probe = atl1c_probe,
> - .remove = __devexit_p(atl1c_remove),
> + .remove = atl1c_remove,
> .shutdown = atl1c_shutdown,
> .err_handler = &atl1c_err_handler,
> .driver.pm = &atl1c_pm_ops,
> diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
> index e213da2..eacf624 100644
> --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
> +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
> @@ -2499,7 +2499,7 @@ static struct pci_driver atl1e_driver = {
> .name = atl1e_driver_name,
> .id_table = atl1e_pci_tbl,
> .probe = atl1e_probe,
> - .remove = __devexit_p(atl1e_remove),
> + .remove = atl1e_remove,
> /* Power Management Hooks */
> #ifdef CONFIG_PM
> .suspend = atl1e_suspend,
> diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
> index 7bae2ad..b396907 100644
> --- a/drivers/net/ethernet/atheros/atlx/atl1.c
> +++ b/drivers/net/ethernet/atheros/atlx/atl1.c
> @@ -3146,7 +3146,7 @@ static struct pci_driver atl1_driver = {
> .name = ATLX_DRIVER_NAME,
> .id_table = atl1_pci_tbl,
> .probe = atl1_probe,
> - .remove = __devexit_p(atl1_remove),
> + .remove = atl1_remove,
> .shutdown = atl1_shutdown,
> .driver.pm = ATL1_PM_OPS,
> };
> diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
> index 623dd86..0988200 100644
> --- a/drivers/net/ethernet/atheros/atlx/atl2.c
> +++ b/drivers/net/ethernet/atheros/atlx/atl2.c
> @@ -1705,7 +1705,7 @@ static struct pci_driver atl2_driver = {
> .name = atl2_driver_name,
> .id_table = atl2_pci_tbl,
> .probe = atl2_probe,
> - .remove = __devexit_p(atl2_remove),
> + .remove = atl2_remove,
> /* Power Management Hooks */
> .suspend = atl2_suspend,
> #ifdef CONFIG_PM
> diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
> index 9786c0e..94fa5d8 100644
> --- a/drivers/net/ethernet/broadcom/b44.c
> +++ b/drivers/net/ethernet/broadcom/b44.c
> @@ -2340,7 +2340,7 @@ static struct ssb_driver b44_ssb_driver = {
> .name = DRV_MODULE_NAME,
> .id_table = b44_ssb_tbl,
> .probe = b44_init_one,
> - .remove = __devexit_p(b44_remove_one),
> + .remove = b44_remove_one,
> .suspend = b44_suspend,
> .resume = b44_resume,
> };
> diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
> index c7ca7ec..f062656 100644
> --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
> +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
> @@ -1877,7 +1877,7 @@ static int __devexit bcm_enet_remove(struct platform_device *pdev)
>
> struct platform_driver bcm63xx_enet_driver = {
> .probe = bcm_enet_probe,
> - .remove = __devexit_p(bcm_enet_remove),
> + .remove = bcm_enet_remove,
> .driver = {
> .name = "bcm63xx_enet",
> .owner = THIS_MODULE,
> @@ -1924,7 +1924,7 @@ static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
> */
> struct platform_driver bcm63xx_enet_shared_driver = {
> .probe = bcm_enet_shared_probe,
> - .remove = __devexit_p(bcm_enet_shared_remove),
> + .remove = bcm_enet_shared_remove,
> .driver = {
> .name = "bcm63xx_enet_shared",
> .owner = THIS_MODULE,
> diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
> index d431070..7b55f78 100644
> --- a/drivers/net/ethernet/broadcom/bnx2.c
> +++ b/drivers/net/ethernet/broadcom/bnx2.c
> @@ -8752,7 +8752,7 @@ static struct pci_driver bnx2_pci_driver = {
> .name = DRV_MODULE_NAME,
> .id_table = bnx2_pci_tbl,
> .probe = bnx2_init_one,
> - .remove = __devexit_p(bnx2_remove_one),
> + .remove = bnx2_remove_one,
> .suspend = bnx2_suspend,
> .resume = bnx2_resume,
> .err_handler = &bnx2_err_handler,
> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> index 3519fed..d9e72fcb 100644
> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> @@ -12349,7 +12349,7 @@ static struct pci_driver bnx2x_pci_driver = {
> .name = DRV_MODULE_NAME,
> .id_table = bnx2x_pci_tbl,
> .probe = bnx2x_init_one,
> - .remove = __devexit_p(bnx2x_remove_one),
> + .remove = bnx2x_remove_one,
> .suspend = bnx2x_suspend,
> .resume = bnx2x_resume,
> .err_handler = &bnx2x_err_handler,
> diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
> index 038ce02..d752b10 100644
> --- a/drivers/net/ethernet/broadcom/tg3.c
> +++ b/drivers/net/ethernet/broadcom/tg3.c
> @@ -16567,7 +16567,7 @@ static struct pci_driver tg3_driver = {
> .name = DRV_MODULE_NAME,
> .id_table = tg3_pci_tbl,
> .probe = tg3_init_one,
> - .remove = __devexit_p(tg3_remove_one),
> + .remove = tg3_remove_one,
> .err_handler = &tg3_err_handler,
> .driver.pm = TG3_PM_OPS,
> };
> diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
> index ce1eac5..7735469 100644
> --- a/drivers/net/ethernet/brocade/bna/bnad.c
> +++ b/drivers/net/ethernet/brocade/bna/bnad.c
> @@ -3490,7 +3490,7 @@ static struct pci_driver bnad_pci_driver = {
> .name = BNAD_NAME,
> .id_table = bnad_pci_id_table,
> .probe = bnad_pci_probe,
> - .remove = __devexit_p(bnad_pci_remove),
> + .remove = bnad_pci_remove,
> };
>
> static int __init
> diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
> index e7a476c..fdf7985 100644
> --- a/drivers/net/ethernet/cadence/at91_ether.c
> +++ b/drivers/net/ethernet/cadence/at91_ether.c
> @@ -512,7 +512,7 @@ static int at91ether_resume(struct platform_device *pdev)
> #endif
>
> static struct platform_driver at91ether_driver = {
> - .remove = __devexit_p(at91ether_remove),
> + .remove = at91ether_remove,
> .suspend = at91ether_suspend,
> .resume = at91ether_resume,
> .driver = {
> diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
> index 1d17c92..7cfa7bb 100644
> --- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
> +++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
> @@ -1361,7 +1361,7 @@ static struct pci_driver driver = {
> .name = DRV_NAME,
> .id_table = t1_pci_tbl,
> .probe = init_one,
> - .remove = __devexit_p(remove_one),
> + .remove = remove_one,
> };
>
> static int __init t1_init_module(void)
> diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
> index 9c9f326..a450f8d 100644
> --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
> +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
> @@ -3425,7 +3425,7 @@ static struct pci_driver driver = {
> .name = DRV_NAME,
> .id_table = cxgb3_pci_tbl,
> .probe = init_one,
> - .remove = __devexit_p(remove_one),
> + .remove = remove_one,
> .err_handler = &t3_err_handler,
> };
>
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
> index 0df1284..f344190 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
> @@ -4680,7 +4680,7 @@ static struct pci_driver cxgb4_driver = {
> .name = KBUILD_MODNAME,
> .id_table = cxgb4_pci_tbl,
> .probe = init_one,
> - .remove = __devexit_p(remove_one),
> + .remove = remove_one,
> .err_handler = &cxgb4_eeh,
> };
>
> diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
> index 9dad561..1ccd28b 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
> +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
> @@ -2905,8 +2905,8 @@ static struct pci_driver cxgb4vf_driver = {
> .name = KBUILD_MODNAME,
> .id_table = cxgb4vf_pci_tbl,
> .probe = cxgb4vf_pci_probe,
> - .remove = __devexit_p(cxgb4vf_pci_remove),
> - .shutdown = __devexit_p(cxgb4vf_pci_shutdown),
> + .remove = cxgb4vf_pci_remove,
> + .shutdown = cxgb4vf_pci_shutdown,
> };
>
> /*
> diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
> index ad1468b..612438a 100644
> --- a/drivers/net/ethernet/cisco/enic/enic_main.c
> +++ b/drivers/net/ethernet/cisco/enic/enic_main.c
> @@ -2584,7 +2584,7 @@ static struct pci_driver enic_driver = {
> .name = DRV_NAME,
> .id_table = enic_id_table,
> .probe = enic_probe,
> - .remove = __devexit_p(enic_remove),
> + .remove = enic_remove,
> };
>
> static int __init enic_init_module(void)
> diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
> index 36499d5..87d7c35 100644
> --- a/drivers/net/ethernet/davicom/dm9000.c
> +++ b/drivers/net/ethernet/davicom/dm9000.c
> @@ -1683,7 +1683,7 @@ static struct platform_driver dm9000_driver = {
> .pm = &dm9000_drv_pm_ops,
> },
> .probe = dm9000_probe,
> - .remove = __devexit_p(dm9000_drv_remove),
> + .remove = dm9000_drv_remove,
> };
>
> static int __init
> diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c
> index 77335853..18fd028 100644
> --- a/drivers/net/ethernet/dec/tulip/de2104x.c
> +++ b/drivers/net/ethernet/dec/tulip/de2104x.c
> @@ -2184,7 +2184,7 @@ static struct pci_driver de_driver = {
> .name = DRV_NAME,
> .id_table = de_pci_tbl,
> .probe = de_init_one,
> - .remove = __devexit_p(de_remove_one),
> + .remove = de_remove_one,
> #ifdef CONFIG_PM
> .suspend = de_suspend,
> .resume = de_resume,
> diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c
> index f879e92..8a4264f 100644
> --- a/drivers/net/ethernet/dec/tulip/de4x5.c
> +++ b/drivers/net/ethernet/dec/tulip/de4x5.c
> @@ -2104,7 +2104,7 @@ static struct eisa_driver de4x5_eisa_driver = {
> .driver = {
> .name = "de4x5",
> .probe = de4x5_eisa_probe,
> - .remove = __devexit_p (de4x5_eisa_remove),
> + .remove = de4x5_eisa_remove,
> }
> };
> MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
> @@ -2344,7 +2344,7 @@ static struct pci_driver de4x5_pci_driver = {
> .name = "de4x5",
> .id_table = de4x5_pci_tbl,
> .probe = de4x5_pci_probe,
> - .remove = __devexit_p (de4x5_pci_remove),
> + .remove = de4x5_pci_remove,
> };
>
> #endif
> diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c
> index d23755e..a631448 100644
> --- a/drivers/net/ethernet/dec/tulip/dmfe.c
> +++ b/drivers/net/ethernet/dec/tulip/dmfe.c
> @@ -2187,7 +2187,7 @@ static struct pci_driver dmfe_driver = {
> .name = "dmfe",
> .id_table = dmfe_pci_tbl,
> .probe = dmfe_init_one,
> - .remove = __devexit_p(dmfe_remove_one),
> + .remove = dmfe_remove_one,
> .suspend = dmfe_suspend,
> .resume = dmfe_resume
> };
> diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
> index 885700a..2a3736e 100644
> --- a/drivers/net/ethernet/dec/tulip/tulip_core.c
> +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
> @@ -1974,7 +1974,7 @@ static struct pci_driver tulip_driver = {
> .name = DRV_NAME,
> .id_table = tulip_pci_tbl,
> .probe = tulip_init_one,
> - .remove = __devexit_p(tulip_remove_one),
> + .remove = tulip_remove_one,
> #ifdef CONFIG_PM
> .suspend = tulip_suspend,
> .resume = tulip_resume,
> diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c
> index 75d45f8..9c24c95 100644
> --- a/drivers/net/ethernet/dec/tulip/uli526x.c
> +++ b/drivers/net/ethernet/dec/tulip/uli526x.c
> @@ -1788,7 +1788,7 @@ static struct pci_driver uli526x_driver = {
> .name = "uli526x",
> .id_table = uli526x_pci_tbl,
> .probe = uli526x_init_one,
> - .remove = __devexit_p(uli526x_remove_one),
> + .remove = uli526x_remove_one,
> .suspend = uli526x_suspend,
> .resume = uli526x_resume,
> };
> diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c
> index 7c1ec4d..6c5db4f 100644
> --- a/drivers/net/ethernet/dec/tulip/winbond-840.c
> +++ b/drivers/net/ethernet/dec/tulip/winbond-840.c
> @@ -1647,7 +1647,7 @@ static struct pci_driver w840_driver = {
> .name = DRV_NAME,
> .id_table = w840_pci_tbl,
> .probe = w840_probe1,
> - .remove = __devexit_p(w840_remove1),
> + .remove = w840_remove1,
> #ifdef CONFIG_PM
> .suspend = w840_suspend,
> .resume = w840_resume,
> diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c
> index 138bf83..4310e97 100644
> --- a/drivers/net/ethernet/dec/tulip/xircom_cb.c
> +++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c
> @@ -148,7 +148,7 @@ static struct pci_driver xircom_ops = {
> .name = "xircom_cb",
> .id_table = xircom_pci_table,
> .probe = xircom_probe,
> - .remove = __devexit_p(xircom_remove),
> + .remove = xircom_remove,
> };
>
>
> diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
> index 2fb01bf..21db34c 100644
> --- a/drivers/net/ethernet/dlink/dl2k.c
> +++ b/drivers/net/ethernet/dlink/dl2k.c
> @@ -1755,7 +1755,7 @@ static struct pci_driver rio_driver = {
> .name = "dl2k",
> .id_table = rio_pci_tbl,
> .probe = rio_probe1,
> - .remove = __devexit_p(rio_remove1),
> + .remove = rio_remove1,
> };
>
> module_pci_driver(rio_driver);
> diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c
> index 3b83588..65187b9 100644
> --- a/drivers/net/ethernet/dlink/sundance.c
> +++ b/drivers/net/ethernet/dlink/sundance.c
> @@ -1910,7 +1910,7 @@ static struct pci_driver sundance_driver = {
> .name = DRV_NAME,
> .id_table = sundance_pci_tbl,
> .probe = sundance_probe1,
> - .remove = __devexit_p(sundance_remove1),
> + .remove = sundance_remove1,
> #ifdef CONFIG_PM
> .suspend = sundance_suspend,
> .resume = sundance_resume,
> diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
> index 290b26f..dfdf553 100644
> --- a/drivers/net/ethernet/dnet.c
> +++ b/drivers/net/ethernet/dnet.c
> @@ -971,7 +971,7 @@ static int __devexit dnet_remove(struct platform_device *pdev)
>
> static struct platform_driver dnet_driver = {
> .probe = dnet_probe,
> - .remove = __devexit_p(dnet_remove),
> + .remove = dnet_remove,
> .driver = {
> .name = "dnet",
> },
> diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
> index 94b7bfc..198d587 100644
> --- a/drivers/net/ethernet/ethoc.c
> +++ b/drivers/net/ethernet/ethoc.c
> @@ -1190,7 +1190,7 @@ MODULE_DEVICE_TABLE(of, ethoc_match);
>
> static struct platform_driver ethoc_driver = {
> .probe = ethoc_probe,
> - .remove = __devexit_p(ethoc_remove),
> + .remove = ethoc_remove,
> .suspend = ethoc_suspend,
> .resume = ethoc_resume,
> .driver = {
> diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c
> index 0e4a0ac..fce1d35 100644
> --- a/drivers/net/ethernet/fealnx.c
> +++ b/drivers/net/ethernet/fealnx.c
> @@ -1950,7 +1950,7 @@ static struct pci_driver fealnx_driver = {
> .name = "fealnx",
> .id_table = fealnx_pci_tbl,
> .probe = fealnx_init_one,
> - .remove = __devexit_p(fealnx_remove_one),
> + .remove = fealnx_remove_one,
> };
>
> static int __init fealnx_init(void)
> diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
> index 2665162..3729996 100644
> --- a/drivers/net/ethernet/freescale/fec.c
> +++ b/drivers/net/ethernet/freescale/fec.c
> @@ -1790,7 +1790,7 @@ static struct platform_driver fec_driver = {
> },
> .id_table = fec_devtype,
> .probe = fec_probe,
> - .remove = __devexit_p(fec_drv_remove),
> + .remove = fec_drv_remove,
> };
>
> module_platform_driver(fec_driver);
> diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c
> index 3f4391b..9aba3fb 100644
> --- a/drivers/net/ethernet/hp/hp100.c
> +++ b/drivers/net/ethernet/hp/hp100.c
> @@ -2878,7 +2878,7 @@ static struct eisa_driver hp100_eisa_driver = {
> .driver = {
> .name = "hp100",
> .probe = hp100_eisa_probe,
> - .remove = __devexit_p (hp100_eisa_remove),
> + .remove = hp100_eisa_remove,
> }
> };
> #endif
> @@ -2950,7 +2950,7 @@ static struct pci_driver hp100_pci_driver = {
> .name = "hp100",
> .id_table = hp100_pci_tbl,
> .probe = hp100_pci_probe,
> - .remove = __devexit_p(hp100_pci_remove),
> + .remove = hp100_pci_remove,
> };
> #endif
>
> diff --git a/drivers/net/ethernet/i825xx/ether1.c b/drivers/net/ethernet/i825xx/ether1.c
> index 067db3f..75a1b57 100644
> --- a/drivers/net/ethernet/i825xx/ether1.c
> +++ b/drivers/net/ethernet/i825xx/ether1.c
> @@ -1070,7 +1070,7 @@ static const struct ecard_id ether1_ids[] = {
>
> static struct ecard_driver ether1_driver = {
> .probe = ether1_probe,
> - .remove = __devexit_p(ether1_remove),
> + .remove = ether1_remove,
> .id_table = ether1_ids,
> .drv = {
> .name = "ether1",
> diff --git a/drivers/net/ethernet/i825xx/lasi_82596.c b/drivers/net/ethernet/i825xx/lasi_82596.c
> index 6eba352..a79cc24 100644
> --- a/drivers/net/ethernet/i825xx/lasi_82596.c
> +++ b/drivers/net/ethernet/i825xx/lasi_82596.c
> @@ -219,7 +219,7 @@ static struct parisc_driver lan_driver = {
> .name = "lasi_82596",
> .id_table = lan_tbl,
> .probe = lan_init_chip,
> - .remove = __devexit_p(lan_remove_chip),
> + .remove = lan_remove_chip,
> };
>
> static int __devinit lasi_82596_init(void)
> diff --git a/drivers/net/ethernet/i825xx/sni_82596.c b/drivers/net/ethernet/i825xx/sni_82596.c
> index 6b2a888..4442c6e 100644
> --- a/drivers/net/ethernet/i825xx/sni_82596.c
> +++ b/drivers/net/ethernet/i825xx/sni_82596.c
> @@ -163,7 +163,7 @@ static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
>
> static struct platform_driver sni_82596_driver = {
> .probe = sni_82596_probe,
> - .remove = __devexit_p(sni_82596_driver_remove),
> + .remove = sni_82596_driver_remove,
> .driver = {
> .name = sni_82596_string,
> .owner = THIS_MODULE,
> diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c
> index 1b563bb..549de0e 100644
> --- a/drivers/net/ethernet/icplus/ipg.c
> +++ b/drivers/net/ethernet/icplus/ipg.c
> @@ -2296,7 +2296,7 @@ static struct pci_driver ipg_pci_driver = {
> .name = IPG_DRIVER_NAME,
> .id_table = ipg_pci_tbl,
> .probe = ipg_probe,
> - .remove = __devexit_p(ipg_remove),
> + .remove = ipg_remove,
> };
>
> static int __init ipg_init_module(void)
> diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
> index 29ce9bd..f41eaed 100644
> --- a/drivers/net/ethernet/intel/e100.c
> +++ b/drivers/net/ethernet/intel/e100.c
> @@ -3167,7 +3167,7 @@ static struct pci_driver e100_driver = {
> .name = DRV_NAME,
> .id_table = e100_id_table,
> .probe = e100_probe,
> - .remove = __devexit_p(e100_remove),
> + .remove = e100_remove,
> #ifdef CONFIG_PM
> /* Power Management hooks */
> .suspend = e100_suspend,
> diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
> index 222bfaf..3ca5fd3 100644
> --- a/drivers/net/ethernet/intel/e1000/e1000_main.c
> +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
> @@ -202,7 +202,7 @@ static struct pci_driver e1000_driver = {
> .name = e1000_driver_name,
> .id_table = e1000_pci_tbl,
> .probe = e1000_probe,
> - .remove = __devexit_p(e1000_remove),
> + .remove = e1000_remove,
> #ifdef CONFIG_PM
> /* Power Management Hooks */
> .suspend = e1000_suspend,
> diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
> index dadb13b..2f5bfd3 100644
> --- a/drivers/net/ethernet/intel/e1000e/netdev.c
> +++ b/drivers/net/ethernet/intel/e1000e/netdev.c
> @@ -6589,7 +6589,7 @@ static struct pci_driver e1000_driver = {
> .name = e1000e_driver_name,
> .id_table = e1000_pci_tbl,
> .probe = e1000_probe,
> - .remove = __devexit_p(e1000_remove),
> + .remove = e1000_remove,
> #ifdef CONFIG_PM
> .driver = {
> .pm = &e1000_pm_ops,
> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
> index 7044aaa..fdb2282 100644
> --- a/drivers/net/ethernet/intel/igb/igb_main.c
> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> @@ -228,7 +228,7 @@ static struct pci_driver igb_driver = {
> .name = igb_driver_name,
> .id_table = igb_pci_tbl,
> .probe = igb_probe,
> - .remove = __devexit_p(igb_remove),
> + .remove = igb_remove,
> #ifdef CONFIG_PM
> .driver.pm = &igb_pm_ops,
> #endif
> diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
> index 4051ec4..935173a 100644
> --- a/drivers/net/ethernet/intel/igbvf/netdev.c
> +++ b/drivers/net/ethernet/intel/igbvf/netdev.c
> @@ -2864,7 +2864,7 @@ static struct pci_driver igbvf_driver = {
> .name = igbvf_driver_name,
> .id_table = igbvf_pci_tbl,
> .probe = igbvf_probe,
> - .remove = __devexit_p(igbvf_remove),
> + .remove = igbvf_remove,
> #ifdef CONFIG_PM
> /* Power Management Hooks */
> .suspend = igbvf_suspend,
> diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
> index d99a2d5..5b44d8a 100644
> --- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
> +++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
> @@ -125,7 +125,7 @@ static struct pci_driver ixgb_driver = {
> .name = ixgb_driver_name,
> .id_table = ixgb_pci_tbl,
> .probe = ixgb_probe,
> - .remove = __devexit_p(ixgb_remove),
> + .remove = ixgb_remove,
> .err_handler = &ixgb_err_handler
> };
>
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> index 38fc186..4258ffa 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> @@ -7818,7 +7818,7 @@ static struct pci_driver ixgbe_driver = {
> .name = ixgbe_driver_name,
> .id_table = ixgbe_pci_tbl,
> .probe = ixgbe_probe,
> - .remove = __devexit_p(ixgbe_remove),
> + .remove = ixgbe_remove,
> #ifdef CONFIG_PM
> .suspend = ixgbe_suspend,
> .resume = ixgbe_resume,
> diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
> index 9d88153..da8b116 100644
> --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
> +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
> @@ -3557,7 +3557,7 @@ static struct pci_driver ixgbevf_driver = {
> .name = ixgbevf_driver_name,
> .id_table = ixgbevf_pci_tbl,
> .probe = ixgbevf_probe,
> - .remove = __devexit_p(ixgbevf_remove),
> + .remove = ixgbevf_remove,
> #ifdef CONFIG_PM
> /* Power Management Hooks */
> .suspend = ixgbevf_suspend,
> diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
> index 76a91f6..939cddc 100644
> --- a/drivers/net/ethernet/jme.c
> +++ b/drivers/net/ethernet/jme.c
> @@ -3330,7 +3330,7 @@ static struct pci_driver jme_driver = {
> .name = DRV_NAME,
> .id_table = jme_pci_tbl,
> .probe = jme_init_one,
> - .remove = __devexit_p(jme_remove_one),
> + .remove = jme_remove_one,
> .shutdown = jme_shutdown,
> .driver.pm = JME_PM_OPS,
> };
> diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
> index 003c5bc..44d4d61 100644
> --- a/drivers/net/ethernet/lantiq_etop.c
> +++ b/drivers/net/ethernet/lantiq_etop.c
> @@ -789,7 +789,7 @@ ltq_etop_remove(struct platform_device *pdev)
> }
>
> static struct platform_driver ltq_mii_driver = {
> - .remove = __devexit_p(ltq_etop_remove),
> + .remove = ltq_etop_remove,
> .driver = {
> .name = "ltq_etop",
> .owner = THIS_MODULE,
> diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
> index d19a143..0912768 100644
> --- a/drivers/net/ethernet/marvell/skge.c
> +++ b/drivers/net/ethernet/marvell/skge.c
> @@ -4142,7 +4142,7 @@ static struct pci_driver skge_driver = {
> .name = DRV_NAME,
> .id_table = skge_id_table,
> .probe = skge_probe,
> - .remove = __devexit_p(skge_remove),
> + .remove = skge_remove,
> .shutdown = skge_shutdown,
> .driver.pm = SKGE_PM_OPS,
> };
> diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
> index 78946fe..3c6314f 100644
> --- a/drivers/net/ethernet/marvell/sky2.c
> +++ b/drivers/net/ethernet/marvell/sky2.c
> @@ -5207,7 +5207,7 @@ static struct pci_driver sky2_driver = {
> .name = DRV_NAME,
> .id_table = sky2_id_table,
> .probe = sky2_probe,
> - .remove = __devexit_p(sky2_remove),
> + .remove = sky2_remove,
> .shutdown = sky2_shutdown,
> .driver.pm = SKY2_PM_OPS,
> };
> diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
> index 2aa80af..877b74a 100644
> --- a/drivers/net/ethernet/mellanox/mlx4/main.c
> +++ b/drivers/net/ethernet/mellanox/mlx4/main.c
> @@ -2391,7 +2391,7 @@ static struct pci_driver mlx4_driver = {
> .name = DRV_NAME,
> .id_table = mlx4_pci_table,
> .probe = mlx4_init_one,
> - .remove = __devexit_p(mlx4_remove_one),
> + .remove = mlx4_remove_one,
> .err_handler = &mlx4_err_handler,
> };
>
> diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c
> index dccae1d..786cc0f 100644
> --- a/drivers/net/ethernet/micrel/ks8695net.c
> +++ b/drivers/net/ethernet/micrel/ks8695net.c
> @@ -1620,7 +1620,7 @@ static struct platform_driver ks8695_driver = {
> .owner = THIS_MODULE,
> },
> .probe = ks8695_probe,
> - .remove = __devexit_p(ks8695_drv_remove),
> + .remove = ks8695_drv_remove,
> .suspend = ks8695_drv_suspend,
> .resume = ks8695_drv_resume,
> };
> diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
> index 24fb049..f84dd2d 100644
> --- a/drivers/net/ethernet/micrel/ks8842.c
> +++ b/drivers/net/ethernet/micrel/ks8842.c
> @@ -1262,7 +1262,7 @@ static struct platform_driver ks8842_platform_driver = {
> .owner = THIS_MODULE,
> },
> .probe = ks8842_probe,
> - .remove = __devexit_p(ks8842_remove),
> + .remove = ks8842_remove,
> };
>
> module_platform_driver(ks8842_platform_driver);
> diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
> index 1540ebe..a1f7d7d 100644
> --- a/drivers/net/ethernet/micrel/ks8851.c
> +++ b/drivers/net/ethernet/micrel/ks8851.c
> @@ -1554,7 +1554,7 @@ static struct spi_driver ks8851_driver = {
> .owner = THIS_MODULE,
> },
> .probe = ks8851_probe,
> - .remove = __devexit_p(ks8851_remove),
> + .remove = ks8851_remove,
> .suspend = ks8851_suspend,
> .resume = ks8851_resume,
> };
> diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c
> index 38529ed..80fe0b3 100644
> --- a/drivers/net/ethernet/micrel/ks8851_mll.c
> +++ b/drivers/net/ethernet/micrel/ks8851_mll.c
> @@ -1663,7 +1663,7 @@ static struct platform_driver ks8851_platform_driver = {
> .owner = THIS_MODULE,
> },
> .probe = ks8851_probe,
> - .remove = __devexit_p(ks8851_remove),
> + .remove = ks8851_remove,
> };
>
> module_platform_driver(ks8851_platform_driver);
> diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
> index 6118bda..1373b02 100644
> --- a/drivers/net/ethernet/microchip/enc28j60.c
> +++ b/drivers/net/ethernet/microchip/enc28j60.c
> @@ -1637,7 +1637,7 @@ static struct spi_driver enc28j60_driver = {
> .owner = THIS_MODULE,
> },
> .probe = enc28j60_probe,
> - .remove = __devexit_p(enc28j60_remove),
> + .remove = enc28j60_remove,
> };
>
> static int __init enc28j60_init(void)
> diff --git a/drivers/net/ethernet/natsemi/jazzsonic.c b/drivers/net/ethernet/natsemi/jazzsonic.c
> index 95dd39f..1b2ed23 100644
> --- a/drivers/net/ethernet/natsemi/jazzsonic.c
> +++ b/drivers/net/ethernet/natsemi/jazzsonic.c
> @@ -286,7 +286,7 @@ static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
>
> static struct platform_driver jazz_sonic_driver = {
> .probe = jazz_sonic_probe,
> - .remove = __devexit_p(jazz_sonic_device_remove),
> + .remove = jazz_sonic_device_remove,
> .driver = {
> .name = jazz_sonic_string,
> .owner = THIS_MODULE,
> diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
> index b9680ba..1d6a789 100644
> --- a/drivers/net/ethernet/natsemi/macsonic.c
> +++ b/drivers/net/ethernet/natsemi/macsonic.c
> @@ -634,7 +634,7 @@ static int __devexit mac_sonic_device_remove (struct platform_device *pdev)
>
> static struct platform_driver mac_sonic_driver = {
> .probe = mac_sonic_probe,
> - .remove = __devexit_p(mac_sonic_device_remove),
> + .remove = mac_sonic_device_remove,
> .driver = {
> .name = mac_sonic_string,
> .owner = THIS_MODULE,
> diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
> index dbaaa99..119930b 100644
> --- a/drivers/net/ethernet/natsemi/natsemi.c
> +++ b/drivers/net/ethernet/natsemi/natsemi.c
> @@ -3353,7 +3353,7 @@ static struct pci_driver natsemi_driver = {
> .name = DRV_NAME,
> .id_table = natsemi_pci_tbl,
> .probe = natsemi_probe1,
> - .remove = __devexit_p(natsemi_remove1),
> + .remove = natsemi_remove1,
> #ifdef CONFIG_PM
> .suspend = natsemi_suspend,
> .resume = natsemi_resume,
> diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
> index d52728b..70ec426 100644
> --- a/drivers/net/ethernet/natsemi/ns83820.c
> +++ b/drivers/net/ethernet/natsemi/ns83820.c
> @@ -2272,7 +2272,7 @@ static struct pci_driver driver = {
> .name = "ns83820",
> .id_table = ns83820_pci_tbl,
> .probe = ns83820_init_one,
> - .remove = __devexit_p(ns83820_remove_one),
> + .remove = ns83820_remove_one,
> #if 0 /* FIXME: implement */
> .suspend = ,
> .resume = ,
> diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c
> index 7dfe883..9bc1fc7 100644
> --- a/drivers/net/ethernet/natsemi/xtsonic.c
> +++ b/drivers/net/ethernet/natsemi/xtsonic.c
> @@ -314,7 +314,7 @@ static int __devexit xtsonic_device_remove (struct platform_device *pdev)
>
> static struct platform_driver xtsonic_driver = {
> .probe = xtsonic_probe,
> - .remove = __devexit_p(xtsonic_device_remove),
> + .remove = xtsonic_device_remove,
> .driver = {
> .name = xtsonic_string,
> },
> diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
> index c98decb..0c8742a 100644
> --- a/drivers/net/ethernet/neterion/s2io.c
> +++ b/drivers/net/ethernet/neterion/s2io.c
> @@ -494,7 +494,7 @@ static struct pci_driver s2io_driver = {
> .name = "S2IO",
> .id_table = s2io_tbl,
> .probe = s2io_init_nic,
> - .remove = __devexit_p(s2io_rem_nic),
> + .remove = s2io_rem_nic,
> .err_handler = &s2io_err_handler,
> };
>
> diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
> index 3e5b750..4af32a3 100644
> --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
> +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
> @@ -4809,7 +4809,7 @@ static struct pci_driver vxge_driver = {
> .name = VXGE_DRIVER_NAME,
> .id_table = vxge_id_table,
> .probe = vxge_probe,
> - .remove = __devexit_p(vxge_remove),
> + .remove = vxge_remove,
> #ifdef CONFIG_PM
> .suspend = vxge_pm_suspend,
> .resume = vxge_pm_resume,
> diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
> index 6893a65..fceec55 100644
> --- a/drivers/net/ethernet/nuvoton/w90p910_ether.c
> +++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c
> @@ -1096,7 +1096,7 @@ static int __devexit w90p910_ether_remove(struct platform_device *pdev)
>
> static struct platform_driver w90p910_ether_driver = {
> .probe = w90p910_ether_probe,
> - .remove = __devexit_p(w90p910_ether_remove),
> + .remove = w90p910_ether_remove,
> .driver = {
> .name = "nuc900-emc",
> .owner = THIS_MODULE,
> diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
> index 876bece..7f89407 100644
> --- a/drivers/net/ethernet/nvidia/forcedeth.c
> +++ b/drivers/net/ethernet/nvidia/forcedeth.c
> @@ -6271,7 +6271,7 @@ static struct pci_driver driver = {
> .name = DRV_NAME,
> .id_table = pci_tbl,
> .probe = nv_probe,
> - .remove = __devexit_p(nv_remove),
> + .remove = nv_remove,
> .shutdown = nv_shutdown,
> .driver.pm = NV_PM_OPS,
> };
> diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
> index af8b414..4638f6a 100644
> --- a/drivers/net/ethernet/nxp/lpc_eth.c
> +++ b/drivers/net/ethernet/nxp/lpc_eth.c
> @@ -1597,7 +1597,7 @@ MODULE_DEVICE_TABLE(of, lpc_eth_match);
>
> static struct platform_driver lpc_eth_driver = {
> .probe = lpc_eth_drv_probe,
> - .remove = __devexit_p(lpc_eth_drv_remove),
> + .remove = lpc_eth_drv_remove,
> #ifdef CONFIG_PM
> .suspend = lpc_eth_drv_suspend,
> .resume = lpc_eth_drv_resume,
> diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
> index f97719c..5fca4a2 100644
> --- a/drivers/net/ethernet/octeon/octeon_mgmt.c
> +++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
> @@ -1583,7 +1583,7 @@ static struct platform_driver octeon_mgmt_driver = {
> .of_match_table = octeon_mgmt_match,
> },
> .probe = octeon_mgmt_probe,
> - .remove = __devexit_p(octeon_mgmt_remove),
> + .remove = octeon_mgmt_remove,
> };
>
> extern void octeon_mdiobus_force_mod_depencency(void);
> diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c
> index c236715..9664732 100644
> --- a/drivers/net/ethernet/packetengines/hamachi.c
> +++ b/drivers/net/ethernet/packetengines/hamachi.c
> @@ -1923,7 +1923,7 @@ static struct pci_driver hamachi_driver = {
> .name = DRV_NAME,
> .id_table = hamachi_pci_tbl,
> .probe = hamachi_init_one,
> - .remove = __devexit_p(hamachi_remove_one),
> + .remove = hamachi_remove_one,
> };
>
> static int __init hamachi_init (void)
> diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c
> index 04e622f..aec57c0 100644
> --- a/drivers/net/ethernet/packetengines/yellowfin.c
> +++ b/drivers/net/ethernet/packetengines/yellowfin.c
> @@ -1399,7 +1399,7 @@ static struct pci_driver yellowfin_driver = {
> .name = DRV_NAME,
> .id_table = yellowfin_pci_tbl,
> .probe = yellowfin_init_one,
> - .remove = __devexit_p(yellowfin_remove_one),
> + .remove = yellowfin_remove_one,
> };
>
>
> diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
> index 6fa74d5..07943a3 100644
> --- a/drivers/net/ethernet/pasemi/pasemi_mac.c
> +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
> @@ -1884,7 +1884,7 @@ static struct pci_driver pasemi_mac_driver = {
> .name = "pasemi_mac",
> .id_table = pasemi_mac_pci_tbl,
> .probe = pasemi_mac_probe,
> - .remove = __devexit_p(pasemi_mac_remove),
> + .remove = pasemi_mac_remove,
> };
>
> static void __exit pasemi_mac_cleanup_module(void)
> diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
> index df45061..f0546b0 100644
> --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
> +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
> @@ -3350,7 +3350,7 @@ static struct pci_driver netxen_driver = {
> .name = netxen_nic_driver_name,
> .id_table = netxen_pci_tbl,
> .probe = netxen_nic_probe,
> - .remove = __devexit_p(netxen_nic_remove),
> + .remove = netxen_nic_remove,
> #ifdef CONFIG_PM
> .suspend = netxen_nic_suspend,
> .resume = netxen_nic_resume,
> diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
> index 12d1f24..506c72f 100644
> --- a/drivers/net/ethernet/qlogic/qla3xxx.c
> +++ b/drivers/net/ethernet/qlogic/qla3xxx.c
> @@ -3952,7 +3952,7 @@ static struct pci_driver ql3xxx_driver = {
> .name = DRV_NAME,
> .id_table = ql3xxx_pci_tbl,
> .probe = ql3xxx_probe,
> - .remove = __devexit_p(ql3xxx_remove),
> + .remove = ql3xxx_remove,
> };
>
> module_pci_driver(ql3xxx_driver);
> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
> index 24ad17e..e553684 100644
> --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
> +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
> @@ -4533,7 +4533,7 @@ static struct pci_driver qlcnic_driver = {
> .name = qlcnic_driver_name,
> .id_table = qlcnic_pci_tbl,
> .probe = qlcnic_probe,
> - .remove = __devexit_p(qlcnic_remove),
> + .remove = qlcnic_remove,
> #ifdef CONFIG_PM
> .suspend = qlcnic_suspend,
> .resume = qlcnic_resume,
> diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
> index b262d61..a576a8d2 100644
> --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
> +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
> @@ -4921,7 +4921,7 @@ static struct pci_driver qlge_driver = {
> .name = DRV_NAME,
> .id_table = qlge_pci_tbl,
> .probe = qlge_probe,
> - .remove = __devexit_p(qlge_remove),
> + .remove = qlge_remove,
> #ifdef CONFIG_PM
> .suspend = qlge_suspend,
> .resume = qlge_resume,
> diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c
> index 557a265..4e91e18 100644
> --- a/drivers/net/ethernet/rdc/r6040.c
> +++ b/drivers/net/ethernet/rdc/r6040.c
> @@ -1274,7 +1274,7 @@ static struct pci_driver r6040_driver = {
> .name = DRV_NAME,
> .id_table = r6040_pci_tbl,
> .probe = r6040_init_one,
> - .remove = __devexit_p(r6040_remove_one),
> + .remove = r6040_remove_one,
> };
>
> module_pci_driver(r6040_driver);
> diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
> index 3ed7add..59d8d70 100644
> --- a/drivers/net/ethernet/realtek/8139too.c
> +++ b/drivers/net/ethernet/realtek/8139too.c
> @@ -2652,7 +2652,7 @@ static struct pci_driver rtl8139_pci_driver = {
> .name = DRV_NAME,
> .id_table = rtl8139_pci_tbl,
> .probe = rtl8139_init_one,
> - .remove = __devexit_p(rtl8139_remove_one),
> + .remove = rtl8139_remove_one,
> #ifdef CONFIG_PM
> .suspend = rtl8139_suspend,
> .resume = rtl8139_resume,
> diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
> index 248f883..1a01b9f 100644
> --- a/drivers/net/ethernet/realtek/r8169.c
> +++ b/drivers/net/ethernet/realtek/r8169.c
> @@ -7028,7 +7028,7 @@ static struct pci_driver rtl8169_pci_driver = {
> .name = MODULENAME,
> .id_table = rtl8169_pci_tbl,
> .probe = rtl_init_one,
> - .remove = __devexit_p(rtl_remove_one),
> + .remove = rtl_remove_one,
> .shutdown = rtl_shutdown,
> .driver.pm = RTL8169_PM_OPS,
> };
> diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c
> index 2ed3ab4..988e27d 100644
> --- a/drivers/net/ethernet/s6gmac.c
> +++ b/drivers/net/ethernet/s6gmac.c
> @@ -1046,7 +1046,7 @@ static int __devexit s6gmac_remove(struct platform_device *pdev)
>
> static struct platform_driver s6gmac_driver = {
> .probe = s6gmac_probe,
> - .remove = __devexit_p(s6gmac_remove),
> + .remove = s6gmac_remove,
> .driver = {
> .name = "s6gmac",
> .owner = THIS_MODULE,
> diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c
> index 6a40dd0..0baae6a 100644
> --- a/drivers/net/ethernet/seeq/ether3.c
> +++ b/drivers/net/ethernet/seeq/ether3.c
> @@ -894,7 +894,7 @@ static const struct ecard_id ether3_ids[] = {
>
> static struct ecard_driver ether3_driver = {
> .probe = ether3_probe,
> - .remove = __devexit_p(ether3_remove),
> + .remove = ether3_remove,
> .id_table = ether3_ids,
> .drv = {
> .name = "ether3",
> diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c
> index 3e5519a..8d6546d 100644
> --- a/drivers/net/ethernet/sgi/ioc3-eth.c
> +++ b/drivers/net/ethernet/sgi/ioc3-eth.c
> @@ -1396,7 +1396,7 @@ static struct pci_driver ioc3_driver = {
> .name = "ioc3-eth",
> .id_table = ioc3_pci_tbl,
> .probe = ioc3_probe,
> - .remove = __devexit_p(ioc3_remove_one),
> + .remove = ioc3_remove_one,
> };
>
> static int __init ioc3_init_module(void)
> diff --git a/drivers/net/ethernet/silan/sc92031.c b/drivers/net/ethernet/silan/sc92031.c
> index 32e5566..a0a2e76 100644
> --- a/drivers/net/ethernet/silan/sc92031.c
> +++ b/drivers/net/ethernet/silan/sc92031.c
> @@ -1574,7 +1574,7 @@ static struct pci_driver sc92031_pci_driver = {
> .name = SC92031_NAME,
> .id_table = sc92031_pci_device_id_table,
> .probe = sc92031_probe,
> - .remove = __devexit_p(sc92031_remove),
> + .remove = sc92031_remove,
> .suspend = sc92031_suspend,
> .resume = sc92031_resume,
> };
> diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c
> index d816601..67fbd4a 100644
> --- a/drivers/net/ethernet/sis/sis190.c
> +++ b/drivers/net/ethernet/sis/sis190.c
> @@ -1932,7 +1932,7 @@ static struct pci_driver sis190_pci_driver = {
> .name = DRV_NAME,
> .id_table = sis190_pci_tbl,
> .probe = sis190_init_one,
> - .remove = __devexit_p(sis190_remove_one),
> + .remove = sis190_remove_one,
> };
>
> static int __init sis190_init_module(void)
> diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c
> index fb9f6b3..d068e2b 100644
> --- a/drivers/net/ethernet/sis/sis900.c
> +++ b/drivers/net/ethernet/sis/sis900.c
> @@ -2496,7 +2496,7 @@ static struct pci_driver sis900_pci_driver = {
> .name = SIS900_MODULE_NAME,
> .id_table = sis900_pci_tbl,
> .probe = sis900_probe,
> - .remove = __devexit_p(sis900_remove),
> + .remove = sis900_remove,
> #ifdef CONFIG_PM
> .suspend = sis900_suspend,
> .resume = sis900_resume,
> diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c
> index d01e59c..67e694b 100644
> --- a/drivers/net/ethernet/smsc/epic100.c
> +++ b/drivers/net/ethernet/smsc/epic100.c
> @@ -1577,7 +1577,7 @@ static struct pci_driver epic_driver = {
> .name = DRV_NAME,
> .id_table = epic_pci_tbl,
> .probe = epic_init_one,
> - .remove = __devexit_p(epic_remove_one),
> + .remove = epic_remove_one,
> #ifdef CONFIG_PM
> .suspend = epic_suspend,
> .resume = epic_resume,
> diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
> index 8d15f7a..f19fba7 100644
> --- a/drivers/net/ethernet/smsc/smc911x.c
> +++ b/drivers/net/ethernet/smsc/smc911x.c
> @@ -2186,7 +2186,7 @@ static int smc911x_drv_resume(struct platform_device *dev)
>
> static struct platform_driver smc911x_driver = {
> .probe = smc911x_drv_probe,
> - .remove = __devexit_p(smc911x_drv_remove),
> + .remove = smc911x_drv_remove,
> .suspend = smc911x_drv_suspend,
> .resume = smc911x_drv_resume,
> .driver = {
> diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
> index 318adc9..8d85cbd 100644
> --- a/drivers/net/ethernet/smsc/smc91x.c
> +++ b/drivers/net/ethernet/smsc/smc91x.c
> @@ -2407,7 +2407,7 @@ static struct dev_pm_ops smc_drv_pm_ops = {
>
> static struct platform_driver smc_driver = {
> .probe = smc_drv_probe,
> - .remove = __devexit_p(smc_drv_remove),
> + .remove = smc_drv_remove,
> .driver = {
> .name = CARDNAME,
> .owner = THIS_MODULE,
> diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
> index 62d1baf..7d034fc 100644
> --- a/drivers/net/ethernet/smsc/smsc911x.c
> +++ b/drivers/net/ethernet/smsc/smsc911x.c
> @@ -2576,7 +2576,7 @@ MODULE_DEVICE_TABLE(of, smsc911x_dt_ids);
>
> static struct platform_driver smsc911x_driver = {
> .probe = smsc911x_drv_probe,
> - .remove = __devexit_p(smsc911x_drv_remove),
> + .remove = smsc911x_drv_remove,
> .driver = {
> .name = SMSC_CHIPNAME,
> .owner = THIS_MODULE,
> diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c
> index 1fcd914e..ed96967 100644
> --- a/drivers/net/ethernet/smsc/smsc9420.c
> +++ b/drivers/net/ethernet/smsc/smsc9420.c
> @@ -1736,7 +1736,7 @@ static struct pci_driver smsc9420_driver = {
> .name = DRV_NAME,
> .id_table = smsc9420_id_table,
> .probe = smsc9420_probe,
> - .remove = __devexit_p(smsc9420_remove),
> + .remove = smsc9420_remove,
> #ifdef CONFIG_PM
> .suspend = smsc9420_suspend,
> .resume = smsc9420_resume,
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
> index 1f069b0..743ab67 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
> @@ -182,7 +182,7 @@ struct pci_driver stmmac_pci_driver = {
> .name = STMMAC_RESOURCE_NAME,
> .id_table = stmmac_id_table,
> .probe = stmmac_pci_probe,
> - .remove = __devexit_p(stmmac_pci_remove),
> + .remove = stmmac_pci_remove,
> #ifdef CONFIG_PM
> .suspend = stmmac_pci_suspend,
> .resume = stmmac_pci_resume,
> diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
> index c8251be..9d716c6 100644
> --- a/drivers/net/ethernet/sun/cassini.c
> +++ b/drivers/net/ethernet/sun/cassini.c
> @@ -5273,7 +5273,7 @@ static struct pci_driver cas_driver = {
> .name = DRV_MODULE_NAME,
> .id_table = cas_pci_tbl,
> .probe = cas_init_one,
> - .remove = __devexit_p(cas_remove_one),
> + .remove = cas_remove_one,
> #ifdef CONFIG_PM
> .suspend = cas_suspend,
> .resume = cas_resume
> diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
> index 275b430..94b0085 100644
> --- a/drivers/net/ethernet/sun/niu.c
> +++ b/drivers/net/ethernet/sun/niu.c
> @@ -9980,7 +9980,7 @@ static struct pci_driver niu_pci_driver = {
> .name = DRV_MODULE_NAME,
> .id_table = niu_pci_tbl,
> .probe = niu_pci_init_one,
> - .remove = __devexit_p(niu_pci_remove_one),
> + .remove = niu_pci_remove_one,
> .suspend = niu_suspend,
> .resume = niu_resume,
> };
> @@ -10211,7 +10211,7 @@ static struct platform_driver niu_of_driver = {
> .of_match_table = niu_match,
> },
> .probe = niu_of_probe,
> - .remove = __devexit_p(niu_of_remove),
> + .remove = niu_of_remove,
> };
>
> #endif /* CONFIG_SPARC64 */
> diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c
> index c9c977b..41609b8 100644
> --- a/drivers/net/ethernet/sun/sunbmac.c
> +++ b/drivers/net/ethernet/sun/sunbmac.c
> @@ -1286,7 +1286,7 @@ static struct platform_driver bigmac_sbus_driver = {
> .of_match_table = bigmac_sbus_match,
> },
> .probe = bigmac_sbus_probe,
> - .remove = __devexit_p(bigmac_sbus_remove),
> + .remove = bigmac_sbus_remove,
> };
>
> module_platform_driver(bigmac_sbus_driver);
> diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
> index 73f341b..61147c2 100644
> --- a/drivers/net/ethernet/sun/sunhme.c
> +++ b/drivers/net/ethernet/sun/sunhme.c
> @@ -3190,7 +3190,7 @@ static struct pci_driver hme_pci_driver = {
> .name = "hme",
> .id_table = happymeal_pci_ids,
> .probe = happy_meal_pci_probe,
> - .remove = __devexit_p(happy_meal_pci_remove),
> + .remove = happy_meal_pci_remove,
> };
>
> static int __init happy_meal_pci_init(void)
> @@ -3284,7 +3284,7 @@ static struct platform_driver hme_sbus_driver = {
> .of_match_table = hme_sbus_match,
> },
> .probe = hme_sbus_probe,
> - .remove = __devexit_p(hme_sbus_remove),
> + .remove = hme_sbus_remove,
> };
>
> static int __init happy_meal_sbus_init(void)
> diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c
> index aeded7f..10b0f50 100644
> --- a/drivers/net/ethernet/sun/sunqe.c
> +++ b/drivers/net/ethernet/sun/sunqe.c
> @@ -971,7 +971,7 @@ static struct platform_driver qec_sbus_driver = {
> .of_match_table = qec_sbus_match,
> },
> .probe = qec_sbus_probe,
> - .remove = __devexit_p(qec_sbus_remove),
> + .remove = qec_sbus_remove,
> };
>
> static int __init qec_init(void)
> diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
> index 6ce9edd..5f6d1f0 100644
> --- a/drivers/net/ethernet/tehuti/tehuti.c
> +++ b/drivers/net/ethernet/tehuti/tehuti.c
> @@ -2458,7 +2458,7 @@ static struct pci_driver bdx_pci_driver = {
> .name = BDX_DRV_NAME,
> .id_table = bdx_pci_tbl,
> .probe = bdx_probe,
> - .remove = __devexit_p(bdx_remove),
> + .remove = bdx_remove,
> };
>
> /*
> diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
> index 860c252..723cba0 100644
> --- a/drivers/net/ethernet/ti/cpmac.c
> +++ b/drivers/net/ethernet/ti/cpmac.c
> @@ -1216,7 +1216,7 @@ static struct platform_driver cpmac_driver = {
> .driver.name = "cpmac",
> .driver.owner = THIS_MODULE,
> .probe = cpmac_probe,
> - .remove = __devexit_p(cpmac_remove),
> + .remove = cpmac_remove,
> };
>
> int __devinit cpmac_init(void)
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index 7654a62..64ea9a9 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
> @@ -1492,7 +1492,7 @@ static struct platform_driver cpsw_driver = {
> .of_match_table = of_match_ptr(cpsw_of_mtable),
> },
> .probe = cpsw_probe,
> - .remove = __devexit_p(cpsw_remove),
> + .remove = cpsw_remove,
> };
>
> static int __init cpsw_init(void)
> diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
> index fce89a0a..e6cbedc 100644
> --- a/drivers/net/ethernet/ti/davinci_emac.c
> +++ b/drivers/net/ethernet/ti/davinci_emac.c
> @@ -2107,7 +2107,7 @@ static struct platform_driver davinci_emac_driver = {
> .of_match_table = of_match_ptr(davinci_emac_of_match),
> },
> .probe = davinci_emac_probe,
> - .remove = __devexit_p(davinci_emac_remove),
> + .remove = davinci_emac_remove,
> };
>
> /**
> diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
> index 51a96db..ca69af8 100644
> --- a/drivers/net/ethernet/ti/davinci_mdio.c
> +++ b/drivers/net/ethernet/ti/davinci_mdio.c
> @@ -496,7 +496,7 @@ static struct platform_driver davinci_mdio_driver = {
> .of_match_table = of_match_ptr(davinci_mdio_of_mtable),
> },
> .probe = davinci_mdio_probe,
> - .remove = __devexit_p(davinci_mdio_remove),
> + .remove = davinci_mdio_remove,
> };
>
> static int __init davinci_mdio_init(void)
> diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c
> index 3e6abf0f..9e326b2 100644
> --- a/drivers/net/ethernet/ti/tlan.c
> +++ b/drivers/net/ethernet/ti/tlan.c
> @@ -392,7 +392,7 @@ static struct pci_driver tlan_driver = {
> .name = "tlan",
> .id_table = tlan_pci_tbl,
> .probe = tlan_init_one,
> - .remove = __devexit_p(tlan_remove_one),
> + .remove = tlan_remove_one,
> .suspend = tlan_suspend,
> .resume = tlan_resume,
> };
> diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
> index c1ebfe9..a89279f 100644
> --- a/drivers/net/ethernet/toshiba/spider_net.c
> +++ b/drivers/net/ethernet/toshiba/spider_net.c
> @@ -2559,7 +2559,7 @@ static struct pci_driver spider_net_driver = {
> .name = spider_net_driver_name,
> .id_table = spider_net_pci_tbl,
> .probe = spider_net_probe,
> - .remove = __devexit_p(spider_net_remove)
> + .remove = spider_net_remove
> };
>
> /**
> diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c
> index 651a70c..6d6af5d 100644
> --- a/drivers/net/ethernet/toshiba/tc35815.c
> +++ b/drivers/net/ethernet/toshiba/tc35815.c
> @@ -2198,7 +2198,7 @@ static struct pci_driver tc35815_pci_driver = {
> .name = MODNAME,
> .id_table = tc35815_pci_tbl,
> .probe = tc35815_init_one,
> - .remove = __devexit_p(tc35815_remove_one),
> + .remove = tc35815_remove_one,
> #ifdef CONFIG_PM
> .suspend = tc35815_suspend,
> .resume = tc35815_resume,
> diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
> index 0459c09..565f077 100644
> --- a/drivers/net/ethernet/via/via-rhine.c
> +++ b/drivers/net/ethernet/via/via-rhine.c
> @@ -2359,7 +2359,7 @@ static struct pci_driver rhine_driver = {
> .name = DRV_NAME,
> .id_table = rhine_pci_tbl,
> .probe = rhine_init_one,
> - .remove = __devexit_p(rhine_remove_one),
> + .remove = rhine_remove_one,
> .shutdown = rhine_shutdown,
> .driver.pm = RHINE_PM_OPS,
> };
> diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
> index a46c198..44e2fa4 100644
> --- a/drivers/net/ethernet/via/via-velocity.c
> +++ b/drivers/net/ethernet/via/via-velocity.c
> @@ -3108,7 +3108,7 @@ static struct pci_driver velocity_driver = {
> .name = VELOCITY_NAME,
> .id_table = velocity_id_table,
> .probe = velocity_found1,
> - .remove = __devexit_p(velocity_remove1),
> + .remove = velocity_remove1,
> #ifdef CONFIG_PM
> .suspend = velocity_suspend,
> .resume = velocity_resume,
> diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
> index 2c08bf6..82187f3 100644
> --- a/drivers/net/ethernet/wiznet/w5100.c
> +++ b/drivers/net/ethernet/wiznet/w5100.c
> @@ -801,7 +801,7 @@ static struct platform_driver w5100_driver = {
> .pm = &w5100_pm_ops,
> },
> .probe = w5100_probe,
> - .remove = __devexit_p(w5100_remove),
> + .remove = w5100_remove,
> };
>
> module_platform_driver(w5100_driver);
> diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
> index 88943d9..48c182e 100644
> --- a/drivers/net/ethernet/wiznet/w5300.c
> +++ b/drivers/net/ethernet/wiznet/w5300.c
> @@ -713,7 +713,7 @@ static struct platform_driver w5300_driver = {
> .pm = &w5300_pm_ops,
> },
> .probe = w5300_probe,
> - .remove = __devexit_p(w5300_remove),
> + .remove = w5300_remove,
> };
>
> module_platform_driver(w5300_driver);
> diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
> index f8e3518..6ac9e4c 100644
> --- a/drivers/net/ethernet/xilinx/ll_temac_main.c
> +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
> @@ -1174,7 +1174,7 @@ MODULE_DEVICE_TABLE(of, temac_of_match);
>
> static struct platform_driver temac_of_driver = {
> .probe = temac_of_probe,
> - .remove = __devexit_p(temac_of_remove),
> + .remove = temac_of_remove,
> .driver = {
> .owner = THIS_MODULE,
> .name = "xilinx_temac",
> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> index 1d04754..6020244 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> @@ -1654,7 +1654,7 @@ static int __devexit axienet_of_remove(struct platform_device *op)
>
> static struct platform_driver axienet_of_driver = {
> .probe = axienet_of_probe,
> - .remove = __devexit_p(axienet_of_remove),
> + .remove = axienet_of_remove,
> .driver = {
> .owner = THIS_MODULE,
> .name = "xilinx_axienet",
> diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
> index 77cfe51..c4d7a80 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
> +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
> @@ -1298,7 +1298,7 @@ static struct platform_driver xemaclite_of_driver = {
> .of_match_table = xemaclite_of_match,
> },
> .probe = xemaclite_of_probe,
> - .remove = __devexit_p(xemaclite_of_remove),
> + .remove = xemaclite_of_remove,
> };
>
> module_platform_driver(xemaclite_of_driver);
>
--
Nicolas Ferre
^ permalink raw reply
* Re: compound skb frag pages appearing in start_xmit
From: Ian Campbell @ 2012-11-20 9:21 UTC (permalink / raw)
To: Stefan Bader
Cc: Eric Dumazet, Konrad Rzeszutek Wilk, netdev@vger.kernel.org,
Marcos E. Matsunaga, xen-devel, Sander Eikelenboom, ANNIE LI,
Eric Dumazet
In-Reply-To: <50AB3F9D.4070905@canonical.com>
On Tue, 2012-11-20 at 08:30 +0000, Stefan Bader wrote:
> >> When I tried to rebase my persistent grant netfront/netback patch on
> >> latest kernel, netperf/netserver test never succeeded. I did some test
> >> to find out that v3.6-rc7 works fine, but v3.7-rc1, v3.7-rc2 and
> >> v3.7-rc4 does not succeed in netperf/netserver test. So I keep my
> >> persistent grant patch only based on v3.4-rc3 now.
> >
> >> Konrad thought about commit 6a8ed462f16b8455eec5ae00eb6014159a6721f0 in
> >> v3.7-rc1, and suggested me to test your debug patch in netfront. This
> >> BUG_ON happens soon after running the netperf/netserver test case.
> >
> >> Thanks
> >> Annie
> >
> > Is there any progression with this bug (rc6 is out the door, so the
> release of 3.7-final seems to be eminent and this bug completely
> cripples any networking with guests) ?
> >
>
> +1 on that. I was testing yesterday with a PVM domU running 3.7-rc5 on Xen 4.2
> (but also reported from EC2 running Xen 3.4.3) c with one VCPU. I actually can
> trigger it by just ssh'ing into the domU (from another machine) and then run
> "find /". Output starts to stutter and then stops completely. When this happens
> a new connection still can be made and as long as only shorter output is
> generated the ssh connection is ok. From a dump taken it looks like user-space
> is waiting in some select call (without any warnon I rather won't see the tx path).
Annie, are you still looking into this or shall I?
Ian.
^ permalink raw reply
* RE: 82571EB: Detected Hardware Unit Hang
From: Dave, Tushar N @ 2012-11-20 8:59 UTC (permalink / raw)
To: Joe Jin
Cc: e1000-devel@lists.sf.net, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, Mary Mcgrath
In-Reply-To: <50A9C5CC.1030300@oracle.com>
>-----Original Message-----
>From: Joe Jin [mailto:joe.jin@oracle.com]
>Sent: Sunday, November 18, 2012 9:38 PM
>To: Dave, Tushar N
>Cc: e1000-devel@lists.sf.net; netdev@vger.kernel.org; linux-
>kernel@vger.kernel.org; Mary Mcgrath
>Subject: Re: 82571EB: Detected Hardware Unit Hang
>
>On 11/16/12 04:26, Dave, Tushar N wrote:
>>> Would you please help to fine the offset of max payload size in eeprom?
>>> I'd like to have a try to modify it by ethtool.
>>
>> It is defined using bit 8 of word 0x1A.
>> Bit value 0 = 128B , bit value 1 = 256B
>
>Hi Tushar,
>
>I checked one of my server which Max Payload Size is 128:
>
># lspci -vvv -s 52:00.1
>52:00.1 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet
>Controller (rev 06)
> Subsystem: Intel Corporation PRO/1000 PT Quad Port Server Adapter
> Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop-
>ParErr+ Stepping- SERR- FastB2B- DisINTx+
> Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort-
><TAbort- <MAbort- >SERR- <PERR- INTx-
> Latency: 0, Cache Line Size: 64 bytes
> Interrupt: pin B routed to IRQ 266
> Region 0: Memory at dfea0000 (32-bit, non-prefetchable)
>[size=128K]
> Region 1: Memory at dfe80000 (32-bit, non-prefetchable)
>[size=128K]
> Region 2: I/O ports at 6020 [size=32]
> [virtual] Expansion ROM at d8120000 [disabled] [size=128K]
> Capabilities: [c8] Power Management version 2
> Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-
>,D3hot+,D3cold-)
> Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=1 PME-
> Capabilities: [d0] MSI: Enable+ Count=1/1 Maskable- 64bit+
> Address: 00000000fee00000 Data: 409a
> Capabilities: [e0] Express (v1) Endpoint, MSI 00
> DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s
><512ns, L1 <64us
> ExtTag- AttnBtn- AttnInd- PwrInd- RBE- FLReset-
> DevCtl: Report errors: Correctable+ Non-Fatal+ Fatal+
>Unsupported+
> RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
> MaxPayload 128 bytes, MaxReadReq 4096 bytes
> DevSta: CorrErr- UncorrErr- FatalErr+ UnsuppReq+ AuxPwr-
>TransPend-
> LnkCap: Port #0, Speed 2.5GT/s, Width x4, ASPM L0s,
>Latency L0 <4us, L1 <64us
> ClockPM- Surprise- LLActRep- BwNot-
> LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain-
>CommClk+
> ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
> LnkSta: Speed 2.5GT/s, Width x4, TrErr- Train- SlotClk+
>DLActive- BWMgmt- ABWMgmt-
> Capabilities: [100 v1] Advanced Error Reporting
> UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt-
>RxOF- MalfTLP- ECRC- UnsupReq+ ACSViol-
> UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt-
>RxOF- MalfTLP- ECRC- UnsupReq+ ACSViol-
> UESvrt: DLP+ SDES- TLP+ FCP+ CmpltTO+ CmpltAbrt+ UnxCmplt+
>RxOF+ MalfTLP+ ECRC- UnsupReq+ ACSViol-
> CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout-
>NonFatalErr-
> CEMsk: RxErr+ BadTLP+ BadDLLP+ Rollover+ Timeout+
>NonFatalErr-
> AERCap: First Error Pointer: 14, GenCap- CGenEn- ChkCap-
>ChkEn-
> Capabilities: [140 v1] Device Serial Number 00-15-17-ff-ff-16-ed-
>86
> Kernel driver in use: e1000e
> Kernel modules: e1000e
>
>And eeprom dump as below:
>
>Offset Values
>------ ------
>0x0000 00 15 17 16 ed 86 24 05 ff ff a2 50 ff ff ff ff
>0x0010 57 d4 07 74 2f a4 a4 11 86 80 a4 10 86 80 65 b1
>0x0020 08 00 a4 10 00 58 00 00 01 50 00 00 00 00 00 01
>0x0030 f6 6c b0 37 a6 07 03 84 83 07 00 00 03 c3 02 06
>0x0040 08 00 f0 0e 64 21 40 00 01 40 00 00 00 00 00 00
>0x0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>0x0060 00 01 00 40 1e 12 07 40 00 01 00 40 ff ff ff ff
>
>
>If I did not misunderstand, the value of offset 0x1a is 0x07a6, then the
>bit 8 is 1, but my NIC's MPS is 128b, anything I'm wrong?
Have you power off the system completely after modifying eeprom? If not please do so.
-Tushar
^ permalink raw reply
* Re: [PATCH 7/7] netprio_cgroup: allow nesting and inherit config on cgroup creation
From: Daniel Wagner @ 2012-11-20 8:57 UTC (permalink / raw)
To: Tejun Heo
Cc: nhorman-2XuSBdqkA4R54TAoqtyWWQ, netdev-u79uwXL29TY76Z2rM5mHXA,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, tgraf-G/eBtMaohhA,
cgroups-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <1353400211-5182-8-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Hi Tejun,
On 20.11.2012 09:30, Tejun Heo wrote:
> Inherit netprio configuration from ->css_online(), allow nesting and
> remove .broken_hierarchy marking. This makes netprio_cgroup's
> behavior match netcls_cgroup's.
>
> Note that this patch changes userland-visible behavior. Nesting is
> allowed and the first level cgroups below the root cgroup behave
> differently - they inherit priorities from the root cgroup on creation
> instead of starting with 0. This is unfortunate but not doing so is
> much crazier.
>
> Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Tested and Acked-by: Daniel Wagner <daniel.wagner-98C5kh4wR6ohFhg+JK9F0w@public.gmane.org>
> ---
> Documentation/cgroups/net_prio.txt | 2 ++
> net/core/netprio_cgroup.c | 42 ++++++++++++++++++++++----------------
> 2 files changed, 26 insertions(+), 18 deletions(-)
>
> diff --git a/Documentation/cgroups/net_prio.txt b/Documentation/cgroups/net_prio.txt
> index 01b3226..a82cbd2 100644
> --- a/Documentation/cgroups/net_prio.txt
> +++ b/Documentation/cgroups/net_prio.txt
> @@ -51,3 +51,5 @@ One usage for the net_prio cgroup is with mqprio qdisc allowing application
> traffic to be steered to hardware/driver based traffic classes. These mappings
> can then be managed by administrators or other networking protocols such as
> DCBX.
> +
> +A new net_prio cgroup inherits the parent's configuration.
> diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c
> index b2af0d0..bde53da 100644
> --- a/net/core/netprio_cgroup.c
> +++ b/net/core/netprio_cgroup.c
> @@ -136,9 +136,6 @@ static struct cgroup_subsys_state *cgrp_css_alloc(struct cgroup *cgrp)
> {
> struct cgroup_netprio_state *cs;
>
> - if (cgrp->parent && cgrp->parent->id)
> - return ERR_PTR(-EINVAL);
> -
> cs = kzalloc(sizeof(*cs), GFP_KERNEL);
> if (!cs)
> return ERR_PTR(-ENOMEM);
> @@ -146,16 +143,34 @@ static struct cgroup_subsys_state *cgrp_css_alloc(struct cgroup *cgrp)
> return &cs->css;
> }
>
> -static void cgrp_css_free(struct cgroup *cgrp)
> +static int cgrp_css_online(struct cgroup *cgrp)
> {
> - struct cgroup_netprio_state *cs = cgrp_netprio_state(cgrp);
> + struct cgroup *parent = cgrp->parent;
> struct net_device *dev;
> + int ret = 0;
> +
> + if (!parent)
> + return 0;
BTW, parent is always != NULL, because the root cgroup will be attached
to the dummytop cgroup.
This is the reason why there are this check in netprio_prio()
static u32 netprio_prio(struct cgroup *cgrp, struct net_device *dev)
{
struct netprio_map *map = rcu_dereference_rtnl(dev->priomap);
if (map && cgrp->id < map->priomap_len)
return map->priomap[cgrp->id];
is necessary.
cheer,
daniel
^ permalink raw reply
* Re: [PATCH 6/7] netprio_cgroup: implement netprio[_set]_prio() helpers
From: Daniel Wagner @ 2012-11-20 8:52 UTC (permalink / raw)
To: Tejun Heo
Cc: nhorman-2XuSBdqkA4R54TAoqtyWWQ, netdev-u79uwXL29TY76Z2rM5mHXA,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
daniel.wagner-98C5kh4wR6ohFhg+JK9F0w,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, tgraf-G/eBtMaohhA,
cgroups-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <1353400211-5182-7-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
On 20.11.2012 09:30, Tejun Heo wrote:
> Introduce two helpers - netprio_prio() and netprio_set_prio() - which
> hide the details of priomap access and expansion. This will help
> implementing hierarchy support.
>
> Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Acked-by: Neil Horman <nhorman-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
Tested and Acked-by: Daniel Wagner <daniel.wagner-98C5kh4wR6ohFhg+JK9F0w@public.gmane.org>
^ permalink raw reply
* Re: [PATCH] bonding: rlb mode of bond should not alter ARP originating via bridge
From: zheng.li @ 2012-11-20 8:51 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: netdev, andy, linux-kernel, davem, joe.jin
In-Reply-To: <30871.1353373354@death.nxdomain>
After i applied my prior patch to the latest kernel and tested ,i change
the patch as this. The prior patch is running ok on 2.6.32,but after
2.6.32 it runs no effect ,it still cause domu(which arp through bridge
via bonding) network intermittently unreachable. I found the reason is
that the alb_monitor of bonding(after 2.6.32) send unicast arp reply
which using rlb_client_info's assigned slave's MAC,so cause peer host
update arp cache of domu with wrong MAC to cause domu unreachable again.
The rlb_client_info is created when rlb_arp_xmit sending ARP request.
rlb_client_info contain local IP with assigned
slave,it will cause all local ip's ARP use slave's mac by
rlb_update_client function.
Bug reproduced rate: 100%.
So i change the patch also affect the ARP request to don't through rlb
to no create rlb_client_info. Applied the new patch on the latest
version,it runs ok.
So,the patch should affect ARP request and reply to work well.
bond_alb_monitor -> rlb_update_rx_clients --> rlb_update_client
rlb_update_client(struct rlb_client_info *client_info)
{
for (i = 0; i < RLB_ARP_BURST_SIZE; i++) {
struct sk_buff *skb;
skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
//peer host's IP
client_info->ip_dst,
client_info->slave->dev,
//Domu 's IP
client_info->ip_src,
//peer host's MAC which be set in rlb_arp_recv
client_info->mac_dst,
//use slave's MAC to send unicast arp reply to peer ,so cause peer host
//update MAC of domu with wrong mac address.
client_info->slave->dev->dev_addr,
client_info->mac_dst);
.......
}
Thanks
Zheng Li
> Zheng Li <zheng.x.li@oracle.com> wrote:
>
>> ARP traffic passing through a bridge and out via the bond (when the bond is a
>> port of the bridge) should not have its source MAC address adjusted by the
>> receive load balance code in rlb_arp_xmit.
>
> This patch differs from prior versions in that it does more than
> what's described here; it also disables the receive load balance logic
> for any ARPs (request or reply) that are passing through the bond (not
> of local origin). For ARP replies, that's mostly harmless, as the ARPs
> passing through will simply always be sent from one particular slave
> (the active slave) instead of being balanced.
>
> For ARP requests, though, they are already always sent via the
> active slave, but there is also some logic in rlb_arp_xmit to limit the
> side effects from the broadcast ARP, in particular this part:
>
> /* The ARP reply packets must be delayed so that
> * they can cancel out the influence of the ARP request.
> */
> bond->alb_info.rlb_update_delay_counter = RLB_UPDATE_DELAY;
>
> /* arp requests are broadcast and are sent on the primary
> * the arp request will collapse all clients on the subnet to
> * the primary slave. We must register these clients to be
> * updated with their assigned mac.
> */
> rlb_req_update_subnet_clients(bond, arp->ip_src);
>
> that arranges for clients to be given ARP updates for their
> slave assignments (which may change to the active slave, due to the ARP
> broadcast being sent via the active slave).
>
> I think the ARP reply side of this is fine (and is what is
> described in teh changelog), but the ARP request behavior change is new
> with this version.
>
> Since prior versions of the patch didn't cause this code to be
> skipped, is this change intentional?
>
> Did you check to see if the above logic is necessary for ARP
> requests passing through via a bridge to prevent peers from "stacking"
> (in terms of load balance assignment) on the active slave due to bridged
> ARP traffic?
>
> -J
>
>> Signed-off-by: Zheng Li <zheng.x.li@oracle.com>
>> Cc: Jay Vosburgh <fubar@us.ibm.com>
>> Cc: Andy Gospodarek <andy@greyhouse.net>
>> Cc: "David S. Miller" <davem@davemloft.net>
>>
>> ---
>> drivers/net/bonding/bond_alb.c | 6 ++++++
>> drivers/net/bonding/bonding.h | 13 +++++++++++++
>> 2 files changed, 19 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
>> index e15cc11..75f6f0d 100644
>> --- a/drivers/net/bonding/bond_alb.c
>> +++ b/drivers/net/bonding/bond_alb.c
>> @@ -694,6 +694,12 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
>> struct arp_pkt *arp = arp_pkt(skb);
>> struct slave *tx_slave = NULL;
>>
>> + /* Only modify ARP's MAC if it originates locally;
>> + * don't change ARPs arriving via a bridge.
>> + */
>> + if (!bond_slave_has_mac(bond, arp->mac_src))
>> + return NULL;
>> +
>> if (arp->op_code == htons(ARPOP_REPLY)) {
>> /* the arp must be sent on the selected
>> * rx channel
>> diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
>> index f8af2fc..6dded56 100644
>> --- a/drivers/net/bonding/bonding.h
>> +++ b/drivers/net/bonding/bonding.h
>> @@ -22,6 +22,7 @@
>> #include <linux/in6.h>
>> #include <linux/netpoll.h>
>> #include <linux/inetdevice.h>
>> +#include <linux/etherdevice.h>
>> #include "bond_3ad.h"
>> #include "bond_alb.h"
>>
>> @@ -450,6 +451,18 @@ static inline void bond_destroy_proc_dir(struct bond_net *bn)
>> }
>> #endif
>>
>> +static inline struct slave *bond_slave_has_mac(struct bonding *bond,
>> + const u8 *mac)
>> +{
>> + int i = 0;
>> + struct slave *tmp;
>> +
>> + bond_for_each_slave(bond, tmp, i)
>> + if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
>> + return tmp;
>> +
>> + return NULL;
>> +}
>>
>> /* exported from bond_main.c */
>> extern int bond_net_id;
>> --
>> 1.7.6.5
>
> ---
> -Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com
>
^ permalink raw reply
* Re: [PATCH 5/7] netprio_cgroup: use cgroup->id instead of cgroup_netprio_state->prioidx
From: Daniel Wagner @ 2012-11-20 8:47 UTC (permalink / raw)
To: Tejun Heo
Cc: nhorman-2XuSBdqkA4R54TAoqtyWWQ, netdev-u79uwXL29TY76Z2rM5mHXA,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, tgraf-G/eBtMaohhA,
cgroups-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <1353400211-5182-6-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
On 20.11.2012 09:30, Tejun Heo wrote:
> With priomap expansion no longer depending on knowing max id
> allocated, netprio_cgroup can use cgroup->id insted of cs->prioidx.
> Drop prioidx alloc/free logic and convert all uses to cgroup->id.
>
> * In cgrp_css_alloc(), parent->id test is moved above @cs allocation
> to simplify error path.
>
> * In cgrp_css_free(), @cs assignment is made initialization.
>
> Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Acked-by: Neil Horman <nhorman-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
Tested and Acked-by: Daniel Wagner <daniel.wagner-98C5kh4wR6ohFhg+JK9F0w@public.gmane.org>
^ permalink raw reply
* Re: [PATCH v5] can: kvaser_usb: Add support for Kvaser CAN/USB devices
From: Olivier Sobrie @ 2012-11-20 8:46 UTC (permalink / raw)
To: Marc Kleine-Budde; +Cc: Wolfgang Grandegger, linux-can, netdev, linux-usb
In-Reply-To: <509AC491.2090701@pengutronix.de>
Hi Marc,
On Wed, Nov 07, 2012 at 09:29:05PM +0100, Marc Kleine-Budde wrote:
> On 10/02/2012 09:16 AM, Olivier Sobrie wrote:
> > This driver provides support for several Kvaser CAN/USB devices.
> > Such kind of devices supports up to three CAN network interfaces.
> >
> > It has been tested with a Kvaser USB Leaf Light (one network interface)
> > connected to a pch_can interface.
> > The firmware version of the Kvaser device was 2.5.205.
> >
> > List of Kvaser devices supported by the driver:
> > - Kvaser Leaf Light
> > - Kvaser Leaf Professional HS
> > - Kvaser Leaf SemiPro HS
> > - Kvaser Leaf Professional LS
> > - Kvaser Leaf Professional SWC
> > - Kvaser Leaf Professional LIN
> > - Kvaser Leaf SemiPro LS
> > - Kvaser Leaf SemiPro SWC
> > - Kvaser Memorator II HS/HS
> > - Kvaser USBcan Professional HS/HS
> > - Kvaser Leaf Light GI
> > - Kvaser Leaf Professional HS (OBD-II connector)
> > - Kvaser Memorator Professional HS/LS
> > - Kvaser Leaf Light "China"
> > - Kvaser BlackBird SemiPro
> > - Kvaser USBcan R
> >
> > Signed-off-by: Daniel Berglund <db@kvaser.com>
> > Signed-off-by: Olivier Sobrie <olivier@sobrie.be>
>
> Sorry I forgot about the review.
> Looks quite good, some comments inline.
Sorry for the late reply but I was in holiday during the last
3 weeks :-)
See my comments below.
>
> > ---
> > Hi,
> >
> > This new patch fixes the errors pointed out by Marc and Wolfgang.
> >
> > Changes since v4:
> > - add missing usb_free_urb()
> > - put error message in a separate function
> > - handle return code of kvaser_usb_init_one() in probe function
> >
> > Olivier
> >
> > drivers/net/can/usb/Kconfig | 29 +
> > drivers/net/can/usb/Makefile | 1 +
> > drivers/net/can/usb/kvaser_usb.c | 1596 ++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 1626 insertions(+)
> > create mode 100644 drivers/net/can/usb/kvaser_usb.c
> >
> > diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig
> > index 0a68768..a4e4bee 100644
> > --- a/drivers/net/can/usb/Kconfig
> > +++ b/drivers/net/can/usb/Kconfig
> > @@ -13,6 +13,35 @@ config CAN_ESD_USB2
> > This driver supports the CAN-USB/2 interface
> > from esd electronic system design gmbh (http://www.esd.eu).
> >
> > +config CAN_KVASER_USB
> > + tristate "Kvaser CAN/USB interface"
> > + ---help---
> > + This driver adds support for Kvaser CAN/USB devices like Kvaser
> > + Leaf Light.
> > +
> > + The driver gives support for the following devices:
> > + - Kvaser Leaf Light
> > + - Kvaser Leaf Professional HS
> > + - Kvaser Leaf SemiPro HS
> > + - Kvaser Leaf Professional LS
> > + - Kvaser Leaf Professional SWC
> > + - Kvaser Leaf Professional LIN
> > + - Kvaser Leaf SemiPro LS
> > + - Kvaser Leaf SemiPro SWC
> > + - Kvaser Memorator II HS/HS
> > + - Kvaser USBcan Professional HS/HS
> > + - Kvaser Leaf Light GI
> > + - Kvaser Leaf Professional HS (OBD-II connector)
> > + - Kvaser Memorator Professional HS/LS
> > + - Kvaser Leaf Light "China"
> > + - Kvaser BlackBird SemiPro
> > + - Kvaser USBcan R
> > +
> > + If unsure, say N.
> > +
> > + To compile this driver as a module, choose M here: the
> > + module will be called kvaser_usb.
> > +
> > config CAN_PEAK_USB
> > tristate "PEAK PCAN-USB/USB Pro interfaces"
> > ---help---
> > diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile
> > index da6d1d3..80a2ee4 100644
> > --- a/drivers/net/can/usb/Makefile
> > +++ b/drivers/net/can/usb/Makefile
> > @@ -4,6 +4,7 @@
> >
> > obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
> > obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o
> > +obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o
> > obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/
> >
> > ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
> > diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
> > new file mode 100644
> > index 0000000..bd48807
> > --- /dev/null
> > +++ b/drivers/net/can/usb/kvaser_usb.c
> > @@ -0,0 +1,1596 @@
> > +/*
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License as
> > + * published by the Free Software Foundation version 2.
> > + *
> > + * Parts of this driver are based on the following:
> > + * - Kvaser linux leaf driver (version 4.78)
> > + * - CAN driver for esd CAN-USB/2
> > + *
> > + * Copyright (C) 2002-2006 KVASER AB, Sweden. All rights reserved.
> > + * Copyright (C) 2010 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh
> > + * Copyright (C) 2012 Olivier Sobrie <olivier@sobrie.be>
> > + */
> > +
> > +#include <linux/init.h>
> > +#include <linux/completion.h>
> > +#include <linux/module.h>
> > +#include <linux/netdevice.h>
> > +#include <linux/usb.h>
> > +
> > +#include <linux/can.h>
> > +#include <linux/can/dev.h>
> > +#include <linux/can/error.h>
> > +
> > +#define MAX_TX_URBS 16
> > +#define MAX_RX_URBS 4
> > +#define START_TIMEOUT 1000 /* msecs */
> > +#define STOP_TIMEOUT 1000 /* msecs */
> > +#define USB_SEND_TIMEOUT 1000 /* msecs */
> > +#define USB_RECV_TIMEOUT 1000 /* msecs */
> > +#define RX_BUFFER_SIZE 3072
> > +#define CAN_USB_CLOCK 8000000
> > +#define MAX_NET_DEVICES 3
> > +
> > +/* Kvaser USB devices */
> > +#define KVASER_VENDOR_ID 0x0bfd
> > +#define USB_LEAF_DEVEL_PRODUCT_ID 10
> > +#define USB_LEAF_LITE_PRODUCT_ID 11
> > +#define USB_LEAF_PRO_PRODUCT_ID 12
> > +#define USB_LEAF_SPRO_PRODUCT_ID 14
> > +#define USB_LEAF_PRO_LS_PRODUCT_ID 15
> > +#define USB_LEAF_PRO_SWC_PRODUCT_ID 16
> > +#define USB_LEAF_PRO_LIN_PRODUCT_ID 17
> > +#define USB_LEAF_SPRO_LS_PRODUCT_ID 18
> > +#define USB_LEAF_SPRO_SWC_PRODUCT_ID 19
> > +#define USB_MEMO2_DEVEL_PRODUCT_ID 22
> > +#define USB_MEMO2_HSHS_PRODUCT_ID 23
> > +#define USB_UPRO_HSHS_PRODUCT_ID 24
> > +#define USB_LEAF_LITE_GI_PRODUCT_ID 25
> > +#define USB_LEAF_PRO_OBDII_PRODUCT_ID 26
> > +#define USB_MEMO2_HSLS_PRODUCT_ID 27
> > +#define USB_LEAF_LITE_CH_PRODUCT_ID 28
> > +#define USB_BLACKBIRD_SPRO_PRODUCT_ID 29
> > +#define USB_OEM_MERCURY_PRODUCT_ID 34
> > +#define USB_OEM_LEAF_PRODUCT_ID 35
> > +#define USB_CAN_R_PRODUCT_ID 39
> > +
> > +/* USB devices features */
> > +#define KVASER_HAS_SILENT_MODE BIT(0)
> > +#define KVASER_HAS_TXRX_ERRORS BIT(1)
> > +
> > +/* Message header size */
> > +#define MSG_HEADER_LEN 2
> > +
> > +/* Can message flags */
> > +#define MSG_FLAG_ERROR_FRAME BIT(0)
> > +#define MSG_FLAG_OVERRUN BIT(1)
> > +#define MSG_FLAG_NERR BIT(2)
> > +#define MSG_FLAG_WAKEUP BIT(3)
> > +#define MSG_FLAG_REMOTE_FRAME BIT(4)
> > +#define MSG_FLAG_RESERVED BIT(5)
> > +#define MSG_FLAG_TX_ACK BIT(6)
> > +#define MSG_FLAG_TX_REQUEST BIT(7)
> > +
> > +/* Can states */
> > +#define M16C_STATE_BUS_RESET BIT(0)
> > +#define M16C_STATE_BUS_ERROR BIT(4)
> > +#define M16C_STATE_BUS_PASSIVE BIT(5)
> > +#define M16C_STATE_BUS_OFF BIT(6)
> > +
> > +/* Can msg ids */
> > +#define CMD_RX_STD_MESSAGE 12
> > +#define CMD_TX_STD_MESSAGE 13
> > +#define CMD_RX_EXT_MESSAGE 14
> > +#define CMD_TX_EXT_MESSAGE 15
> > +#define CMD_SET_BUS_PARAMS 16
> > +#define CMD_GET_BUS_PARAMS 17
> > +#define CMD_GET_BUS_PARAMS_REPLY 18
> > +#define CMD_GET_CHIP_STATE 19
> > +#define CMD_CHIP_STATE_EVENT 20
> > +#define CMD_SET_CTRL_MODE 21
> > +#define CMD_GET_CTRL_MODE 22
> > +#define CMD_GET_CTRL_MODE_REPLY 23
> > +#define CMD_RESET_CHIP 24
> > +#define CMD_RESET_CARD 25
> > +#define CMD_START_CHIP 26
> > +#define CMD_START_CHIP_REPLY 27
> > +#define CMD_STOP_CHIP 28
> > +#define CMD_STOP_CHIP_REPLY 29
> > +#define CMD_GET_CARD_INFO2 32
> > +#define CMD_GET_CARD_INFO 34
> > +#define CMD_GET_CARD_INFO_REPLY 35
> > +#define CMD_GET_SOFTWARE_INFO 38
> > +#define CMD_GET_SOFTWARE_INFO_REPLY 39
> > +#define CMD_ERROR_EVENT 45
> > +#define CMD_FLUSH_QUEUE 48
> > +#define CMD_RESET_ERROR_COUNTER 49
> > +#define CMD_TX_ACKNOWLEDGE 50
> > +#define CMD_CAN_ERROR_EVENT 51
> > +#define CMD_USB_THROTTLE 77
> > +#define CMD_LOG_MESSAGE 106
> > +
> > +/* error factors */
> > +#define M16C_EF_ACKE BIT(0)
> > +#define M16C_EF_CRCE BIT(1)
> > +#define M16C_EF_FORME BIT(2)
> > +#define M16C_EF_STFE BIT(3)
> > +#define M16C_EF_BITE0 BIT(4)
> > +#define M16C_EF_BITE1 BIT(5)
> > +#define M16C_EF_RCVE BIT(6)
> > +#define M16C_EF_TRE BIT(7)
> > +
> > +/* bittiming parameters */
> > +#define KVASER_USB_TSEG1_MIN 1
> > +#define KVASER_USB_TSEG1_MAX 16
> > +#define KVASER_USB_TSEG2_MIN 1
> > +#define KVASER_USB_TSEG2_MAX 8
> > +#define KVASER_USB_SJW_MAX 4
> > +#define KVASER_USB_BRP_MIN 1
> > +#define KVASER_USB_BRP_MAX 64
> > +#define KVASER_USB_BRP_INC 1
> > +
> > +/* ctrl modes */
> > +#define KVASER_CTRL_MODE_NORMAL 1
> > +#define KVASER_CTRL_MODE_SILENT 2
> > +#define KVASER_CTRL_MODE_SELFRECEPTION 3
> > +#define KVASER_CTRL_MODE_OFF 4
> > +
> > +struct kvaser_msg_simple {
> > + u8 tid;
> > + u8 channel;
> > +} __packed;
> > +
> > +struct kvaser_msg_cardinfo {
> > + u8 tid;
> > + u8 nchannels;
> > + __le32 serial_number;
> > + __le32 padding;
> > + __le32 clock_resolution;
> > + __le32 mfgdate;
> > + u8 ean[8];
> > + u8 hw_revision;
> > + u8 usb_hs_mode;
> > + __le16 padding2;
> > +} __packed;
> > +
> > +struct kvaser_msg_cardinfo2 {
> > + u8 tid;
> > + u8 channel;
> > + u8 pcb_id[24];
> > + __le32 oem_unlock_code;
> > +} __packed;
> > +
> > +struct kvaser_msg_softinfo {
> > + u8 tid;
> > + u8 channel;
> > + __le32 sw_options;
> > + __le32 fw_version;
> > + __le16 max_outstanding_tx;
> > + __le16 padding[9];
> > +} __packed;
> > +
> > +struct kvaser_msg_busparams {
> > + u8 tid;
> > + u8 channel;
> > + __le32 bitrate;
> > + u8 tseg1;
> > + u8 tseg2;
> > + u8 sjw;
> > + u8 no_samp;
> > +} __packed;
> > +
> > +struct kvaser_msg_tx_can {
> > + u8 channel;
> > + u8 tid;
> > + u8 msg[14];
> > + u8 padding;
> > + u8 flags;
> > +} __packed;
> > +
> > +struct kvaser_msg_rx_can {
> > + u8 channel;
> > + u8 flag;
> > + __le16 time[3];
> > + u8 msg[14];
> > +} __packed;
> > +
> > +struct kvaser_msg_chip_state_event {
> > + u8 tid;
> > + u8 channel;
> > + __le16 time[3];
> > + u8 tx_errors_count;
> > + u8 rx_errors_count;
> > + u8 status;
> > + u8 padding[3];
> > +} __packed;
> > +
> > +struct kvaser_msg_tx_acknowledge {
> > + u8 channel;
> > + u8 tid;
> > + __le16 time[3];
> > + u8 flags;
> > + u8 time_offset;
> > +} __packed;
> > +
> > +struct kvaser_msg_error_event {
> > + u8 tid;
> > + u8 flags;
> > + __le16 time[3];
> > + u8 channel;
> > + u8 padding;
> > + u8 tx_errors_count;
> > + u8 rx_errors_count;
> > + u8 status;
> > + u8 error_factor;
> > +} __packed;
> > +
> > +struct kvaser_msg_ctrl_mode {
> > + u8 tid;
> > + u8 channel;
> > + u8 ctrl_mode;
> > + u8 padding[3];
> > +} __packed;
> > +
> > +struct kvaser_msg_flush_queue {
> > + u8 tid;
> > + u8 channel;
> > + u8 flags;
> > + u8 padding[3];
> > +} __packed;
> > +
> > +struct kvaser_msg_log_message {
> > + u8 channel;
> > + u8 flags;
> > + __le16 time[3];
> > + u8 dlc;
> > + u8 time_offset;
> > + __le32 id;
> > + u8 data[8];
> > +} __packed;
> > +
> > +struct kvaser_msg {
> > + u8 len;
> > + u8 id;
> > + union {
> > + struct kvaser_msg_simple simple;
> > + struct kvaser_msg_cardinfo cardinfo;
> > + struct kvaser_msg_cardinfo2 cardinfo2;
> > + struct kvaser_msg_softinfo softinfo;
> > + struct kvaser_msg_busparams busparams;
> > + struct kvaser_msg_tx_can tx_can;
> > + struct kvaser_msg_rx_can rx_can;
> > + struct kvaser_msg_chip_state_event chip_state_event;
> > + struct kvaser_msg_tx_acknowledge tx_acknowledge;
> > + struct kvaser_msg_error_event error_event;
> > + struct kvaser_msg_ctrl_mode ctrl_mode;
> > + struct kvaser_msg_flush_queue flush_queue;
> > + struct kvaser_msg_log_message log_message;
> > + } u;
> > +} __packed;
> > +
> > +struct kvaser_usb_tx_urb_context {
> > + struct kvaser_usb_net_priv *priv;
> > + u32 echo_index;
> > + int dlc;
> > +};
> > +
> > +struct kvaser_usb {
> > + struct usb_device *udev;
> > + struct kvaser_usb_net_priv *nets[MAX_NET_DEVICES];
> > +
> > + struct usb_endpoint_descriptor *bulk_in, *bulk_out;
> > + struct usb_anchor rx_submitted;
> > +
> > + u32 fw_version;
> > + unsigned int nchannels;
> > +
> > + bool rxinitdone;
> > + void *rxbuf[MAX_RX_URBS];
> > + dma_addr_t rxbuf_dma[MAX_RX_URBS];
> > +};
> > +
> > +struct kvaser_usb_net_priv {
> > + struct can_priv can;
> > +
> > + atomic_t active_tx_urbs;
> > + struct usb_anchor tx_submitted;
> > + struct kvaser_usb_tx_urb_context tx_contexts[MAX_TX_URBS];
> > +
> > + struct completion start_comp, stop_comp;
> > +
> > + struct kvaser_usb *dev;
> > + struct net_device *netdev;
> > + int channel;
> > +
> > + struct can_berr_counter bec;
> > +};
> > +
> > +static struct usb_device_id kvaser_usb_table[] = {
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID) },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID) },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS |
> > + KVASER_HAS_SILENT_MODE },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS |
> > + KVASER_HAS_SILENT_MODE },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LS_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS |
> > + KVASER_HAS_SILENT_MODE },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_SWC_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS |
> > + KVASER_HAS_SILENT_MODE },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LIN_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS |
> > + KVASER_HAS_SILENT_MODE },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_LS_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS |
> > + KVASER_HAS_SILENT_MODE },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_SWC_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS |
> > + KVASER_HAS_SILENT_MODE },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_DEVEL_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS |
> > + KVASER_HAS_SILENT_MODE },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSHS_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS |
> > + KVASER_HAS_SILENT_MODE },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_UPRO_HSHS_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID) },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_OBDII_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS |
> > + KVASER_HAS_SILENT_MODE },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSLS_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_CH_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_SPRO_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_MERCURY_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_LEAF_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS },
> > + { USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID),
> > + .driver_info = KVASER_HAS_TXRX_ERRORS },
> > + { }
> > +};
> > +MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
> > +
> > +static inline int kvaser_usb_send_msg(const struct kvaser_usb *dev,
> > + struct kvaser_msg *msg)
> > +{
> > + int actual_len;
> > +
> > + return usb_bulk_msg(dev->udev,
> > + usb_sndbulkpipe(dev->udev,
> > + dev->bulk_out->bEndpointAddress),
> > + msg, msg->len, &actual_len,
> > + USB_SEND_TIMEOUT);
> > +}
> > +
> > +static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id,
> > + struct kvaser_msg *msg)
> > +{
> > + struct kvaser_msg *tmp;
> > + void *buf;
> > + int actual_len;
> > + int err;
> > + int pos = 0;
> > +
> > + buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL);
> > + if (!buf)
> > + return -ENOMEM;
> > +
> > + err = usb_bulk_msg(dev->udev,
> > + usb_rcvbulkpipe(dev->udev,
> > + dev->bulk_in->bEndpointAddress),
> > + buf, RX_BUFFER_SIZE, &actual_len,
> > + USB_RECV_TIMEOUT);
> > + if (err < 0)
> > + goto end;
> > +
> > + while (pos <= actual_len - MSG_HEADER_LEN) {
> > + tmp = buf + pos;
> > +
> > + if (!tmp->len)
> > + break;
> > +
> > + if (pos + tmp->len > actual_len) {
> > + dev_err(dev->udev->dev.parent, "Format error\n");
> > + break;
> > + }
> > +
> > + if (tmp->id == id) {
> > + memcpy(msg, tmp, tmp->len);
> > + goto end;
> > + }
> > +
> > + pos += tmp->len;
> > + }
> > +
> > + err = -EINVAL;
> > +
> > +end:
> > + kfree(buf);
> > +
> > + return err;
> > +}
> > +
> > +static int kvaser_usb_send_simple_msg(const struct kvaser_usb *dev,
> > + u8 msg_id, int channel)
> > +{
> > + struct kvaser_msg msg = {
> > + .len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_simple),
> > + .id = msg_id,
> > + .u.simple.channel = channel,
> > + .u.simple.tid = 0xff,
> > + };
> > +
> > + return kvaser_usb_send_msg(dev, &msg);
> > +}
> > +
> > +static int kvaser_usb_get_software_info(struct kvaser_usb *dev)
> > +{
> > + struct kvaser_msg msg;
> > + int err;
> > +
> > + err = kvaser_usb_send_simple_msg(dev, CMD_GET_SOFTWARE_INFO, 0);
> > + if (err)
> > + return err;
> > +
> > + err = kvaser_usb_wait_msg(dev, CMD_GET_SOFTWARE_INFO_REPLY, &msg);
> > + if (err)
> > + return err;
> > +
> > + dev->fw_version = le32_to_cpu(msg.u.softinfo.fw_version);
> > +
> > + return 0;
> > +}
> > +
> > +static int kvaser_usb_get_card_info(struct kvaser_usb *dev)
> > +{
> > + struct kvaser_msg msg;
> > + int err;
> > +
> > + err = kvaser_usb_send_simple_msg(dev, CMD_GET_CARD_INFO, 0);
> > + if (err)
> > + return err;
> > +
> > + err = kvaser_usb_wait_msg(dev, CMD_GET_CARD_INFO_REPLY, &msg);
> > + if (err)
> > + return err;
> > +
> > + dev->nchannels = msg.u.cardinfo.nchannels;
> > +
> > + return 0;
> > +}
> > +
> > +static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
> > + const struct kvaser_msg *msg)
> > +{
> > + struct net_device_stats *stats;
> > + struct kvaser_usb_tx_urb_context *context;
> > + struct kvaser_usb_net_priv *priv;
> > + struct sk_buff *skb;
> > + struct can_frame *cf;
> > + u8 channel = msg->u.tx_acknowledge.channel;
> > + u8 tid = msg->u.tx_acknowledge.tid;
> > +
> > + if (channel >= dev->nchannels) {
> > + dev_err(dev->udev->dev.parent,
> > + "Invalid channel number (%d)\n", channel);
> > + return;
> > + }
> > +
> > + priv = dev->nets[channel];
> > +
> > + if (!netif_device_present(priv->netdev))
> > + return;
> > +
> > + stats = &priv->netdev->stats;
> > +
> > + context = &priv->tx_contexts[tid % MAX_TX_URBS];
> > +
> > + /* Sometimes the state change doesn't come after a bus-off event */
> > + if (priv->can.restart_ms &&
> > + (priv->can.state >= CAN_STATE_BUS_OFF)) {
> > + skb = alloc_can_err_skb(priv->netdev, &cf);
> > + if (skb) {
> > + cf->can_id |= CAN_ERR_RESTARTED;
> > + netif_rx(skb);
> > +
> > + stats->rx_packets++;
> > + stats->rx_bytes += cf->can_dlc;
> > + } else {
> > + netdev_err(priv->netdev,
> > + "No memory left for err_skb\n");
> > + }
> > +
> > + priv->can.can_stats.restarts++;
> > + netif_carrier_on(priv->netdev);
> > +
> > + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> > + }
> > +
> > + stats->tx_packets++;
> > + stats->tx_bytes += context->dlc;
> > + can_get_echo_skb(priv->netdev, context->echo_index);
> > +
> > + context->echo_index = MAX_TX_URBS;
> > + atomic_dec(&priv->active_tx_urbs);
> > +
> > + netif_wake_queue(priv->netdev);
> > +}
> > +
> > +static void kvaser_usb_simple_msg_callback(struct urb *urb)
> > +{
> > + struct net_device *netdev = urb->context;
> > +
> > + kfree(urb->transfer_buffer);
> > +
> > + if (urb->status)
> > + netdev_warn(netdev, "urb status received: %d\n",
> > + urb->status);
> > +}
> > +
> > +static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv,
> > + u8 msg_id)
> > +{
> > + struct kvaser_usb *dev = priv->dev;
> > + struct net_device *netdev = priv->netdev;
> > + struct kvaser_msg *msg;
> > + struct urb *urb;
> > + void *buf;
> > + int err;
> > +
> > + urb = usb_alloc_urb(0, GFP_ATOMIC);
> > + if (!urb) {
> > + netdev_err(netdev, "No memory left for URBs\n");
> > + return -ENOMEM;
> > + }
> > +
> > + buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
> > + if (!buf) {
> > + netdev_err(netdev, "No memory left for USB buffer\n");
> > + usb_free_urb(urb);
> > + return -ENOMEM;
> > + }
> > +
> > + msg = (struct kvaser_msg *)buf;
> > + msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_simple);
> > + msg->id = msg_id;
> > + msg->u.simple.channel = priv->channel;
> > +
> > + usb_fill_bulk_urb(urb, dev->udev,
> > + usb_sndbulkpipe(dev->udev,
> > + dev->bulk_out->bEndpointAddress),
> > + buf, msg->len,
> > + kvaser_usb_simple_msg_callback, priv);
> > + usb_anchor_urb(urb, &priv->tx_submitted);
> > +
> > + err = usb_submit_urb(urb, GFP_ATOMIC);
> > + if (err) {
> > + netdev_err(netdev, "Error transmitting URB\n");
> > + usb_unanchor_urb(urb);
> > + usb_free_urb(urb);
> > + kfree(buf);
> > + return err;
> > + }
> > +
> > + usb_free_urb(urb);
> > +
> > + return 0;
> > +}
> > +
> > +static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
> > +{
> > + int i;
> > +
> > + usb_kill_anchored_urbs(&priv->tx_submitted);
> > + atomic_set(&priv->active_tx_urbs, 0);
> > +
> > + for (i = 0; i < MAX_TX_URBS; i++)
> > + priv->tx_contexts[i].echo_index = MAX_TX_URBS;
> > +}
> > +
> > +static void kvaser_usb_rx_error(const struct kvaser_usb *dev,
> > + const struct kvaser_msg *msg)
> > +{
> > + struct can_frame *cf;
> > + struct sk_buff *skb;
> > + struct net_device_stats *stats;
> > + struct kvaser_usb_net_priv *priv;
> > + unsigned int new_state;
> > + u8 channel, status, txerr, rxerr, error_factor;
> > +
> > + switch (msg->id) {
> > + case CMD_CAN_ERROR_EVENT:
> > + channel = msg->u.error_event.channel;
> > + status = msg->u.error_event.status;
> > + txerr = msg->u.error_event.tx_errors_count;
> > + rxerr = msg->u.error_event.rx_errors_count;
> > + error_factor = msg->u.error_event.error_factor;
> > + break;
> > + case CMD_LOG_MESSAGE:
> > + channel = msg->u.log_message.channel;
> > + status = msg->u.log_message.data[0];
> > + txerr = msg->u.log_message.data[2];
> > + rxerr = msg->u.log_message.data[3];
> > + error_factor = msg->u.log_message.data[1];
> > + break;
> > + case CMD_CHIP_STATE_EVENT:
> > + channel = msg->u.chip_state_event.channel;
> > + status = msg->u.chip_state_event.status;
> > + txerr = msg->u.chip_state_event.tx_errors_count;
> > + rxerr = msg->u.chip_state_event.rx_errors_count;
> > + error_factor = 0;
> > + break;
> > + default:
> > + dev_err(dev->udev->dev.parent, "Invalid msg id (%d)\n",
> > + msg->id);
> > + return;
> > + }
> > +
> > + if (channel >= dev->nchannels) {
> > + dev_err(dev->udev->dev.parent,
> > + "Invalid channel number (%d)\n", channel);
> > + return;
> > + }
> > +
> > + priv = dev->nets[channel];
> > + stats = &priv->netdev->stats;
> > +
> > + if (status & M16C_STATE_BUS_RESET) {
> > + kvaser_usb_unlink_tx_urbs(priv);
> > + return;
> > + }
> > +
> > + skb = alloc_can_err_skb(priv->netdev, &cf);
> > + if (!skb) {
> > + stats->rx_dropped++;
> > + return;
> > + }
> > +
> > + new_state = priv->can.state;
> > +
> > + netdev_dbg(priv->netdev, "Error status: 0x%02x\n", status);
> > +
> > + if (status & M16C_STATE_BUS_OFF) {
> > + cf->can_id |= CAN_ERR_BUSOFF;
> > +
> > + priv->can.can_stats.bus_off++;
> > + if (!priv->can.restart_ms)
> > + kvaser_usb_simple_msg_async(priv, CMD_STOP_CHIP);
> > +
> > + netif_carrier_off(priv->netdev);
> > +
> > + new_state = CAN_STATE_BUS_OFF;
> > + } else if (status & M16C_STATE_BUS_PASSIVE) {
> > + if (priv->can.state != CAN_STATE_ERROR_PASSIVE) {
> > + cf->can_id |= CAN_ERR_CRTL;
> > +
> > + if (txerr || rxerr)
> > + cf->data[1] = (txerr > rxerr)
> > + ? CAN_ERR_CRTL_TX_PASSIVE
> > + : CAN_ERR_CRTL_RX_PASSIVE;
> > + else
> > + cf->data[1] = CAN_ERR_CRTL_TX_PASSIVE |
> > + CAN_ERR_CRTL_RX_PASSIVE;
> > +
> > + priv->can.can_stats.error_passive++;
> > + }
> > +
> > + new_state = CAN_STATE_ERROR_PASSIVE;
> > + }
> > +
> > + if (status == M16C_STATE_BUS_ERROR) {
> > + if ((priv->can.state < CAN_STATE_ERROR_WARNING) &&
> > + ((txerr >= 96) || (rxerr >= 96))) {
> > + cf->can_id |= CAN_ERR_CRTL;
> > + cf->data[1] = (txerr > rxerr)
> > + ? CAN_ERR_CRTL_TX_WARNING
> > + : CAN_ERR_CRTL_RX_WARNING;
> > +
> > + priv->can.can_stats.error_warning++;
> > + new_state = CAN_STATE_ERROR_WARNING;
> > + } else if (priv->can.state > CAN_STATE_ERROR_ACTIVE) {
> > + cf->can_id |= CAN_ERR_PROT;
> > + cf->data[2] = CAN_ERR_PROT_ACTIVE;
> > +
> > + new_state = CAN_STATE_ERROR_ACTIVE;
> > + }
> > + }
> > +
> > + if (!status) {
> > + cf->can_id |= CAN_ERR_PROT;
> > + cf->data[2] = CAN_ERR_PROT_ACTIVE;
> > +
> > + new_state = CAN_STATE_ERROR_ACTIVE;
> > + }
> > +
> > + if (priv->can.restart_ms &&
> > + (priv->can.state >= CAN_STATE_BUS_OFF) &&
> > + (new_state < CAN_STATE_BUS_OFF)) {
> > + cf->can_id |= CAN_ERR_RESTARTED;
> > + netif_carrier_on(priv->netdev);
> > +
> > + priv->can.can_stats.restarts++;
> > + }
> > +
> > + if (error_factor) {
> > + priv->can.can_stats.bus_error++;
> > + stats->rx_errors++;
> > +
> > + cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
> > +
> > + if (error_factor & M16C_EF_ACKE)
> > + cf->data[3] |= (CAN_ERR_PROT_LOC_ACK);
> > + if (error_factor & M16C_EF_CRCE)
> > + cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
> > + CAN_ERR_PROT_LOC_CRC_DEL);
> > + if (error_factor & M16C_EF_FORME)
> > + cf->data[2] |= CAN_ERR_PROT_FORM;
> > + if (error_factor & M16C_EF_STFE)
> > + cf->data[2] |= CAN_ERR_PROT_STUFF;
> > + if (error_factor & M16C_EF_BITE0)
> > + cf->data[2] |= CAN_ERR_PROT_BIT0;
> > + if (error_factor & M16C_EF_BITE1)
> > + cf->data[2] |= CAN_ERR_PROT_BIT1;
> > + if (error_factor & M16C_EF_TRE)
> > + cf->data[2] |= CAN_ERR_PROT_TX;
> > + }
> > +
> > + cf->data[6] = txerr;
> > + cf->data[7] = rxerr;
> > +
> > + priv->bec.txerr = txerr;
> > + priv->bec.rxerr = rxerr;
> > +
> > + priv->can.state = new_state;
> > +
> > + netif_rx(skb);
> > +
> > + stats->rx_packets++;
> > + stats->rx_bytes += cf->can_dlc;
> > +}
> > +
> > +static void kvaser_usb_rx_can_err(const struct kvaser_usb_net_priv *priv,
> > + const struct kvaser_msg *msg)
> > +{
> > + struct can_frame *cf;
> > + struct sk_buff *skb;
> > + struct net_device_stats *stats = &priv->netdev->stats;
> > +
> > + if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME |
> > + MSG_FLAG_NERR)) {
> > + netdev_err(priv->netdev, "Unknow error (flags: 0x%02x)\n",
> > + msg->u.rx_can.flag);
> > +
> > + stats->rx_errors++;
> > + return;
> > + }
> > +
> > + if (msg->u.rx_can.flag & MSG_FLAG_OVERRUN) {
> > + skb = alloc_can_err_skb(priv->netdev, &cf);
> > + if (!skb) {
> > + stats->tx_dropped++;
>
> Should be rx, as we are in the rx function.
Ok I'll fix that.
>
> > + return;
> > + }
> > +
> > + cf->can_id |= CAN_ERR_CRTL;
> > + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
> > +
> > + stats->rx_over_errors++;
> > + stats->rx_errors++;
> > +
> > + netif_rx(skb);
> > +
> > + stats->rx_packets++;
> > + stats->rx_bytes += cf->can_dlc;
> > + }
> > +}
> > +
> > +static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
> > + const struct kvaser_msg *msg)
> > +{
> > + struct kvaser_usb_net_priv *priv;
> > + struct can_frame *cf;
> > + struct sk_buff *skb;
> > + struct net_device_stats *stats;
> > + u8 channel = msg->u.rx_can.channel;
> > +
> > + if (channel >= dev->nchannels) {
> > + dev_err(dev->udev->dev.parent,
> > + "Invalid channel number (%d)\n", channel);
> > + return;
> > + }
> > +
> > + priv = dev->nets[channel];
> > + stats = &priv->netdev->stats;
> > +
> > + if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME | MSG_FLAG_NERR |
> > + MSG_FLAG_OVERRUN)) {
> > + kvaser_usb_rx_can_err(priv, msg);
> > + return;
> > + } else if (msg->u.rx_can.flag & ~MSG_FLAG_REMOTE_FRAME) {
> > + netdev_warn(priv->netdev,
> > + "Unhandled frame (flags: 0x%02x)",
> > + msg->u.rx_can.flag);
> > + return;
> > + }
> > +
> > + skb = alloc_can_skb(priv->netdev, &cf);
> > + if (!skb) {
> > + stats->tx_dropped++;
> > + return;
> > + }
> > +
> > + cf->can_id = ((msg->u.rx_can.msg[0] & 0x1f) << 6) |
> > + (msg->u.rx_can.msg[1] & 0x3f);
> > + cf->can_dlc = get_can_dlc(msg->u.rx_can.msg[5]);
> > +
> > + if (msg->id == CMD_RX_EXT_MESSAGE) {
> > + cf->can_id <<= 18;
> > + cf->can_id |= ((msg->u.rx_can.msg[2] & 0x0f) << 14) |
> > + ((msg->u.rx_can.msg[3] & 0xff) << 6) |
> > + (msg->u.rx_can.msg[4] & 0x3f);
> > + cf->can_id |= CAN_EFF_FLAG;
> > + }
> > +
> > + if (msg->u.rx_can.flag & MSG_FLAG_REMOTE_FRAME)
> > + cf->can_id |= CAN_RTR_FLAG;
> > + else
> > + memcpy(cf->data, &msg->u.rx_can.msg[6], cf->can_dlc);
> > +
> > + netif_rx(skb);
> > +
> > + stats->rx_packets++;
> > + stats->rx_bytes += cf->can_dlc;
> > +}
> > +
> > +static void kvaser_usb_start_chip_reply(const struct kvaser_usb *dev,
> > + const struct kvaser_msg *msg)
> > +{
> > + struct kvaser_usb_net_priv *priv;
> > + u8 channel = msg->u.simple.channel;
> > +
> > + if (channel >= dev->nchannels) {
> > + dev_err(dev->udev->dev.parent,
> > + "Invalid channel number (%d)\n", channel);
> > + return;
> > + }
> > +
> > + priv = dev->nets[channel];
> > +
> > + if (completion_done(&priv->start_comp) &&
> > + netif_queue_stopped(priv->netdev)) {
> > + netif_wake_queue(priv->netdev);
> > + } else {
> > + netif_start_queue(priv->netdev);
> > + complete(&priv->start_comp);
> > + }
> > +}
> > +
> > +static void kvaser_usb_stop_chip_reply(const struct kvaser_usb *dev,
> > + const struct kvaser_msg *msg)
> > +{
> > + struct kvaser_usb_net_priv *priv;
> > + u8 channel = msg->u.simple.channel;
> > +
> > + if (channel >= dev->nchannels) {
> > + dev_err(dev->udev->dev.parent,
> > + "Invalid channel number (%d)\n", channel);
> > + return;
> > + }
> > +
> > + priv = dev->nets[channel];
> > +
> > + complete(&priv->stop_comp);
> > +}
> > +
> > +static void kvaser_usb_handle_message(const struct kvaser_usb *dev,
> > + const struct kvaser_msg *msg)
> > +{
> > + switch (msg->id) {
> > + case CMD_START_CHIP_REPLY:
> > + kvaser_usb_start_chip_reply(dev, msg);
> > + break;
> > +
> > + case CMD_STOP_CHIP_REPLY:
> > + kvaser_usb_stop_chip_reply(dev, msg);
> > + break;
> > +
> > + case CMD_RX_STD_MESSAGE:
> > + case CMD_RX_EXT_MESSAGE:
> > + kvaser_usb_rx_can_msg(dev, msg);
> > + break;
> > +
> > + case CMD_CHIP_STATE_EVENT:
> > + case CMD_CAN_ERROR_EVENT:
> > + kvaser_usb_rx_error(dev, msg);
> > + break;
> > +
> > + case CMD_LOG_MESSAGE:
> > + if (msg->u.log_message.flags & MSG_FLAG_ERROR_FRAME)
> > + kvaser_usb_rx_error(dev, msg);
> > + break;
> > +
> > + case CMD_TX_ACKNOWLEDGE:
> > + kvaser_usb_tx_acknowledge(dev, msg);
> > + break;
> > +
> > + default:
> > + dev_warn(dev->udev->dev.parent,
> > + "Unhandled message (%d)\n", msg->id);
> > + break;
> > + }
> > +}
> > +
> > +static void kvaser_usb_read_bulk_callback(struct urb *urb)
> > +{
> > + struct kvaser_usb *dev = urb->context;
> > + struct kvaser_msg *msg;
> > + int pos = 0;
> > + int err, i;
> > +
> > + switch (urb->status) {
> > + case 0:
> > + break;
> > + case -ENOENT:
> > + case -ESHUTDOWN:
> > + return;
> > + default:
> > + dev_info(dev->udev->dev.parent, "Rx URB aborted (%d)\n",
> > + urb->status);
> > + goto resubmit_urb;
> > + }
> > +
> > + while (pos <= urb->actual_length - MSG_HEADER_LEN) {
> > + msg = urb->transfer_buffer + pos;
> > +
> > + if (!msg->len)
> > + break;
> > +
> > + if (pos + msg->len > urb->actual_length) {
> > + dev_err(dev->udev->dev.parent, "Format error\n");
> > + break;
> > + }
> > +
> > + kvaser_usb_handle_message(dev, msg);
> > +
> > + pos += msg->len;
> > + }
> > +
> > +resubmit_urb:
> > + usb_fill_bulk_urb(urb, dev->udev,
> > + usb_rcvbulkpipe(dev->udev,
> > + dev->bulk_in->bEndpointAddress),
> > + urb->transfer_buffer, RX_BUFFER_SIZE,
> > + kvaser_usb_read_bulk_callback, dev);
> > +
> > + err = usb_submit_urb(urb, GFP_ATOMIC);
> > + if (err == -ENODEV) {
> > + for (i = 0; i < dev->nchannels; i++) {
> > + if (!dev->nets[i])
> > + continue;
> > +
> > + netif_device_detach(dev->nets[i]->netdev);
> > + }
> > + } else if (err) {
> > + dev_err(dev->udev->dev.parent,
> > + "Failed resubmitting read bulk urb: %d\n", err);
> > + }
> > +
> > + return;
> > +}
> > +
> > +static int kvaser_usb_setup_rx_urbs(struct kvaser_usb *dev)
> > +{
> > + int i, err = 0;
> > +
> > + if (dev->rxinitdone)
> > + return 0;
> > +
> > + for (i = 0; i < MAX_RX_URBS; i++) {
> > + struct urb *urb = NULL;
> > + u8 *buf = NULL;
> > + dma_addr_t buf_dma;
> > +
> > + urb = usb_alloc_urb(0, GFP_KERNEL);
> > + if (!urb) {
> > + dev_warn(dev->udev->dev.parent,
> > + "No memory left for URBs\n");
> > + err = -ENOMEM;
> > + break;
> > + }
> > +
> > + buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE,
> > + GFP_KERNEL, &buf_dma);
> > + if (!buf) {
> > + dev_warn(dev->udev->dev.parent,
> > + "No memory left for USB buffer\n");
> > + usb_free_urb(urb);
> > + err = -ENOMEM;
> > + break;
> > + }
> > +
> > + usb_fill_bulk_urb(urb, dev->udev,
> > + usb_rcvbulkpipe(dev->udev,
> > + dev->bulk_in->bEndpointAddress),
> > + buf, RX_BUFFER_SIZE,
> > + kvaser_usb_read_bulk_callback,
> > + dev);
> > + urb->transfer_dma = buf_dma;
> > + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
> > + usb_anchor_urb(urb, &dev->rx_submitted);
> > +
> > + err = usb_submit_urb(urb, GFP_KERNEL);
> > + if (err) {
> > + usb_unanchor_urb(urb);
> > + usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
> > + buf_dma);
> > + usb_free_urb(urb);
> > + break;
> > + }
> > +
> > + dev->rxbuf[i] = buf;
> > + dev->rxbuf_dma[i] = buf_dma;
> > +
> > + usb_free_urb(urb);
> > + }
> > +
> > + if (i == 0) {
> > + dev_warn(dev->udev->dev.parent,
> > + "Cannot setup read URBs, error %d\n", err);
> > + return err;
> > + } else if (i < MAX_RX_URBS) {
> > + dev_warn(dev->udev->dev.parent,
> > + "RX performances may be slow\n");
> > + }
> > +
> > + dev->rxinitdone = true;
> > +
> > + return 0;
> > +}
> > +
> > +static int kvaser_usb_set_opt_mode(const struct kvaser_usb_net_priv *priv)
> > +{
> > + struct kvaser_msg msg = {
> > + .id = CMD_SET_CTRL_MODE,
> > + .len = MSG_HEADER_LEN +
> > + sizeof(struct kvaser_msg_ctrl_mode),
> > + .u.ctrl_mode.tid = 0xff,
> > + .u.ctrl_mode.channel = priv->channel,
> > + };
> > +
> > + if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
> > + msg.u.ctrl_mode.ctrl_mode = KVASER_CTRL_MODE_SILENT;
> > + else
> > + msg.u.ctrl_mode.ctrl_mode = KVASER_CTRL_MODE_NORMAL;
> > +
> > + return kvaser_usb_send_msg(priv->dev, &msg);
> > +}
> > +
> > +static int kvaser_usb_start_chip(struct kvaser_usb_net_priv *priv)
> > +{
> > + int err;
> > +
> > + init_completion(&priv->start_comp);
> > +
> > + err = kvaser_usb_send_simple_msg(priv->dev, CMD_START_CHIP,
> > + priv->channel);
> > + if (err)
> > + return err;
> > +
> > + if (!wait_for_completion_timeout(&priv->start_comp,
> > + msecs_to_jiffies(START_TIMEOUT)))
> > + return -ETIMEDOUT;
> > +
> > + return 0;
> > +}
> > +
> > +static int kvaser_usb_open(struct net_device *netdev)
> > +{
> > + struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
> > + struct kvaser_usb *dev = priv->dev;
> > + int err;
> > +
> > + err = open_candev(netdev);
> > + if (err)
> > + return err;
> > +
> > + err = kvaser_usb_setup_rx_urbs(dev);
> > + if (err)
> > + goto error;
> > +
> > + err = kvaser_usb_set_opt_mode(priv);
> > + if (err)
> > + goto error;
> > +
> > + err = kvaser_usb_start_chip(priv);
> > + if (err) {
> > + netdev_warn(netdev, "Cannot start device, error %d\n", err);
> > + goto error;
> > + }
> > +
> > + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> > +
> > + return 0;
> > +
> > +error:
> > + close_candev(netdev);
> > + return err;
> > +}
> > +
> > +static void kvaser_usb_unlink_all_urbs(struct kvaser_usb *dev)
> > +{
> > + int i;
> > +
> > + usb_kill_anchored_urbs(&dev->rx_submitted);
> > +
> > + for (i = 0; i < MAX_RX_URBS; i++)
> > + usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
> > + dev->rxbuf[i],
> > + dev->rxbuf_dma[i]);
> > +
> > + for (i = 0; i < MAX_NET_DEVICES; i++) {
> > + struct kvaser_usb_net_priv *priv = dev->nets[i];
> > +
> > + if (priv)
> > + kvaser_usb_unlink_tx_urbs(priv);
> > + }
> > +}
> > +
> > +static int kvaser_usb_stop_chip(struct kvaser_usb_net_priv *priv)
> > +{
> > + int err;
> > +
> > + init_completion(&priv->stop_comp);
> > +
> > + err = kvaser_usb_send_simple_msg(priv->dev, CMD_STOP_CHIP,
> > + priv->channel);
> > + if (err)
> > + return err;
> > +
> > + if (!wait_for_completion_timeout(&priv->stop_comp,
> > + msecs_to_jiffies(STOP_TIMEOUT)))
> > + return -ETIMEDOUT;
> > +
> > + return 0;
> > +}
> > +
> > +static int kvaser_usb_flush_queue(struct kvaser_usb_net_priv *priv)
> > +{
> > + struct kvaser_msg msg = {
> > + .id = CMD_FLUSH_QUEUE,
> > + .len = MSG_HEADER_LEN +
> > + sizeof(struct kvaser_msg_flush_queue),
> > + .u.flush_queue.channel = priv->channel,
> > + .u.flush_queue.flags = 0x00,
> > + };
> > +
> > + return kvaser_usb_send_msg(priv->dev, &msg);
> > +}
> > +
> > +static int kvaser_usb_close(struct net_device *netdev)
> > +{
> > + struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
> > + struct kvaser_usb *dev = priv->dev;
> > + int err;
> > +
> > + netif_stop_queue(netdev);
> > +
> > + err = kvaser_usb_flush_queue(priv);
> > + if (err)
> > + netdev_warn(netdev, "Cannot flush queue, error %d\n", err);
> > +
> > + if (kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel))
> > + netdev_warn(netdev, "Cannot reset card, error %d\n", err);
> > +
> > + err = kvaser_usb_stop_chip(priv);
> > + if (err)
> > + netdev_warn(netdev, "Cannot stop device, error %d\n", err);
> > +
> > + priv->can.state = CAN_STATE_STOPPED;
> > + close_candev(priv->netdev);
> > +
> > + return 0;
> > +}
> > +
> > +static void kvaser_usb_write_bulk_callback(struct urb *urb)
> > +{
> > + struct kvaser_usb_tx_urb_context *context = urb->context;
> > + struct kvaser_usb_net_priv *priv;
> > + struct net_device *netdev;
> > +
> > + if (WARN_ON(!context))
> > + return;
> > +
> > + priv = context->priv;
> > + netdev = priv->netdev;
> > +
> > + kfree(urb->transfer_buffer);
> > +
> > + if (!netif_device_present(netdev))
> > + return;
> > +
> > + if (urb->status)
> > + netdev_info(netdev, "Tx URB aborted (%d)\n", urb->status);
> > +}
> > +
> > +static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
> > + struct net_device *netdev)
> > +{
> > + struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
> > + struct kvaser_usb *dev = priv->dev;
> > + struct net_device_stats *stats = &netdev->stats;
> > + struct can_frame *cf = (struct can_frame *)skb->data;
> > + struct kvaser_usb_tx_urb_context *context = NULL;
> > + struct urb *urb;
> > + void *buf;
> > + struct kvaser_msg *msg;
> > + int i, err;
> > + int ret = NETDEV_TX_OK;
> > +
> > + if (can_dropped_invalid_skb(netdev, skb))
> > + return NETDEV_TX_OK;
> > +
> > + urb = usb_alloc_urb(0, GFP_ATOMIC);
> > + if (!urb) {
> > + netdev_err(netdev, "No memory left for URBs\n");
> > + stats->tx_dropped++;
>
> Move the dev_kfree_skb to the end and goto there.
I assume you mean doing something like that at the end of the function:
releasebuf:
kfree(buf);
nobufmem:
usb_free_urb(urb);
nourbmem:
dev_kfree_skb(skb);
return ret;
If I do that it will give problems when the 'releasebuf' condition is
reached. The skb buffer will be freed twice. The skb is already freed
by the function can_free_echo_skb().
>
> > + dev_kfree_skb(skb);
> > + return NETDEV_TX_OK;
> > + }
> > +
> > + buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
> > + if (!buf) {
> > + netdev_err(netdev, "No memory left for USB buffer\n");
> > + stats->tx_dropped++;
> You cann usb_free_urb twice...here and in the error handling at the end.
Indeed thanks.
>
> > + dev_kfree_skb(skb);
> > + usb_free_urb(urb);
> > + goto nobufmem;
> > + }
> > +
> > + msg = buf;
> > + msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_tx_can);
> > + msg->u.tx_can.flags = 0;
> > + msg->u.tx_can.channel = priv->channel;
> > +
> > + if (cf->can_id & CAN_EFF_FLAG) {
> > + msg->id = CMD_TX_EXT_MESSAGE;
> > + msg->u.tx_can.msg[0] = (cf->can_id >> 24) & 0x1f;
> > + msg->u.tx_can.msg[1] = (cf->can_id >> 18) & 0x3f;
> > + msg->u.tx_can.msg[2] = (cf->can_id >> 14) & 0x0f;
> > + msg->u.tx_can.msg[3] = (cf->can_id >> 6) & 0xff;
> > + msg->u.tx_can.msg[4] = cf->can_id & 0x3f;
> > + } else {
> > + msg->id = CMD_TX_STD_MESSAGE;
> > + msg->u.tx_can.msg[0] = (cf->can_id >> 6) & 0x1f;
> > + msg->u.tx_can.msg[1] = cf->can_id & 0x3f;
> > + }
> > +
> > + msg->u.tx_can.msg[5] = cf->can_dlc;
> > + memcpy(&msg->u.tx_can.msg[6], cf->data, cf->can_dlc);
> > +
> > + if (cf->can_id & CAN_RTR_FLAG)
> > + msg->u.tx_can.flags |= MSG_FLAG_REMOTE_FRAME;
> > +
> > + for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++) {
> > + if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
> > + context = &priv->tx_contexts[i];
> > + break;
> > + }
> > + }
> > +
> > + if (!context) {
> > + netdev_warn(netdev, "cannot find free context\n");
> > + ret = NETDEV_TX_BUSY;
> > + goto releasebuf;
> > + }
> > +
> > + context->priv = priv;
> > + context->echo_index = i;
> > + context->dlc = cf->can_dlc;
> > +
> > + msg->u.tx_can.tid = context->echo_index;
> > +
> > + usb_fill_bulk_urb(urb, dev->udev,
> > + usb_sndbulkpipe(dev->udev,
> > + dev->bulk_out->bEndpointAddress),
> > + buf, msg->len,
> > + kvaser_usb_write_bulk_callback, context);
> > + usb_anchor_urb(urb, &priv->tx_submitted);
> > +
> > + can_put_echo_skb(skb, netdev, context->echo_index);
> > +
> > + atomic_inc(&priv->active_tx_urbs);
> > +
> > + if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
> > + netif_stop_queue(netdev);
> > +
> > + err = usb_submit_urb(urb, GFP_ATOMIC);
> > + if (unlikely(err)) {
> > + can_free_echo_skb(netdev, context->echo_index);
> > +
> > + atomic_dec(&priv->active_tx_urbs);
> > + usb_unanchor_urb(urb);
> > +
> > + stats->tx_dropped++;
> > +
> > + if (err == -ENODEV)
> > + netif_device_detach(netdev);
> > + else
> > + netdev_warn(netdev, "Failed tx_urb %d\n", err);
> > +
> > + goto releasebuf;
> > + }
> > +
> > + usb_free_urb(urb);
> > +
> > + return NETDEV_TX_OK;
> > +
> > +releasebuf:
> > + kfree(buf);
> > +nobufmem:
> > + usb_free_urb(urb);
> > + return ret;
> > +}
> > +
> > +static const struct net_device_ops kvaser_usb_netdev_ops = {
> > + .ndo_open = kvaser_usb_open,
> > + .ndo_stop = kvaser_usb_close,
> > + .ndo_start_xmit = kvaser_usb_start_xmit,
> > +};
> > +
> > +static struct can_bittiming_const kvaser_usb_bittiming_const = {
> > + .name = "kvaser_usb",
> > + .tseg1_min = KVASER_USB_TSEG1_MIN,
> > + .tseg1_max = KVASER_USB_TSEG1_MAX,
> > + .tseg2_min = KVASER_USB_TSEG2_MIN,
> > + .tseg2_max = KVASER_USB_TSEG2_MAX,
> > + .sjw_max = KVASER_USB_SJW_MAX,
> > + .brp_min = KVASER_USB_BRP_MIN,
> > + .brp_max = KVASER_USB_BRP_MAX,
> > + .brp_inc = KVASER_USB_BRP_INC,
> > +};
> > +
> > +static int kvaser_usb_set_bittiming(struct net_device *netdev)
> > +{
> > + struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
> > + struct can_bittiming *bt = &priv->can.bittiming;
> > + struct kvaser_usb *dev = priv->dev;
> > + struct kvaser_msg msg = {
> > + .id = CMD_SET_BUS_PARAMS,
> > + .len = MSG_HEADER_LEN +
> > + sizeof(struct kvaser_msg_busparams),
> > + .u.busparams.channel = priv->channel,
> > + .u.busparams.tid = 0xff,
> > + .u.busparams.bitrate = cpu_to_le32(bt->bitrate),
> > + .u.busparams.sjw = bt->sjw,
> > + .u.busparams.tseg1 = bt->prop_seg + bt->phase_seg1,
> > + .u.busparams.tseg2 = bt->phase_seg2,
> > + };
> > +
> > + if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
> > + msg.u.busparams.no_samp = 3;
> > + else
> > + msg.u.busparams.no_samp = 1;
> > +
> > + return kvaser_usb_send_msg(dev, &msg);
> > +}
> > +
> > +static int kvaser_usb_set_mode(struct net_device *netdev,
> > + enum can_mode mode)
> > +{
> > + struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
> > + int err;
> > +
> > + switch (mode) {
> > + case CAN_MODE_START:
> > + err = kvaser_usb_simple_msg_async(priv, CMD_START_CHIP);
> > + if (err)
> > + return err;
> > + break;
> > + default:
> > + return -EOPNOTSUPP;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int kvaser_usb_get_berr_counter(const struct net_device *netdev,
> > + struct can_berr_counter *bec)
> > +{
> > + struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
> > +
> > + *bec = priv->bec;
> > +
> > + return 0;
> > +}
> > +
> > +static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev)
> > +{
> > + int i;
> > +
> > + for (i = 0; i < dev->nchannels; i++) {
> > + if (!dev->nets[i])
> > + continue;
> > +
> > + unregister_netdev(dev->nets[i]->netdev);
> > + }
> > +
> > + kvaser_usb_unlink_all_urbs(dev);
> > +
> > + for (i = 0; i < dev->nchannels; i++) {
> > + if (!dev->nets[i])
> > + continue;
> > +
> > + free_candev(dev->nets[i]->netdev);
> > + }
> > +}
> > +
> > +static int kvaser_usb_init_one(struct usb_interface *intf,
> > + const struct usb_device_id *id, int channel)
> > +{
> > + struct kvaser_usb *dev = usb_get_intfdata(intf);
> > + struct net_device *netdev;
> > + struct kvaser_usb_net_priv *priv;
> > + int i, err;
> > +
> > + netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
> > + if (!netdev) {
> > + dev_err(&intf->dev, "Cannot alloc candev\n");
> > + return -ENOMEM;
> > + }
> > +
> > + priv = netdev_priv(netdev);
> > +
> > + init_completion(&priv->start_comp);
> > + init_completion(&priv->stop_comp);
> > +
> > + init_usb_anchor(&priv->tx_submitted);
> > + atomic_set(&priv->active_tx_urbs, 0);
> > +
> > + for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++)
> > + priv->tx_contexts[i].echo_index = MAX_TX_URBS;
> > +
> > + priv->dev = dev;
> > + priv->netdev = netdev;
> > + priv->channel = channel;
> > +
> > + priv->can.state = CAN_STATE_STOPPED;
> > + priv->can.clock.freq = CAN_USB_CLOCK;
> > + priv->can.bittiming_const = &kvaser_usb_bittiming_const;
> > + priv->can.do_set_bittiming = kvaser_usb_set_bittiming;
> > + priv->can.do_set_mode = kvaser_usb_set_mode;
> > + if (id->driver_info & KVASER_HAS_TXRX_ERRORS)
> > + priv->can.do_get_berr_counter = kvaser_usb_get_berr_counter;
> > + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
> > + if (id->driver_info & KVASER_HAS_SILENT_MODE)
> > + priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
> > +
> > + netdev->flags |= IFF_ECHO;
> > +
> > + netdev->netdev_ops = &kvaser_usb_netdev_ops;
> > +
> > + SET_NETDEV_DEV(netdev, &intf->dev);
> > +
> > + dev->nets[channel] = priv;
> > +
> > + err = register_candev(netdev);
> > + if (err) {
> > + dev_err(&intf->dev, "Failed to register can device\n");
> > + free_candev(netdev);
> > + dev->nets[channel] = NULL;
> > + return err;
> > + }
> > +
> > + netdev_dbg(netdev, "device registered\n");
> > +
> > + return 0;
> > +}
> > +
> > +static void kvaser_usb_get_endpoints(const struct usb_interface *intf,
> > + struct usb_endpoint_descriptor **in,
> > + struct usb_endpoint_descriptor **out)
> > +{
> > + const struct usb_host_interface *iface_desc;
> > + struct usb_endpoint_descriptor *endpoint;
> > + int i;
> > +
> > + iface_desc = &intf->altsetting[0];
> > +
> > + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
> > + endpoint = &iface_desc->endpoint[i].desc;
> > +
> > + if (usb_endpoint_is_bulk_in(endpoint))
> > + *in = endpoint;
> > +
> > + if (usb_endpoint_is_bulk_out(endpoint))
> > + *out = endpoint;
> > + }
> > +}
> > +
> > +static int kvaser_usb_probe(struct usb_interface *intf,
> > + const struct usb_device_id *id)
> > +{
> > + struct kvaser_usb *dev;
> > + int err = -ENOMEM;
> > + int i;
> > +
> > + dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL);
> > + if (!dev)
> > + return -ENOMEM;
> > +
> > + kvaser_usb_get_endpoints(intf, &dev->bulk_in, &dev->bulk_out);
> > + if (!dev->bulk_in || !dev->bulk_out) {
> > + dev_err(&intf->dev, "Cannot get usb endpoint(s)");
> > + return err;
> > + }
> > +
> > + dev->udev = interface_to_usbdev(intf);
> > +
> > + init_usb_anchor(&dev->rx_submitted);
> > +
> > + usb_set_intfdata(intf, dev);
> > +
> > + for (i = 0; i < MAX_NET_DEVICES; i++)
> > + kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, i);
> > +
> > + err = kvaser_usb_get_software_info(dev);
> > + if (err) {
> > + dev_err(&intf->dev,
> > + "Cannot get software infos, error %d\n", err);
> > + return err;
> > + }
> > +
> > + err = kvaser_usb_get_card_info(dev);
> > + if (err) {
> > + dev_err(&intf->dev,
> > + "Cannot get card infos, error %d\n", err);
> > + return err;
> > + }
> > +
> > + dev_dbg(&intf->dev, "Firmware version: %d.%d.%d\n",
> > + ((dev->fw_version >> 24) & 0xff),
> > + ((dev->fw_version >> 16) & 0xff),
> > + (dev->fw_version & 0xffff));
> > +
> > + for (i = 0; i < dev->nchannels; i++) {
> > + err = kvaser_usb_init_one(intf, id, i);
> > + if (err) {
> > + kvaser_usb_remove_interfaces(dev);
> > + return err;
> > + }
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void kvaser_usb_disconnect(struct usb_interface *intf)
> > +{
> > + struct kvaser_usb *dev = usb_get_intfdata(intf);
> > +
> > + usb_set_intfdata(intf, NULL);
> > +
> > + if (!dev)
> > + return;
> > +
> > + kvaser_usb_remove_interfaces(dev);
> > +}
> > +
> > +static struct usb_driver kvaser_usb_driver = {
> > + .name = "kvaser_usb",
> > + .probe = kvaser_usb_probe,
> > + .disconnect = kvaser_usb_disconnect,
> > + .id_table = kvaser_usb_table
> ^^^
> nitpick, please add a "," there.
Ok.
> > +};
> >
> can you please add MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
It is already present just after the kvaser_usb_table structure.
>
> > +module_usb_driver(kvaser_usb_driver);
> > +
> > +MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>");
> > +MODULE_DESCRIPTION("CAN driver for Kvaser CAN/USB devices");
> > +MODULE_LICENSE("GPL v2");
> >
>
> Marc
> --
> Pengutronix e.K. | Marc Kleine-Budde |
> Industrial Linux Solutions | Phone: +49-231-2826-924 |
> Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
> Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
>
Thank you,
--
Olivier
^ permalink raw reply
* Re: [PATCH 4/7] netprio_cgroup: reimplement priomap expansion
From: Daniel Wagner @ 2012-11-20 8:46 UTC (permalink / raw)
To: Tejun Heo
Cc: serge.hallyn-Z7WLFzj8eWMS+FvcfC7Uqw,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, nhorman-2XuSBdqkA4R54TAoqtyWWQ,
tgraf-G/eBtMaohhA, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
lizefan-hv44wF8Li93QT0dZR+AlfA, cgroups-u79uwXL29TY76Z2rM5mHXA,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1353400211-5182-5-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Hi Tejun,
On 20.11.2012 09:30, Tejun Heo wrote:
> netprio kept track of the highest prioidx allocated and resized
> priomaps accordingly when necessary. This makes it necessary to keep
> track of prioidx allocation and may end up resizing on every new
> prioidx.
>
> Update extend_netdev_table() such that it takes @target_idx which the
> priomap should be able to accomodate. If the priomap is large enough,
> nothing happens; otherwise, the size is doubled until @target_idx can
> be accomodated.
>
> This makes max_prioidx and write_update_netdev_table() unnecessary.
> write_priomap() now calls extend_netdev_table() directly.
>
> Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Acked-by: Neil Horman <nhorman-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
> ---
> net/core/netprio_cgroup.c | 56 ++++++++++++++++++++++++++++-------------------
> 1 file changed, 33 insertions(+), 23 deletions(-)
>
> diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c
> index 92cc54c..569d83d 100644
> --- a/net/core/netprio_cgroup.c
> +++ b/net/core/netprio_cgroup.c
> @@ -27,11 +27,11 @@
>
> #include <linux/fdtable.h>
>
> +#define PRIOMAP_MIN_SZ 128
> #define PRIOIDX_SZ 128
>
> static unsigned long prioidx_map[PRIOIDX_SZ];
> static DEFINE_SPINLOCK(prioidx_map_lock);
> -static atomic_t max_prioidx = ATOMIC_INIT(0);
>
> static inline struct cgroup_netprio_state *cgrp_netprio_state(struct cgroup *cgrp)
> {
> @@ -51,8 +51,6 @@ static int get_prioidx(u32 *prio)
> return -ENOSPC;
> }
> set_bit(prioidx, prioidx_map);
> - if (atomic_read(&max_prioidx) < prioidx)
> - atomic_set(&max_prioidx, prioidx);
> spin_unlock_irqrestore(&prioidx_map_lock, flags);
> *prio = prioidx;
> return 0;
> @@ -67,15 +65,40 @@ static void put_prioidx(u32 idx)
> spin_unlock_irqrestore(&prioidx_map_lock, flags);
> }
>
> -static int extend_netdev_table(struct net_device *dev, u32 new_len)
> +/*
> + * Extend @dev->priomap so that it's large enough to accomodate
> + * @target_idx. @dev->priomap.priomap_len > @target_idx after successful
> + * return. Must be called under rtnl lock.
> + */
> +static int extend_netdev_table(struct net_device *dev, u32 target_idx)
> {
> - size_t new_size = sizeof(struct netprio_map) +
> - ((sizeof(u32) * new_len));
> - struct netprio_map *new = kzalloc(new_size, GFP_KERNEL);
> - struct netprio_map *old;
> + struct netprio_map *old, *new;
> + size_t new_sz, new_len;
>
> + /* is the existing priomap large enough? */
> old = rtnl_dereference(dev->priomap);
> + if (old && old->priomap_len > target_idx)
> + return 0;
> +
> + /*
> + * Determine the new size. Let's keep it power-of-two. We start
> + * from PRIOMAP_MIN_SZ and double it until it's large enough to
> + * accommodate @target_idx.
> + */
> + new_sz = PRIOMAP_MIN_SZ;
> + while (true) {
> + new_len = (new_sz - offsetof(struct netprio_map, priomap)) /
> + sizeof(new->priomap[0]);
> + if (new_len > target_idx)
> + break;
> + new_sz *= 2;
> + /* overflowed? */
> + if (WARN_ON(new_sz < PRIOMAP_MIN_SZ))
> + return -ENOSPC;
> + }
>
> + /* allocate & copy */
> + new = kzalloc(new_sz, GFP_KERNEL);
> if (!new) {
> pr_warn("Unable to alloc new priomap!\n");
> return -ENOMEM;
> @@ -87,26 +110,13 @@ static int extend_netdev_table(struct net_device *dev, u32 new_len)
>
> new->priomap_len = new_len;
>
> + /* install the new priomap */
> rcu_assign_pointer(dev->priomap, new);
> if (old)
> kfree_rcu(old, rcu);
> return 0;
> }
Okay, I might be just to stupid to see the beauty in what you are doing. So
please bear with me when I ask these question.
struct netprio_map {
struct rcu_head rcu;
struct netprio_aux *aux; /* auxiliary config array */
u32 priomap_len;
u32 priomap[];
};
Is there a specific reason why aux and priomap is handled differently? Couldn't you
just use same approach for both variables, e.g. re/allocating only them here and
leave the allocation struct netprio_map in cgrp_css_alloc()?
Also the algorithm to figure out the size of the array might be a bit too aggressive
in my opinion. So you always start at PRIOMAP_MIN_SIZE and then try to double
the size until target_idx fits. Wouldn't it make sense to start to look
for the new size beginning at old->priomap_len and then do the power-of-two
increase?
cheers,
daniel
^ permalink raw reply
* [Suggestion] net/netfilter: strcpy for timeout->name
From: Chen Gang @ 2012-11-20 8:47 UTC (permalink / raw)
To: Xue Ying, David Miller; +Cc: Shan Wei, Eric Dumazet, netdev
In-Reply-To: <50AB12EE.6050802@gmail.com>
Hello Xue Ying, David Miller:
Please help checking net/netfilter/nfnetlink_cttimeout.c:
I suggest, we use strncpy instead of strcpy at line 143.
just like we have already used strncmp at line 94.
after checking the calling work flow:
the length of nla_data(cda[CTA_TIMEOUT_NAME]) is not limited in server side.
one of calling work flows is:
netlink_unicast -> netlink_unicast_kernel -> nfnetlink_rcv -> netlink_rcv_skb
-> nfnetlink_rcv_msg -> cttimeout_new_timeout
thanks.
gchen.
70 static int
71 cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,
72 const struct nlmsghdr *nlh,
73 const struct nlattr * const cda[])
74 {
75 __u16 l3num;
76 __u8 l4num;
77 struct nf_conntrack_l4proto *l4proto;
78 struct ctnl_timeout *timeout, *matching = NULL;
79 struct net *net = sock_net(skb->sk);
80 char *name;
81 int ret;
82
83 if (!cda[CTA_TIMEOUT_NAME] ||
84 !cda[CTA_TIMEOUT_L3PROTO] ||
85 !cda[CTA_TIMEOUT_L4PROTO] ||
86 !cda[CTA_TIMEOUT_DATA])
87 return -EINVAL;
88
89 name = nla_data(cda[CTA_TIMEOUT_NAME]);
90 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
91 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
92
93 list_for_each_entry(timeout, &cttimeout_list, head) {
94 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
95 continue;
96
97 if (nlh->nlmsg_flags & NLM_F_EXCL)
98 return -EEXIST;
99
100 matching = timeout;
101 break;
102 }
103
104 l4proto = nf_ct_l4proto_find_get(l3num, l4num);
105
106 /* This protocol is not supportted, skip. */
107 if (l4proto->l4proto != l4num) {
108 ret = -EOPNOTSUPP;
109 goto err_proto_put;
110 }
111
112 if (matching) {
113 if (nlh->nlmsg_flags & NLM_F_REPLACE) {
114 /* You cannot replace one timeout policy by another of
115 * different kind, sorry.
116 */
117 if (matching->l3num != l3num ||
118 matching->l4proto->l4proto != l4num) {
119 ret = -EINVAL;
120 goto err_proto_put;
121 }
122
123 ret = ctnl_timeout_parse_policy(matching, l4proto, net,
124 cda[CTA_TIMEOUT_DATA]);
125 return ret;
126 }
127 ret = -EBUSY;
128 goto err_proto_put;
129 }
130
131 timeout = kzalloc(sizeof(struct ctnl_timeout) +
132 l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
133 if (timeout == NULL) {
134 ret = -ENOMEM;
135 goto err_proto_put;
136 }
137
138 ret = ctnl_timeout_parse_policy(timeout, l4proto, net,
139 cda[CTA_TIMEOUT_DATA]);
140 if (ret < 0)
141 goto err;
142
143 strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
144 timeout->l3num = l3num;
145 timeout->l4proto = l4proto;
146 atomic_set(&timeout->refcnt, 1);
147 list_add_tail_rcu(&timeout->head, &cttimeout_list);
148
149 return 0;
150 err:
151 kfree(timeout);
152 err_proto_put:
153 nf_ct_l4proto_put(l4proto);
154 return ret;
155 }
156
^ permalink raw reply
* [RESEND PATCH net-next 1/1] sit: allow to configure 6rd tunnels via netlink
From: Nicolas Dichtel @ 2012-11-20 8:41 UTC (permalink / raw)
To: davem; +Cc: netdev, shemminger, Nicolas Dichtel
In-Reply-To: <20121120.033405.490869980095149376.davem@davemloft.net>
This patch add the support of 6RD tunnels management via netlink.
Note that netdev_state_change() is now called when 6RD parameters are updated.
6RD parameters are updated only if there is at least one 6RD attribute.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/uapi/linux/if_tunnel.h | 4 ++
net/ipv6/sit.c | 149 ++++++++++++++++++++++++++++++++++-------
2 files changed, 128 insertions(+), 25 deletions(-)
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index 5ab0c8d..aee73d0 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -49,6 +49,10 @@ enum {
IFLA_IPTUN_FLAGS,
IFLA_IPTUN_PROTO,
IFLA_IPTUN_PMTUDISC,
+ IFLA_IPTUN_6RD_PREFIX,
+ IFLA_IPTUN_6RD_RELAY_PREFIX,
+ IFLA_IPTUN_6RD_PREFIXLEN,
+ IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
__IFLA_IPTUN_MAX,
};
#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index fee21c6..80cb382 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -936,6 +936,38 @@ static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p)
netdev_state_change(t->dev);
}
+#ifdef CONFIG_IPV6_SIT_6RD
+static int ipip6_tunnel_update_6rd(struct ip_tunnel *t,
+ struct ip_tunnel_6rd *ip6rd)
+{
+ struct in6_addr prefix;
+ __be32 relay_prefix;
+
+ if (ip6rd->relay_prefixlen > 32 ||
+ ip6rd->prefixlen + (32 - ip6rd->relay_prefixlen) > 64)
+ return -EINVAL;
+
+ ipv6_addr_prefix(&prefix, &ip6rd->prefix, ip6rd->prefixlen);
+ if (!ipv6_addr_equal(&prefix, &ip6rd->prefix))
+ return -EINVAL;
+ if (ip6rd->relay_prefixlen)
+ relay_prefix = ip6rd->relay_prefix &
+ htonl(0xffffffffUL <<
+ (32 - ip6rd->relay_prefixlen));
+ else
+ relay_prefix = 0;
+ if (relay_prefix != ip6rd->relay_prefix)
+ return -EINVAL;
+
+ t->ip6rd.prefix = prefix;
+ t->ip6rd.relay_prefix = relay_prefix;
+ t->ip6rd.prefixlen = ip6rd->prefixlen;
+ t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen;
+ netdev_state_change(t->dev);
+ return 0;
+}
+#endif
+
static int
ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
{
@@ -1105,31 +1137,9 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
t = netdev_priv(dev);
if (cmd != SIOCDEL6RD) {
- struct in6_addr prefix;
- __be32 relay_prefix;
-
- err = -EINVAL;
- if (ip6rd.relay_prefixlen > 32 ||
- ip6rd.prefixlen + (32 - ip6rd.relay_prefixlen) > 64)
- goto done;
-
- ipv6_addr_prefix(&prefix, &ip6rd.prefix,
- ip6rd.prefixlen);
- if (!ipv6_addr_equal(&prefix, &ip6rd.prefix))
+ err = ipip6_tunnel_update_6rd(t, &ip6rd);
+ if (err < 0)
goto done;
- if (ip6rd.relay_prefixlen)
- relay_prefix = ip6rd.relay_prefix &
- htonl(0xffffffffUL <<
- (32 - ip6rd.relay_prefixlen));
- else
- relay_prefix = 0;
- if (relay_prefix != ip6rd.relay_prefix)
- goto done;
-
- t->ip6rd.prefix = prefix;
- t->ip6rd.relay_prefix = relay_prefix;
- t->ip6rd.prefixlen = ip6rd.prefixlen;
- t->ip6rd.relay_prefixlen = ip6rd.relay_prefixlen;
} else
ipip6_tunnel_clone_6rd(dev, sitn);
@@ -1261,11 +1271,53 @@ static void ipip6_netlink_parms(struct nlattr *data[],
parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]);
}
+#ifdef CONFIG_IPV6_SIT_6RD
+/* This function returns true when 6RD attributes are present in the nl msg */
+static bool ipip6_netlink_6rd_parms(struct nlattr *data[],
+ struct ip_tunnel_6rd *ip6rd)
+{
+ bool ret = false;
+ memset(ip6rd, 0, sizeof(*ip6rd));
+
+ if (!data)
+ return ret;
+
+ if (data[IFLA_IPTUN_6RD_PREFIX]) {
+ ret = true;
+ nla_memcpy(&ip6rd->prefix, data[IFLA_IPTUN_6RD_PREFIX],
+ sizeof(struct in6_addr));
+ }
+
+ if (data[IFLA_IPTUN_6RD_RELAY_PREFIX]) {
+ ret = true;
+ ip6rd->relay_prefix =
+ nla_get_be32(data[IFLA_IPTUN_6RD_RELAY_PREFIX]);
+ }
+
+ if (data[IFLA_IPTUN_6RD_PREFIXLEN]) {
+ ret = true;
+ ip6rd->prefixlen = nla_get_u16(data[IFLA_IPTUN_6RD_PREFIXLEN]);
+ }
+
+ if (data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]) {
+ ret = true;
+ ip6rd->relay_prefixlen =
+ nla_get_u16(data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
+ }
+
+ return ret;
+}
+#endif
+
static int ipip6_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
{
struct net *net = dev_net(dev);
struct ip_tunnel *nt;
+#ifdef CONFIG_IPV6_SIT_6RD
+ struct ip_tunnel_6rd ip6rd;
+#endif
+ int err;
nt = netdev_priv(dev);
ipip6_netlink_parms(data, &nt->parms);
@@ -1273,7 +1325,16 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev,
if (ipip6_tunnel_locate(net, &nt->parms, 0))
return -EEXIST;
- return ipip6_tunnel_create(dev);
+ err = ipip6_tunnel_create(dev);
+ if (err < 0)
+ return err;
+
+#ifdef CONFIG_IPV6_SIT_6RD
+ if (ipip6_netlink_6rd_parms(data, &ip6rd))
+ err = ipip6_tunnel_update_6rd(nt, &ip6rd);
+#endif
+
+ return err;
}
static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
@@ -1283,6 +1344,9 @@ static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
struct ip_tunnel_parm p;
struct net *net = dev_net(dev);
struct sit_net *sitn = net_generic(net, sit_net_id);
+#ifdef CONFIG_IPV6_SIT_6RD
+ struct ip_tunnel_6rd ip6rd;
+#endif
if (dev == sitn->fb_tunnel_dev)
return -EINVAL;
@@ -1302,6 +1366,12 @@ static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
t = netdev_priv(dev);
ipip6_tunnel_update(t, &p);
+
+#ifdef CONFIG_IPV6_SIT_6RD
+ if (ipip6_netlink_6rd_parms(data, &ip6rd))
+ return ipip6_tunnel_update_6rd(t, &ip6rd);
+#endif
+
return 0;
}
@@ -1322,6 +1392,16 @@ static size_t ipip6_get_size(const struct net_device *dev)
nla_total_size(1) +
/* IFLA_IPTUN_FLAGS */
nla_total_size(2) +
+#ifdef CONFIG_IPV6_SIT_6RD
+ /* IFLA_IPTUN_6RD_PREFIX */
+ nla_total_size(sizeof(struct in6_addr)) +
+ /* IFLA_IPTUN_6RD_RELAY_PREFIX */
+ nla_total_size(4) +
+ /* IFLA_IPTUN_6RD_PREFIXLEN */
+ nla_total_size(2) +
+ /* IFLA_IPTUN_6RD_RELAY_PREFIXLEN */
+ nla_total_size(2) +
+#endif
0;
}
@@ -1339,6 +1419,19 @@ static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
!!(parm->iph.frag_off & htons(IP_DF))) ||
nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags))
goto nla_put_failure;
+
+#ifdef CONFIG_IPV6_SIT_6RD
+ if (nla_put(skb, IFLA_IPTUN_6RD_PREFIX, sizeof(struct in6_addr),
+ &tunnel->ip6rd.prefix) ||
+ nla_put_be32(skb, IFLA_IPTUN_6RD_RELAY_PREFIX,
+ tunnel->ip6rd.relay_prefix) ||
+ nla_put_u16(skb, IFLA_IPTUN_6RD_PREFIXLEN,
+ tunnel->ip6rd.prefixlen) ||
+ nla_put_u16(skb, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+ tunnel->ip6rd.relay_prefixlen))
+ goto nla_put_failure;
+#endif
+
return 0;
nla_put_failure:
@@ -1353,6 +1446,12 @@ static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = {
[IFLA_IPTUN_TOS] = { .type = NLA_U8 },
[IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
[IFLA_IPTUN_FLAGS] = { .type = NLA_U16 },
+#ifdef CONFIG_IPV6_SIT_6RD
+ [IFLA_IPTUN_6RD_PREFIX] = { .len = sizeof(struct in6_addr) },
+ [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 },
+ [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NLA_U16 },
+ [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 },
+#endif
};
static struct rtnl_link_ops sit_link_ops __read_mostly = {
--
1.7.12
^ permalink raw reply related
* Re: [PATCH 3/7] netprio_cgroup: shorten variable names in extend_netdev_table()
From: Daniel Wagner @ 2012-11-20 8:37 UTC (permalink / raw)
To: Tejun Heo
Cc: nhorman-2XuSBdqkA4R54TAoqtyWWQ, netdev-u79uwXL29TY76Z2rM5mHXA,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, tgraf-G/eBtMaohhA,
cgroups-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <1353400211-5182-4-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
On 20.11.2012 09:30, Tejun Heo wrote:
> The function is about to go through a rewrite. In preparation,
> shorten the variable names so that we don't repeat "priomap" so often.
>
> This patch is cosmetic.
>
> Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Acked-by: Neil Horman <nhorman-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
Tested and Acked-by: Daniel Wagner <daniel.wagner-98C5kh4wR6ohFhg+JK9F0w@public.gmane.org>
^ permalink raw reply
* Re: [PATCH 2/7] netprio_cgroup: simplify write_priomap()
From: Daniel Wagner @ 2012-11-20 8:37 UTC (permalink / raw)
To: Tejun Heo
Cc: nhorman-2XuSBdqkA4R54TAoqtyWWQ, netdev-u79uwXL29TY76Z2rM5mHXA,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, tgraf-G/eBtMaohhA,
cgroups-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <1353400211-5182-3-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
On 20.11.2012 09:30, Tejun Heo wrote:
> sscanf() doesn't bite.
>
> Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Acked-by: Neil Horman <nhorman-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
Tested and Acked-by: Daniel Wagner <daniel.wagner-98C5kh4wR6ohFhg+JK9F0w@public.gmane.org>
^ permalink raw reply
* Re: [PATCH 1/7] netcls_cgroup: move config inheritance to ->css_online() and remove .broken_hierarchy marking
From: Daniel Wagner @ 2012-11-20 8:35 UTC (permalink / raw)
To: Tejun Heo
Cc: nhorman-2XuSBdqkA4R54TAoqtyWWQ, netdev-u79uwXL29TY76Z2rM5mHXA,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, tgraf-G/eBtMaohhA,
cgroups-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <1353400211-5182-2-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
On 20.11.2012 09:30, Tejun Heo wrote:
> It turns out that we'll have to live with attributes which are
> inherited at cgroup creation time but not affected by further updates
> to the parent afterwards - such attributes are already in wide use
> e.g. for cpuset.
>
> So, there's nothing to do for netcls_cgroup for hierarchy support.
> Its current behavior - inherit only during creation - is good enough.
>
> Move config inheriting from ->css_alloc() to ->css_online() for
> consistency, which doesn't change behavior at all, and remove
> .broken_hierarchy marking.
>
> Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Not introducing the 'is_local' is a good thing.
Tested and Acked-by: Daniel Wagner <daniel.wagner-98C5kh4wR6ohFhg+JK9F0w@public.gmane.org>
^ permalink raw reply
* Re: [PATCH net-next 1/4] ipip: allow to deactivate the creation of fb dev
From: David Miller @ 2012-11-20 8:34 UTC (permalink / raw)
To: nicolas.dichtel; +Cc: shemminger, netdev
In-Reply-To: <50AB3F99.7070701@6wind.com>
From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Date: Tue, 20 Nov 2012 09:30:17 +0100
> Le 20/11/2012 01:07, David Miller a écrit :
>> Why not put this aside and submit the other parts of your
>> patch set on their own, since those looked fine to me?
> Ok, no problem. I wanted to get feedback about this kind of idea, I
> understand the point.
>
> When you said "the other parts", you mean only patch 2/4 (sit: allow
> to configure 6rd tunnels via netlink) or 3/4 and 4/4 too?
> Because 3/4 and 4/4 are equivalent to this one.
I meant patch #2.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox