* [PATCH] Re: still having r8169 woes with XID 18000000
From: Timo Teräs @ 2010-06-05 7:39 UTC (permalink / raw)
To: Phil Sutter, françois romieu, netdev
In-Reply-To: <4C09611B.2090805@iki.fi>
On 06/04/2010 11:24 PM, Timo Teräs wrote:
> On 06/04/2010 08:31 PM, Timo Teräs wrote:
> r8169 Gigabit Ethernet driver 2.3LK-NAPI loaded
> r8169 0000:00:09.0: PCI->APIC IRQ transform: INT A -> IRQ 18
> r8169 0000:00:09.0: no PCI Express capability
> eth0: RTL8169sc/8110sc at 0xf835c000, 00:30:18:a6:2b:6c, XID 18000000 IRQ 18
> r8169 Gigabit Ethernet driver 2.3LK-NAPI loaded
> r8169 0000:00:0b.0: PCI->APIC IRQ transform: INT A -> IRQ 19
> r8169 0000:00:0b.0: no PCI Express capability
> eth1: RTL8169sc/8110sc at 0xf8360000, 00:30:18:a6:2b:6d, XID 18000000 IRQ 19
> r8169 Gigabit Ethernet driver 2.3LK-NAPI loaded
> r8169 0000:00:0c.0: PCI->APIC IRQ transform: INT A -> IRQ 16
> r8169 0000:00:0c.0: no PCI Express capability
> eth2: RTL8169sc/8110sc at 0xf8364000, 00:30:18:a6:2b:6e, XID 18000000 IRQ 16
> r8169: mdio_write(f8364000, 0x00000003, 0000000a1) required 2000 cycles
> r8169: mdio_write(f8364000, 0x00000000, 000001000) required 2000 cycles
> r8169: mdio_write(f8364000, 0x00000000, 00000a0ff) required 2000 cycles
> r8169: mdio_write(f8364000, 0x00000014, 00000fb54) required 2000 cycles
>
> And eth2 was not working. Reloading the module gave a lot of other
> mdio_write and mdio_read errors.
>
> It seems to be pretty random when the errors occur, but that's the
> reason why the NIC stops working: mdio_write() fails (one or more times)
> at some crucial point of the board specific phy config code resulting in
> bad state.
>
> Any ideas how to debug this further?
Ok, I compared Realtek's and the in-tree driver. The only essential
difference is that Realtek driver uses udelay(100) in mdio_write()'s
busy polling loop where as the in-tree uses udelay(25). And that seems
to be the magic difference! Using udelay(100) fixes this!
I'm guessing that the phy needs slight delay between consecutive
mdio_write's even if it has advertised that the write has been
completed. And yes, just adding a small delay in the end of mdio_write
does seem to work too.
Francois, you think the below patch is ok? Should I send it as properly
formatted commit?
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 217e709..6db62bf 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -559,6 +559,7 @@ static void mdio_write(void __iomem *ioaddr,
break;
udelay(25);
}
+ udelay(25);
}
static int mdio_read(void __iomem *ioaddr, int reg_addr)
^ permalink raw reply related
* RE: [Patch 1/2] s2io: add dynamic LRO disable support
From: Ramkrishna Vepa @ 2010-06-05 8:53 UTC (permalink / raw)
To: Michal Schmidt, netdev@vger.kernel.org
Cc: Amerigo Wang, herbert.xu@redhat.com, nhorman@redhat.com,
sgruszka@redhat.com, davem@davemloft.net
In-Reply-To: <20100603153811.7b14a1a8@leela>
> +static int s2io_ethtool_set_flags(struct net_device *dev, u32 data)
> +{
> + struct s2io_nic *sp = netdev_priv(dev);
> + int rc = 0;
> + int changed = 0;
> +
> + if (data & ETH_FLAG_LRO) {
> + if (lro_enable) {
> + if (!(dev->features & NETIF_F_LRO)) {
> + dev->features |= NETIF_F_LRO;
> + changed = 1;
> + }
> + } else
> + rc = -EINVAL;
> + } else if (dev->features & NETIF_F_LRO) {
> + dev->features &= ~NETIF_F_LRO;
> + changed = 1;
> + }
> +
> + if (changed && netif_running(dev)) {
> + s2io_stop_all_tx_queue(sp);
> + s2io_card_down(sp);
> + sp->lro = dev->features & NETIF_F_LRO;
> + rc = s2io_card_up(sp);
In s2io_card_up, update ring->lro too as it is used in the fast path -
struct ring_info *ring = &mac_control->rings[i];
ring->mtu = dev->mtu;
+ ring->lro = sp->lro;
> + s2io_start_all_tx_queue(sp);
The following line in init_shared_mem() is redundant and can be removed.
- ring->lro = lro_enable;
Thanks,
Ram
^ permalink raw reply
* Re: [PATCH] Re: still having r8169 woes with XID 18000000
From: David Miller @ 2010-06-05 9:02 UTC (permalink / raw)
To: timo.teras; +Cc: phil, romieu, netdev
In-Reply-To: <4C09FF4B.4050601@iki.fi>
From: Timo Teräs <timo.teras@iki.fi>
Date: Sat, 05 Jun 2010 10:39:55 +0300
> Ok, I compared Realtek's and the in-tree driver. The only essential
> difference is that Realtek driver uses udelay(100) in mdio_write()'s
> busy polling loop where as the in-tree uses udelay(25). And that seems
> to be the magic difference! Using udelay(100) fixes this!
>
> I'm guessing that the phy needs slight delay between consecutive
> mdio_write's even if it has advertised that the write has been
> completed. And yes, just adding a small delay in the end of mdio_write
> does seem to work too.
>
> Francois, you think the below patch is ok? Should I send it as properly
> formatted commit?
Excellent detective work, Francois please review!
^ permalink raw reply
* Re: [PATCH] Re: still having r8169 woes with XID 18000000
From: Eric Dumazet @ 2010-06-05 9:13 UTC (permalink / raw)
To: Timo Teräs; +Cc: Phil Sutter, françois romieu, netdev
In-Reply-To: <4C09FF4B.4050601@iki.fi>
Le samedi 05 juin 2010 à 10:39 +0300, Timo Teräs a écrit :
> Ok, I compared Realtek's and the in-tree driver. The only essential
> difference is that Realtek driver uses udelay(100) in mdio_write()'s
> busy polling loop where as the in-tree uses udelay(25). And that seems
> to be the magic difference! Using udelay(100) fixes this!
>
> I'm guessing that the phy needs slight delay between consecutive
> mdio_write's even if it has advertised that the write has been
> completed. And yes, just adding a small delay in the end of mdio_write
> does seem to work too.
>
> Francois, you think the below patch is ok? Should I send it as properly
> formatted commit?
>
> diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
> index 217e709..6db62bf 100644
> --- a/drivers/net/r8169.c
> +++ b/drivers/net/r8169.c
> @@ -559,6 +559,7 @@ static void mdio_write(void __iomem *ioaddr,
> break;
> udelay(25);
> }
> + udelay(25);
> }
>
> static int mdio_read(void __iomem *ioaddr, int reg_addr)
> --
Sure this deserves an official patch with all prereqs, but please add a
comment in mdio_write() why this extra udelay(25) is needed, especially
since you say of udelay(100) 'fixes the bug'.
^ permalink raw reply
* Re: [Bugme-new] [Bug 16120] New: Oops: 0000 [#1] SMP, unable to handle kernel NULL pointer dereference at (null)
From: Eric Dumazet @ 2010-06-05 9:17 UTC (permalink / raw)
To: Andrew Morton, David Miller
Cc: netdev, bugzilla-daemon, bugme-daemon, alex.vizor,
Patrick McHardy
In-Reply-To: <20100604161737.25c7940a.akpm@linux-foundation.org>
Le vendredi 04 juin 2010 à 16:17 -0700, Andrew Morton a écrit :
> (switched to email. Please respond via emailed reply-to-all, not via the
> bugzilla web interface).
>
> On Fri, 4 Jun 2010 09:25:58 GMT
> bugzilla-daemon@bugzilla.kernel.org wrote:
>
> > https://bugzilla.kernel.org/show_bug.cgi?id=16120
> >
> > Summary: Oops: 0000 [#1] SMP, unable to handle kernel NULL
> > pointer dereference at (null)
> > Product: Platform Specific/Hardware
> > Version: 2.5
> > Kernel Version: 2.6.35-rc1
> > Platform: All
> > OS/Version: Linux
> > Tree: Mainline
> > Status: NEW
> > Severity: high
> > Priority: P1
> > Component: x86-64
> > AssignedTo: platform_x86_64@kernel-bugs.osdl.org
> > ReportedBy: alex.vizor@gmail.com
> > Regression: Yes
> >
> >
> > Created an attachment (id=26647)
> > --> (https://bugzilla.kernel.org/attachment.cgi?id=26647) id)
> > 2.6.35-rc1 kernel log
> >
> > It happens randomly, almost a week I used 2.6.35-rc1 and don't have any
> > problems. But since last day it happened twice.
> >
> > I attached kernel log, please inform me if I can help in investigation.
> >
>
> ip6mr_sk_done() oopsed.
Only thing I found a first glance is a typo but this should not be the
root of the problem.
[PATCH] ip6mr: fix a typo in ip6mr_for_each_table()
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 073071f..89c0b07 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -120,7 +120,7 @@ static void mroute_clean_tables(struct mr6_table *mrt);
static void ipmr_expire_process(unsigned long arg);
#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
-#define ip6mr_for_each_table(mrt, met) \
+#define ip6mr_for_each_table(mrt, net) \
list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
^ permalink raw reply related
* Re: [PATCH] Re: still having r8169 woes with XID 18000000
From: Timo Teräs @ 2010-06-05 9:21 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Phil Sutter, françois romieu, netdev
In-Reply-To: <1275729201.5238.2.camel@edumazet-laptop>
On 06/05/2010 12:13 PM, Eric Dumazet wrote:
> Le samedi 05 juin 2010 à 10:39 +0300, Timo Teräs a écrit :
>> Ok, I compared Realtek's and the in-tree driver. The only essential
>> difference is that Realtek driver uses udelay(100) in mdio_write()'s
>> busy polling loop where as the in-tree uses udelay(25). And that seems
>> to be the magic difference! Using udelay(100) fixes this!
>>
>> I'm guessing that the phy needs slight delay between consecutive
>> mdio_write's even if it has advertised that the write has been
>> completed. And yes, just adding a small delay in the end of mdio_write
>> does seem to work too.
>>
>> Francois, you think the below patch is ok? Should I send it as properly
>> formatted commit?
>>
>> diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
>> index 217e709..6db62bf 100644
>> --- a/drivers/net/r8169.c
>> +++ b/drivers/net/r8169.c
>> @@ -559,6 +559,7 @@ static void mdio_write(void __iomem *ioaddr,
>> break;
>> udelay(25);
>> }
>> + udelay(25);
>> }
>>
>> static int mdio_read(void __iomem *ioaddr, int reg_addr)
>> --
>
> Sure this deserves an official patch with all prereqs, but please add a
> comment in mdio_write() why this extra udelay(25) is needed, especially
> since you say of udelay(100) 'fixes the bug'.
Uh, yes. The intention was to get feedback if this is the proper place
for the delay. I first thought that maybe we could just add the delay to
the phy config function writing the values in tight loop... but as it
appears even some other mdio_writes seem to fail, this seems to be the
logical and correct place.
Alternatively, I was thinking if someone had specs to check if they say
anything about delay needed between mdio writes.
Reason why adding new delay in the end of the function is better is
because using udelay(100) in the loop means that anything between
0..100us has elapsed after the "write complete" is acked; if very
unlucky the "write complete" happens just after our udelay has ended and
there would be no delay between next mdio write.
Adding the additional udelay(25) in the end guarantees small delay
between "write complete" ack and the next write. And yes, it needs a
comment.
I'll send a new patch shortly.
^ permalink raw reply
* Re: [Bugme-new] [Bug 16120] New: Oops: 0000 [#1] SMP, unable to handle kernel NULL pointer dereference at (null)
From: Eric Dumazet @ 2010-06-05 9:34 UTC (permalink / raw)
To: Andrew Morton
Cc: David Miller, netdev, bugzilla-daemon, bugme-daemon, alex.vizor,
Patrick McHardy
In-Reply-To: <1275729426.5238.6.camel@edumazet-laptop>
Le samedi 05 juin 2010 à 11:17 +0200, Eric Dumazet a écrit :
> Le vendredi 04 juin 2010 à 16:17 -0700, Andrew Morton a écrit :
> > (switched to email. Please respond via emailed reply-to-all, not via the
> > bugzilla web interface).
> >
> > On Fri, 4 Jun 2010 09:25:58 GMT
> > bugzilla-daemon@bugzilla.kernel.org wrote:
> >
> > > https://bugzilla.kernel.org/show_bug.cgi?id=16120
> > >
> > > Summary: Oops: 0000 [#1] SMP, unable to handle kernel NULL
> > > pointer dereference at (null)
> > > Product: Platform Specific/Hardware
> > > Version: 2.5
> > > Kernel Version: 2.6.35-rc1
> > > Platform: All
> > > OS/Version: Linux
> > > Tree: Mainline
> > > Status: NEW
> > > Severity: high
> > > Priority: P1
> > > Component: x86-64
> > > AssignedTo: platform_x86_64@kernel-bugs.osdl.org
> > > ReportedBy: alex.vizor@gmail.com
> > > Regression: Yes
> > >
> > >
> > > Created an attachment (id=26647)
> > > --> (https://bugzilla.kernel.org/attachment.cgi?id=26647) id)
>
> > > 2.6.35-rc1 kernel log
> > >
> > > It happens randomly, almost a week I used 2.6.35-rc1 and don't have any
> > > problems. But since last day it happened twice.
> > >
> > > I attached kernel log, please inform me if I can help in investigation.
> > >
> >
> > ip6mr_sk_done() oopsed.
>
> Only thing I found a first glance is a typo but this should not be the
> root of the problem.
>
At a second glance, I think the problem is that we probably cleanup
in the wrong order.
ip6mr_rules_exit() is probably called before icmpv6_sk_exit() ?
I dont know how to fix this order, no more time for me until Monday.
We should reinit mr6_tables list in ip6mr_rules_exit() in any case
[PATCH] ip6mr: fixes
1) Fix a typo in ip6mr_for_each_table() definition
2) Re-initiliaze mr6_tables in ip6mr_rules_exit()
bugzilla report : https://bugzilla.kernel.org/attachment.cgi?id=26647
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 073071f..e2ff192 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -120,7 +120,7 @@ static void mroute_clean_tables(struct mr6_table *mrt);
static void ipmr_expire_process(unsigned long arg);
#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
-#define ip6mr_for_each_table(mrt, met) \
+#define ip6mr_for_each_table(mrt, net) \
list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
@@ -256,6 +256,7 @@ static void __net_exit ip6mr_rules_exit(struct net *net)
list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list)
ip6mr_free_table(mrt);
+ INIT_LIST_HEAD(&net->ipv6.mr6_tables);
fib_rules_unregister(net->ipv6.mr6_rules_ops);
}
#else
^ permalink raw reply related
* Re: [Bugme-new] [Bug 16120] New: Oops: 0000 [#1] SMP, unable to handle kernel NULL pointer dereference at (null)
From: Eric Dumazet @ 2010-06-05 9:36 UTC (permalink / raw)
To: Andrew Morton
Cc: David Miller, netdev, bugzilla-daemon, bugme-daemon, alex.vizor,
Patrick McHardy
In-Reply-To: <1275730457.5238.14.camel@edumazet-laptop>
Le samedi 05 juin 2010 à 11:34 +0200, Eric Dumazet a écrit :
> Le samedi 05 juin 2010 à 11:17 +0200, Eric Dumazet a écrit :
> > Le vendredi 04 juin 2010 à 16:17 -0700, Andrew Morton a écrit :
> > > (switched to email. Please respond via emailed reply-to-all, not via the
> > > bugzilla web interface).
> > >
> > > On Fri, 4 Jun 2010 09:25:58 GMT
> > > bugzilla-daemon@bugzilla.kernel.org wrote:
> > >
> > > > https://bugzilla.kernel.org/show_bug.cgi?id=16120
> > > >
> > > > Summary: Oops: 0000 [#1] SMP, unable to handle kernel NULL
> > > > pointer dereference at (null)
> > > > Product: Platform Specific/Hardware
> > > > Version: 2.5
> > > > Kernel Version: 2.6.35-rc1
> > > > Platform: All
> > > > OS/Version: Linux
> > > > Tree: Mainline
> > > > Status: NEW
> > > > Severity: high
> > > > Priority: P1
> > > > Component: x86-64
> > > > AssignedTo: platform_x86_64@kernel-bugs.osdl.org
> > > > ReportedBy: alex.vizor@gmail.com
> > > > Regression: Yes
> > > >
> > > >
> > > > Created an attachment (id=26647)
> > > > --> (https://bugzilla.kernel.org/attachment.cgi?id=26647) id)
> >
> > > > 2.6.35-rc1 kernel log
> > > >
> > > > It happens randomly, almost a week I used 2.6.35-rc1 and don't have any
> > > > problems. But since last day it happened twice.
> > > >
> > > > I attached kernel log, please inform me if I can help in investigation.
> > > >
> > >
> > > ip6mr_sk_done() oopsed.
> >
> > Only thing I found a first glance is a typo but this should not be the
> > root of the problem.
> >
>
> At a second glance, I think the problem is that we probably cleanup
> in the wrong order.
>
> ip6mr_rules_exit() is probably called before icmpv6_sk_exit() ?
>
> I dont know how to fix this order, no more time for me until Monday.
>
>
> We should reinit mr6_tables list in ip6mr_rules_exit() in any case
>
>
> [PATCH] ip6mr: fixes
>
> 1) Fix a typo in ip6mr_for_each_table() definition
>
> 2) Re-initiliaze mr6_tables in ip6mr_rules_exit()
>
> bugzilla report : https://bugzilla.kernel.org/attachment.cgi?id=26647
>
Ah well, crap... https://bugzilla.kernel.org/show_bug.cgi?id=16120
Sorry, I really have to run...
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
>
> diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
> index 073071f..e2ff192 100644
> --- a/net/ipv6/ip6mr.c
> +++ b/net/ipv6/ip6mr.c
> @@ -120,7 +120,7 @@ static void mroute_clean_tables(struct mr6_table *mrt);
> static void ipmr_expire_process(unsigned long arg);
>
> #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
> -#define ip6mr_for_each_table(mrt, met) \
> +#define ip6mr_for_each_table(mrt, net) \
> list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
>
> static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
> @@ -256,6 +256,7 @@ static void __net_exit ip6mr_rules_exit(struct net *net)
>
> list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list)
> ip6mr_free_table(mrt);
> + INIT_LIST_HEAD(&net->ipv6.mr6_tables);
> fib_rules_unregister(net->ipv6.mr6_rules_ops);
> }
> #else
>
^ permalink raw reply
* [PATCH] 8139too: fix buffer overrun in rtl8139_init_board
From: Denis Kirjanov @ 2010-06-05 9:45 UTC (permalink / raw)
To: davem; +Cc: jeff, netdev
Fix rtl_chip_info buffer overrun when we can't identify the chip.
(i = ARRAY_SIZE (rtl_chip_info) in this case)
Signed-off-by: Denis Kirjanov <dkirjanov@kernel.org>
---
drivers/net/8139too.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index cc7d462..149253d 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -860,6 +860,7 @@ retry:
}
/* if unknown chip, assume array element #0, original RTL-8139 in this case */
+ i = 0;
dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n");
dev_dbg(&pdev->dev, "TxConfig = 0x%x\n", RTL_R32 (TxConfig));
tp->chipset = 0;
^ permalink raw reply related
* Re: [PATCH net-next-2.6] syncookies: make v4/v6 synflood warning behaviour the same
From: David Miller @ 2010-06-05 9:53 UTC (permalink / raw)
To: fw; +Cc: netdev
In-Reply-To: <1275561792-24179-1-git-send-email-fw@strlen.de>
From: Florian Westphal <fw@strlen.de>
Date: Thu, 3 Jun 2010 12:43:12 +0200
> both syn_flood_warning functions print a message, but
> ipv4 version only prints a warning if CONFIG_SYN_COOKIES=y.
>
> Make the v4 one behave like the v6 one.
>
> Signed-off-by: Florian Westphal <fw@strlen.de>
Applied.
^ permalink raw reply
* Re: [PATCH net-next-2.6] syncookies: avoid unneeded tcp header flag double check
From: David Miller @ 2010-06-05 9:53 UTC (permalink / raw)
To: fw; +Cc: netdev
In-Reply-To: <1275561824-24227-1-git-send-email-fw@strlen.de>
From: Florian Westphal <fw@strlen.de>
Date: Thu, 3 Jun 2010 12:43:44 +0200
> caller: if (!th->rst && !th->syn && th->ack)
> callee: if (!th->ack)
>
> make the caller only check for !syn (common for 3whs), and move
> the !rst / ack test to the callee.
>
> Signed-off-by: Florian Westphal <fw@strlen.de>
Applied.
^ permalink raw reply
* Re: [PATCH net-next-2.6] syncookies: update mss tables
From: David Miller @ 2010-06-05 9:53 UTC (permalink / raw)
To: fw; +Cc: netdev
In-Reply-To: <1275561837-24269-1-git-send-email-fw@strlen.de>
From: Florian Westphal <fw@strlen.de>
Date: Thu, 3 Jun 2010 12:43:57 +0200
> - ipv6 msstab: account for ipv6 header size
> - ipv4 msstab: add mss for Jumbograms.
>
> Signed-off-by: Florian Westphal <fw@strlen.de>
Applied, thanks for doing this.
^ permalink raw reply
* Re: [PATCH net-next-2.6] [PPPOE] fix return value of __pppoe_xmit() method.
From: David Miller @ 2010-06-05 9:54 UTC (permalink / raw)
To: ramirose; +Cc: netdev
In-Reply-To: <AANLkTimW3olb9_3Wo8HvtYRP_LOCEeHDGWuVQvGMvFxd@mail.gmail.com>
From: Rami Rosen <ramirose@gmail.com>
Date: Thu, 3 Jun 2010 18:02:29 +0300
> __pppoe_xmit() in drivers/net/pppoe always returns 1.
> When the methods fails (via goto abort), it should return 0 and not 1.
>
> Signed-off-by: Rami Rosen <ramirose@gmail.com>
APplied.
^ permalink raw reply
* Re: [net-next-2.6 PATCH 1/2] skbuff: add check for non-linear to warn_if_lro and needs_linearize
From: David Miller @ 2010-06-05 9:54 UTC (permalink / raw)
To: jeffrey.t.kirsher
Cc: mingo, tglx, hpa, x86, linux-kernel, netdev, gospo,
alexander.h.duyck
In-Reply-To: <20100602222230.12962.97260.stgit@localhost.localdomain>
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Wed, 02 Jun 2010 15:24:37 -0700
> From: Alexander Duyck <alexander.h.duyck@intel.com>
>
> We can avoid an unecessary cache miss by checking if the skb is non-linear
> before accessing gso_size/gso_type in skb_warn_if_lro, the same can also be
> done to avoid a cache miss on nr_frags if data_len is 0.
>
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next-2.6 1/2][v2] bonding: add all_slaves_active parameter
From: David Miller @ 2010-06-05 9:54 UTC (permalink / raw)
To: andy; +Cc: netdev, fubar, nhorman
In-Reply-To: <20100602183921.GK7497@gospo.rdu.redhat.com>
From: Andy Gospodarek <andy@greyhouse.net>
Date: Wed, 2 Jun 2010 14:39:21 -0400
>
> v2: changed parameter name from 'keep_all' to 'all_slaves_active' and
> skipped setting slaves to inactive rather than creating a new flag at
> Jay's suggestion.
>
> In an effort to suppress duplicate frames on certain bonding modes
> (specifically the modes that do not require additional configuration on
> the switch or switches connected to the host), code was added in the
> generic receive patch in 2.6.16. The current behavior works quite well
> for most users, but there are some times it would be nice to restore old
> functionality and allow all frames to make their way up the stack.
>
> This patch adds support for a new module option and sysfs file called
> 'all_slaves_active' that will restore pre-2.6.16 functionality if the
> user desires. The default value is '0' and retains existing behavior,
> but the user can set it to '1' and allow all frames up if desired.
>
> Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
> Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next-2.6 2/2][v2] bonding: allow user-controlled output slave selection
From: David Miller @ 2010-06-05 9:54 UTC (permalink / raw)
To: andy; +Cc: netdev, nhorman
In-Reply-To: <20100602184018.GL7497@gospo.rdu.redhat.com>
From: Andy Gospodarek <andy@greyhouse.net>
Date: Wed, 2 Jun 2010 14:40:18 -0400
>
> v2: changed bonding module version, modified to apply on top of changes
> from previous patch in series, and updated documentation to elaborate on
> multiqueue awareness that now exists in bonding driver.
>
> This patch give the user the ability to control the output slave for
> round-robin and active-backup bonding. Similar functionality was
> discussed in the past, but Jay Vosburgh indicated he would rather see a
> feature like this added to existing modes rather than creating a
> completely new mode. Jay's thoughts as well as Neil's input surrounding
> some of the issues with the first implementation pushed us toward a
> design that relied on the queue_mapping rather than skb marks.
> Round-robin and active-backup modes were chosen as the first users of
> this slave selection as they seemed like the most logical choices when
> considering a multi-switch environment.
>
> Round-robin mode works without any modification, but active-backup does
> require inclusion of the first patch in this series and setting
> the 'all_slaves_active' flag. This will allow reception of unicast traffic on
> any of the backup interfaces.
>
> This was tested with IPv4-based filters as well as VLAN-based filters
> with good results.
>
> More information as well as a configuration example is available in the
> patch to Documentation/networking/bonding.txt.
>
> Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Applied.
^ permalink raw reply
* Re: [PATCH] fec: convert legacy PM hooks to dem_pm_ops
From: David Miller @ 2010-06-05 9:55 UTC (permalink / raw)
To: dkirjanov; +Cc: netdev, s.hauer, linux-arm-kernel, eric, gerg
In-Reply-To: <20100602192704.GA22726@hera.kernel.org>
From: Denis Kirjanov <dkirjanov@hera.kernel.org>
Date: Wed, 2 Jun 2010 19:27:04 +0000
> This patch compile tested only.
>
> Convert legacy PM hooks to dev_pm_ops
> Signed-off-by: Denis Kirjanov <dkirjanov@kernel.org>
Applied, thanks.
^ permalink raw reply
* Re: [Bugme-new] [Bug 16083] New: swapper: Page allocation failure
From: David Miller @ 2010-06-05 9:59 UTC (permalink / raw)
To: eric.dumazet; +Cc: akpm, netdev
In-Reply-To: <1275602282.2533.72.camel@edumazet-laptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Thu, 03 Jun 2010 23:58:02 +0200
> So in this particular case, the bugzilla report can point to a real
> problem in our stack.
>
> Failed allocations had been silent, we probably would never have
> noticed.
Agreed.
We'd be instead scratching our heads over reports about IGMP/MLD
reports not going out.
^ permalink raw reply
* Re: [Bugme-new] [Bug 16083] New: swapper: Page allocation failure
From: David Miller @ 2010-06-05 10:04 UTC (permalink / raw)
To: eric.dumazet; +Cc: akpm, netdev
In-Reply-To: <1275601036.2533.63.camel@edumazet-laptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Thu, 03 Jun 2010 23:37:16 +0200
> [PATCH] ipv6: avoid high order allocations
>
> With mtu=9000, mld_newpack() use order-2 GFP_ATOMIC allocations, that
> are very unreliable, on machines where PAGE_SIZE=4K
>
> Limit allocated skbs to be at most one page. (order-0 allocations)
>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
This looks perfectly fine to me, except I had to change
min(...) to min_t(int, ...) to avoid a compile warning.
Thanks Eric!
^ permalink raw reply
* Re: [net-next-2.6 PATCH v2] ixgbevf: Enable GRO by default
From: David Miller @ 2010-06-05 10:05 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, gospo, xma, gregory.v.rose
In-Reply-To: <20100604031911.16828.76874.stgit@localhost.localdomain>
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Thu, 03 Jun 2010 20:19:25 -0700
> From: Shirley Ma <mashirle@us.ibm.com>
>
> Enable GRO by default for performance.
>
> Signed-off-by: Shirley Ma <xma@us.ibm.com>
> Acked-by: Greg Rose <gregory.v.rose@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Applied, thanks.
^ permalink raw reply
* [RFC PATCH v7 05/19] Add a function make external buffer owner to query capability.
From: xiaohui.xin @ 2010-06-05 10:14 UTC (permalink / raw)
To: netdev, kvm, linux-kernel, mst, mingo, davem, herbert, jdike; +Cc: Xin Xiaohui
In-Reply-To: <1275732899-5423-4-git-send-email-xiaohui.xin@intel.com>
From: Xin Xiaohui <xiaohui.xin@intel.com>
The external buffer owner can use the functions to get
the capability of the underlying NIC driver.
Signed-off-by: Xin Xiaohui <xiaohui.xin@intel.com>
Signed-off-by: Zhao Yu <yzhaonew@gmail.com>
Reviewed-by: Jeff Dike <jdike@linux.intel.com>
---
include/linux/netdevice.h | 2 +
net/core/dev.c | 51 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+), 0 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 183c786..31d9c4a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1599,6 +1599,8 @@ extern gro_result_t napi_gro_frags(struct napi_struct *napi);
extern int netdev_mp_port_attach(struct net_device *dev,
struct mpassthru_port *port);
extern void netdev_mp_port_detach(struct net_device *dev);
+extern int netdev_mp_port_prep(struct net_device *dev,
+ struct mpassthru_port *port);
static inline void napi_free_frags(struct napi_struct *napi)
{
diff --git a/net/core/dev.c b/net/core/dev.c
index ecbb6b1..37b389a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2497,6 +2497,57 @@ void netdev_mp_port_detach(struct net_device *dev)
}
EXPORT_SYMBOL(netdev_mp_port_detach);
+/* To support meidate passthru(zero-copy) with NIC driver,
+ * we'd better query NIC driver for the capability it can
+ * provide, especially for packet split mode, now we only
+ * query for the header size, and the payload a descriptor
+ * may carry. If a driver does not use the API to export,
+ * then we may try to use a default value, currently,
+ * we use the default value from an IGB driver. Now,
+ * it's only called by mpassthru device.
+ */
+#if defined(CONFIG_MEDIATE_PASSTHRU) || defined(CONFIG_MEDIATE_PASSTHRU_MODULE)
+int netdev_mp_port_prep(struct net_device *dev,
+ struct mpassthru_port *port)
+{
+ int rc;
+ int npages, data_len;
+ const struct net_device_ops *ops = dev->netdev_ops;
+
+ /* needed by packet split */
+
+ if (ops->ndo_mp_port_prep) {
+ rc = ops->ndo_mp_port_prep(dev, port);
+ if (rc)
+ return rc;
+ } else {
+ /* If the NIC driver did not report this,
+ * then we try to use default value.
+ */
+ port->hdr_len = 128;
+ port->data_len = 2048;
+ port->npages = 1;
+ }
+
+ if (port->hdr_len <= 0)
+ goto err;
+
+ npages = port->npages;
+ data_len = port->data_len;
+ if (npages <= 0 || npages > MAX_SKB_FRAGS ||
+ (data_len < PAGE_SIZE * (npages - 1) ||
+ data_len > PAGE_SIZE * npages))
+ goto err;
+
+ return 0;
+err:
+ dev_warn(&dev->dev, "invalid page constructor parameters\n");
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(netdev_mp_port_prep);
+#endif
+
/**
* netif_receive_skb - process receive buffer from network
* @skb: buffer to process
--
1.5.4.4
^ permalink raw reply related
* [RFC PATCH v7 08/19] Make __alloc_skb() to get external buffer.
From: xiaohui.xin @ 2010-06-05 10:14 UTC (permalink / raw)
To: netdev, kvm, linux-kernel, mst, mingo, davem, herbert, jdike; +Cc: Xin Xiaohui
In-Reply-To: <1275732899-5423-7-git-send-email-xiaohui.xin@intel.com>
From: Xin Xiaohui <xiaohui.xin@intel.com>
Add a dev parameter to __alloc_skb(), skb->data
points to external buffer, recompute skb->head,
maintain shinfo of the external buffer, record
external buffer info into destructor_arg field.
Signed-off-by: Xin Xiaohui <xiaohui.xin@intel.com>
Signed-off-by: Zhao Yu <yzhao81new@gmail.com>
Reviewed-by: Jeff Dike <jdike@linux.intel.com>
---
__alloc_skb() cleanup by
Jeff Dike <jdike@linux.intel.com>
include/linux/skbuff.h | 7 ++++---
net/core/skbuff.c | 43 +++++++++++++++++++++++++++++++++++++------
2 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 281a1c0..5ff8c27 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -442,17 +442,18 @@ extern void kfree_skb(struct sk_buff *skb);
extern void consume_skb(struct sk_buff *skb);
extern void __kfree_skb(struct sk_buff *skb);
extern struct sk_buff *__alloc_skb(unsigned int size,
- gfp_t priority, int fclone, int node);
+ gfp_t priority, int fclone,
+ int node, struct net_device *dev);
static inline struct sk_buff *alloc_skb(unsigned int size,
gfp_t priority)
{
- return __alloc_skb(size, priority, 0, -1);
+ return __alloc_skb(size, priority, 0, -1, NULL);
}
static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
gfp_t priority)
{
- return __alloc_skb(size, priority, 1, -1);
+ return __alloc_skb(size, priority, 1, -1, NULL);
}
extern int skb_recycle_check(struct sk_buff *skb, int skb_size);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index fbdb1f1..38d19d0 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -161,7 +161,8 @@ EXPORT_SYMBOL(skb_under_panic);
* @fclone: allocate from fclone cache instead of head cache
* and allocate a cloned (child) skb
* @node: numa node to allocate memory on
- *
+ * @dev: a device owns the skb if the skb try to get external buffer.
+ * otherwise is NULL.
* Allocate a new &sk_buff. The returned buffer has no headroom and a
* tail room of size bytes. The object has a reference count of one.
* The return is the buffer. On a failure the return is %NULL.
@@ -170,12 +171,13 @@ EXPORT_SYMBOL(skb_under_panic);
* %GFP_ATOMIC.
*/
struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
- int fclone, int node)
+ int fclone, int node, struct net_device *dev)
{
struct kmem_cache *cache;
struct skb_shared_info *shinfo;
struct sk_buff *skb;
- u8 *data;
+ u8 *data = NULL;
+ struct skb_external_page *ext_page = NULL;
cache = fclone ? skbuff_fclone_cache : skbuff_head_cache;
@@ -185,8 +187,23 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
goto out;
size = SKB_DATA_ALIGN(size);
- data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info),
- gfp_mask, node);
+
+ /* If the device wants to do mediate passthru(zero-copy),
+ * the skb may try to get external buffers from outside.
+ * If fails, then fall back to alloc buffers from kernel.
+ */
+ if (dev && dev->mp_port) {
+ ext_page = netdev_alloc_external_page(dev, skb, size);
+ if (ext_page) {
+ data = ext_page->start;
+ size = ext_page->size;
+ }
+ }
+
+ if (!data)
+ data = kmalloc_node_track_caller(
+ size + sizeof(struct skb_shared_info),
+ gfp_mask, node);
if (!data)
goto nodata;
@@ -208,6 +225,15 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
skb->mac_header = ~0U;
#endif
+ /* If the skb get external buffers sucessfully, since the shinfo is
+ * at the end of the buffer, we may retain the shinfo once we
+ * need it sometime.
+ */
+ if (ext_page) {
+ skb->head = skb->data - NET_IP_ALIGN - NET_SKB_PAD;
+ memcpy(ext_page->ushinfo, skb_shinfo(skb),
+ sizeof(struct skb_shared_info));
+ }
/* make sure we initialize shinfo sequentially */
shinfo = skb_shinfo(skb);
atomic_set(&shinfo->dataref, 1);
@@ -231,6 +257,11 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
child->fclone = SKB_FCLONE_UNAVAILABLE;
}
+ /* Record the external buffer info in this field. It's not so good,
+ * but we cannot find another place easily.
+ */
+ shinfo->destructor_arg = ext_page;
+
out:
return skb;
nodata:
@@ -259,7 +290,7 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
struct sk_buff *skb;
- skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node);
+ skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node, dev);
if (likely(skb)) {
skb_reserve(skb, NET_SKB_PAD);
skb->dev = dev;
--
1.5.4.4
^ permalink raw reply related
* [RFC PATCH v7 09/19] Ignore room skb_reserve() when device is using external buffer.
From: xiaohui.xin @ 2010-06-05 10:14 UTC (permalink / raw)
To: netdev, kvm, linux-kernel, mst, mingo, davem, herbert, jdike; +Cc: Xin Xiaohui
In-Reply-To: <1275732899-5423-8-git-send-email-xiaohui.xin@intel.com>
From: Xin Xiaohui <xiaohui.xin@intel.com>
Make the skb->data and skb->head from external buffer
to be consistent, we ignore the room reserved by driver
for kernel skb.
Signed-off-by: Xin Xiaohui <xiaohui.xin@intel.com>
Signed-off-by: Zhao Yu <yzhao81new@gmail.com>
Reviewed-by: Jeff Dike <jdike@linux.intel.com>
---
include/linux/skbuff.h | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 5ff8c27..193b259 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1200,6 +1200,15 @@ static inline int skb_tailroom(const struct sk_buff *skb)
*/
static inline void skb_reserve(struct sk_buff *skb, int len)
{
+ /* Since skb_reserve() is only for an empty buffer,
+ * and when the skb is getting external buffer, we cannot
+ * retain the external buffer has the same reserved space
+ * in the header which kernel allocatd skb has, so have to
+ * ignore this. And we have recorded the external buffer
+ * info in the destructor_arg field, so use it as indicator.
+ */
+ if (skb_shinfo(skb)->destructor_arg)
+ return;
skb->data += len;
skb->tail += len;
}
--
1.5.4.4
^ permalink raw reply related
* [RFC PATCH v7 14/19] Add header file for mp device.
From: xiaohui.xin @ 2010-06-05 10:14 UTC (permalink / raw)
To: netdev, kvm, linux-kernel, mst, mingo, davem, herbert, jdike; +Cc: Xin Xiaohui
In-Reply-To: <1275732899-5423-13-git-send-email-xiaohui.xin@intel.com>
From: Xin Xiaohui <xiaohui.xin@intel.com>
Signed-off-by: Xin Xiaohui <xiaohui.xin@intel.com>
Signed-off-by: Zhao Yu <yzhao81new@gmail.com>
Reviewed-by: Jeff Dike <jdike@linux.intel.com>
---
include/linux/mpassthru.h | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
create mode 100644 include/linux/mpassthru.h
diff --git a/include/linux/mpassthru.h b/include/linux/mpassthru.h
new file mode 100644
index 0000000..ba8f320
--- /dev/null
+++ b/include/linux/mpassthru.h
@@ -0,0 +1,25 @@
+#ifndef __MPASSTHRU_H
+#define __MPASSTHRU_H
+
+#include <linux/types.h>
+#include <linux/if_ether.h>
+
+/* ioctl defines */
+#define MPASSTHRU_BINDDEV _IOW('M', 213, int)
+#define MPASSTHRU_UNBINDDEV _IO('M', 214)
+
+#ifdef __KERNEL__
+#if defined(CONFIG_MEDIATE_PASSTHRU) || defined(CONFIG_MEDIATE_PASSTHRU_MODULE)
+struct socket *mp_get_socket(struct file *);
+#else
+#include <linux/err.h>
+#include <linux/errno.h>
+struct file;
+struct socket;
+static inline struct socket *mp_get_socket(struct file *f)
+{
+ return ERR_PTR(-EINVAL);
+}
+#endif /* CONFIG_MEDIATE_PASSTHRU */
+#endif /* __KERNEL__ */
+#endif /* __MPASSTHRU_H */
--
1.5.4.4
^ permalink raw reply related
* [RFC PATCH v7 17/19] Export proto_ops to vhost-net driver.
From: xiaohui.xin @ 2010-06-05 10:14 UTC (permalink / raw)
To: netdev, kvm, linux-kernel, mst, mingo, davem, herbert, jdike; +Cc: Xin Xiaohui
In-Reply-To: <1275732899-5423-16-git-send-email-xiaohui.xin@intel.com>
From: Xin Xiaohui <xiaohui.xin@intel.com>
Currently, vhost-net is only user to the mp device.
Signed-off-by: Xin Xiaohui <xiaohui.xin@intel.com>
Signed-off-by: Zhao Yu <yzhao81new@gmail.com>
Reviewed-by: Jeff Dike <jdike@linux.intel.com>
---
drivers/vhost/mpassthru.c | 295 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 290 insertions(+), 5 deletions(-)
diff --git a/drivers/vhost/mpassthru.c b/drivers/vhost/mpassthru.c
index 8c48898..23755ba 100644
--- a/drivers/vhost/mpassthru.c
+++ b/drivers/vhost/mpassthru.c
@@ -414,6 +414,11 @@ static void mp_put(struct mp_file *mfile)
mp_detach(mfile->mp);
}
+static void iocb_tag(struct kiocb *iocb)
+{
+ iocb->ki_flags = 1;
+}
+
/* The callback to destruct the external buffers or skb */
static void page_dtor(struct skb_external_page *ext_page)
{
@@ -449,7 +454,7 @@ static void page_dtor(struct skb_external_page *ext_page)
* Queue the notifier to wake up the backend driver
*/
- create_iocb(info, info->total);
+ iocb_tag(info->iocb);
sk = ctor->port.sock->sk;
sk->sk_write_space(sk);
@@ -569,8 +574,288 @@ failed:
return NULL;
}
+static void mp_sock_destruct(struct sock *sk)
+{
+ struct mp_struct *mp = container_of(sk, struct mp_sock, sk)->mp;
+ kfree(mp);
+}
+
+static void mp_sock_state_change(struct sock *sk)
+{
+ if (sk_has_sleeper(sk))
+ wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN);
+}
+
+static void mp_sock_write_space(struct sock *sk)
+{
+ if (sk_has_sleeper(sk))
+ wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT);
+}
+
+static void mp_sock_data_ready(struct sock *sk, int coming)
+{
+ struct mp_struct *mp = container_of(sk, struct mp_sock, sk)->mp;
+ struct page_ctor *ctor = NULL;
+ struct sk_buff *skb = NULL;
+ struct page_info *info = NULL;
+ struct ethhdr *eth;
+ struct kiocb *iocb = NULL;
+ int len, i;
+
+ struct virtio_net_hdr hdr = {
+ .flags = 0,
+ .gso_type = VIRTIO_NET_HDR_GSO_NONE
+ };
+
+ ctor = rcu_dereference(mp->ctor);
+ if (!ctor)
+ return;
+
+ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ if (skb_shinfo(skb)->destructor_arg) {
+ info = container_of(skb_shinfo(skb)->destructor_arg,
+ struct page_info, ext_page);
+ info->skb = skb;
+ if (skb->len > info->len) {
+ mp->dev->stats.rx_dropped++;
+ DBG(KERN_INFO "Discarded truncated rx packet: "
+ " len %d > %zd\n", skb->len, info->len);
+ info->total = skb->len;
+ goto clean;
+ } else {
+ eth = eth_hdr(skb);
+ skb_push(skb, ETH_HLEN);
+ info->total = skb->len;
+ }
+ } else {
+ /* The skb composed with kernel buffers
+ * in case external buffers are not sufficent.
+ * The case should be rare.
+ */
+ unsigned long flags;
+ int i;
+ info = NULL;
+
+ spin_lock_irqsave(&ctor->read_lock, flags);
+ if (!list_empty(&ctor->readq)) {
+ info = list_first_entry(&ctor->readq,
+ struct page_info, list);
+ list_del(&info->list);
+ }
+ spin_unlock_irqrestore(&ctor->read_lock, flags);
+ if (!info) {
+ DBG(KERN_INFO
+ "No external buffer avaliable %p\n",
+ skb);
+ skb_queue_head(&sk->sk_receive_queue,
+ skb);
+ break;
+ }
+ info->skb = skb;
+ eth = eth_hdr(skb);
+ skb_push(skb, ETH_HLEN);
+ info->total = skb->len;
+ skb_copy_datagram_iovec(skb, 0, info->iov, skb->len);
+ }
+
+ len = memcpy_toiovec(info->hdr, (unsigned char *)&hdr,
+ sizeof hdr);
+ if (len) {
+ DBG(KERN_INFO
+ "Unable to write vnet_hdr at addr %p: %d\n",
+ info->hdr->iov_base, len);
+ goto clean;
+ }
+
+ iocb = create_iocb(info, skb->len + sizeof(hdr));
+ continue;
+
+clean:
+ kfree_skb(skb);
+ for (i = 0; info->pages[i]; i++)
+ put_page(info->pages[i]);
+ kmem_cache_free(ext_page_info_cache, info);
+ }
+ return;
+}
+
+static int mp_sendmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t total_len)
+{
+ struct mp_struct *mp = container_of(sock->sk, struct mp_sock, sk)->mp;
+ struct page_ctor *ctor;
+ struct iovec *iov = m->msg_iov;
+ struct page_info *info = NULL;
+ struct frag frags[MAX_SKB_FRAGS];
+ struct sk_buff *skb;
+ int count = m->msg_iovlen;
+ int total = 0, header, n, i, len, rc;
+ unsigned long base;
+
+ ctor = rcu_dereference(mp->ctor);
+ if (!ctor)
+ return -ENODEV;
+
+ total = iov_length(iov, count);
+
+ if (total < ETH_HLEN)
+ return -EINVAL;
+
+ if (total <= COPY_THRESHOLD)
+ goto copy;
+
+ n = 0;
+ for (i = 0; i < count; i++) {
+ base = (unsigned long)iov[i].iov_base;
+ len = iov[i].iov_len;
+ if (!len)
+ continue;
+ n += ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
+ if (n > MAX_SKB_FRAGS)
+ return -EINVAL;
+ }
+
+copy:
+ header = total > COPY_THRESHOLD ? COPY_HDR_LEN : total;
+
+ skb = alloc_skb(header + NET_IP_ALIGN, GFP_ATOMIC);
+ if (!skb)
+ goto drop;
+
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ skb_set_network_header(skb, ETH_HLEN);
+
+ memcpy_fromiovec(skb->data, iov, header);
+ skb_put(skb, header);
+ skb->protocol = *((__be16 *)(skb->data) + ETH_ALEN);
+
+ if (header == total) {
+ rc = total;
+ info = alloc_small_page_info(ctor, iocb, total);
+ } else {
+ info = alloc_page_info(ctor, iocb, iov, count, frags, 0, total);
+ if (info)
+ for (i = 0; info->pages[i]; i++) {
+ skb_add_rx_frag(skb, i, info->pages[i],
+ frags[i].offset, frags[i].size);
+ info->pages[i] = NULL;
+ }
+ }
+ if (info != NULL) {
+ info->desc_pos = iocb->ki_pos;
+ info->total = total;
+ info->skb = skb;
+ skb_shinfo(skb)->destructor_arg = &info->ext_page;
+ skb->dev = mp->dev;
+ ctor->wq_len++;
+ create_iocb(info, info->total);
+ dev_queue_xmit(skb);
+ return 0;
+ }
+drop:
+ kfree_skb(skb);
+ if (info) {
+ for (i = 0; info->pages[i]; i++)
+ put_page(info->pages[i]);
+ kmem_cache_free(ext_page_info_cache, info);
+ }
+ mp->dev->stats.tx_dropped++;
+ return -ENOMEM;
+}
+
+static int mp_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t total_len,
+ int flags)
+{
+ struct mp_struct *mp = container_of(sock->sk, struct mp_sock, sk)->mp;
+ struct page_ctor *ctor;
+ struct iovec *iov = m->msg_iov;
+ int count = m->msg_iovlen;
+ int npages, payload;
+ struct page_info *info;
+ struct frag frags[MAX_SKB_FRAGS];
+ unsigned long base;
+ int i, len;
+ unsigned long flag;
+
+ if (!(flags & MSG_DONTWAIT))
+ return -EINVAL;
+
+ ctor = rcu_dereference(mp->ctor);
+ if (!ctor)
+ return -EINVAL;
+
+ /* Error detections in case invalid external buffer */
+ if (count > 2 && iov[1].iov_len < ctor->port.hdr_len &&
+ mp->dev->features & NETIF_F_SG) {
+ return -EINVAL;
+ }
+
+ npages = ctor->port.npages;
+ payload = ctor->port.data_len;
+
+ /* If KVM guest virtio-net FE driver use SG feature */
+ if (count > 2) {
+ for (i = 2; i < count; i++) {
+ base = (unsigned long)iov[i].iov_base & ~PAGE_MASK;
+ len = iov[i].iov_len;
+ if (npages == 1)
+ len = min_t(int, len, PAGE_SIZE - base);
+ else if (base)
+ break;
+ payload -= len;
+ if (payload <= 0)
+ goto proceed;
+ if (npages == 1 || (len & ~PAGE_MASK))
+ break;
+ }
+ }
+
+ if ((((unsigned long)iov[1].iov_base & ~PAGE_MASK)
+ - NET_SKB_PAD - NET_IP_ALIGN) >= 0)
+ goto proceed;
+
+ return -EINVAL;
+
+proceed:
+ /* skip the virtnet head */
+ iov++;
+ count--;
+
+ if (!ctor->lock_pages || !ctor->rq_len)
+ set_memlock_rlimit(ctor, RLIMIT_MEMLOCK,
+ iocb->ki_user_data * 4096 * 2,
+ iocb->ki_user_data * 4096 * 2);
+
+ /* Translate address to kernel */
+ info = alloc_page_info(ctor, iocb, iov, count, frags, npages, 0);
+ if (!info)
+ return -ENOMEM;
+ info->len = total_len;
+ info->hdr[0].iov_base = iocb->ki_iovec[0].iov_base;
+ info->hdr[0].iov_len = iocb->ki_iovec[0].iov_len;
+ info->offset = frags[0].offset;
+ info->desc_pos = iocb->ki_pos;
+
+ iov--;
+ count++;
+
+ memcpy(info->iov, iov, sizeof(struct iovec) * count);
+
+ spin_lock_irqsave(&ctor->read_lock, flag);
+ list_add_tail(&info->list, &ctor->readq);
+ spin_unlock_irqrestore(&ctor->read_lock, flag);
+
+ ctor->rq_len++;
+
+ return 0;
+}
+
/* Ops structure to mimic raw sockets with mp device */
static const struct proto_ops mp_socket_ops = {
+ .sendmsg = mp_sendmsg,
+ .recvmsg = mp_recvmsg,
};
static struct proto mp_proto = {
@@ -693,10 +978,10 @@ static long mp_chr_ioctl(struct file *file, unsigned int cmd,
sk->sk_sndbuf = INT_MAX;
container_of(sk, struct mp_sock, sk)->mp = mp;
- sk->sk_destruct = NULL;
- sk->sk_data_ready = NULL;
- sk->sk_write_space = NULL;
- sk->sk_state_change = NULL;
+ sk->sk_destruct = mp_sock_destruct;
+ sk->sk_data_ready = mp_sock_data_ready;
+ sk->sk_write_space = mp_sock_write_space;
+ sk->sk_state_change = mp_sock_state_change;
ret = mp_attach(mp, file);
if (ret < 0)
goto err_free_sk;
--
1.5.4.4
^ permalink raw reply related
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