* Re: TAHI CN-6-4-1 failed on Linux 2.6.32 kernel
From: Steve Chen @ 2010-08-13 0:00 UTC (permalink / raw)
To: Brian Haley; +Cc: usagi-users-ctl, netdev
In-Reply-To: <AANLkTik5JOupTW97ikf1imsZrkmwgfPNsvBoSZp1S8JV@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1540 bytes --]
On Thu, Aug 12, 2010 at 6:04 PM, Steve Chen <schen@mvista.com> wrote:
> On Thu, Aug 12, 2010 at 4:10 PM, Brian Haley <brian.haley@hp.com> wrote:
>> Hi Steve,
>>
>> On 07/28/2010 11:20 PM, Steve Chen wrote:
>>> Hello,
>>>
>>> The TAHI correspondent node tests CN-6-4-1 (Processing in upper layer
>>> - Echo Checksum) failed for me in the 2.6.32 kernel. It appears that
>>> the Linux kernel is replying the ICMP echo request in
>>> icmpv6_echo_reply without much checking. Is this an intentional
>>> non-conformance to RFC3775 section 9.3.1?
>>
>> Sorry for the late reply. I've run these tests in the past against
>> SLES11 (2.6.27 ?) back in January 2009 and this one passed from looking
>> at my logs. I don't have that system around anymore to check the config,
>> etc. I didn't see any obvious commit that would have broken it from a
>> quick look, do you have a test setup to do some debugging? It will
>> take a little time for me to re-configure mine to run this test.
>
> Brian,
>
> I'm using mip6d from git://www.umip.org/git/umip.git commit id
> d1c240f3deb690af902ce1ff128780551ff6141c. Is that the correct version
> to use? Looking at the kernel code again, the checksum error should
> have been caught in icmpv6_rcv. There are probably something wrong
> with my setup. I'll dig around a bit more.
>
> Tests 5-3-1 to 5-3-6 also failed for me. Did they pass for you?
By the way, these tests passed for me with the following patch.
Please let me know what you think.
Thanks
Steve
[-- Attachment #2: h_bit_check.patch --]
[-- Type: text/x-patch, Size: 592 bytes --]
Reinstate checks to handle BU with H bit set
Check for the H flag was omitted in 2276ddec36a3789826842ac8316553fa0702ea89.
This caused TAHI correcpondend node tests 118-123 (5.3. Receiving BU with
(H)bit is set) to fail.
diff --git a/src/cn.c b/src/cn.c
index 0318e9e..a036d96 100644
--- a/src/cn.c
+++ b/src/cn.c
@@ -173,6 +173,10 @@ static int cn_bu_check(struct ip6_mh_binding_update *bu, ssize_t len,
int ret;
non_ind = mh_opt(&bu->ip6mhbu_hdr, mh_opts, IP6_MHOPT_NONCEID);
+
+ if (bu->ip6mhbu_flags & IP6_MH_BU_HOME)
+ return non_ind ? -1 : 0;
+
if (!non_ind)
return -1;
^ permalink raw reply related
* RE: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
From: Wang, Qi @ 2010-08-13 0:23 UTC (permalink / raw)
To: Wolfgang Grandegger
Cc: Daniel Baluta, Masayuki Ohtak, meego-dev@meego.com,
socketcan-core@lists.berlios.de, netdev@vger.kernel.org,
Khor, Andrew Chih Howe, gregkh@suse.de, arjan@linux.intel.com,
Wang, Yong Y
In-Reply-To: <4C63B8F8.6090106@grandegger.com>
> -----Original Message-----
> From: Wolfgang Grandegger [mailto:wg@grandegger.com]
> Sent: Thursday, August 12, 2010 5:04 PM
> To: Wang, Qi
> Cc: Daniel Baluta; Masayuki Ohtak; meego-dev@meego.com;
> socketcan-core@lists.berlios.de; netdev@vger.kernel.org; Khor, Andrew Chih
> Howe; gregkh@suse.de; arjan@linux.intel.com; Wang, Yong Y
> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
>
> On 08/12/2010 03:42 AM, Wang, Qi wrote:
> >> -----Original Message-----
> >> From: Daniel Baluta [mailto:daniel.baluta@gmail.com]
> >> Sent: Wednesday, August 11, 2010 6:37 PM
> >> To: Masayuki Ohtak
> >> Cc: meego-dev@meego.com; Wolfgang Grandegger;
> >> socketcan-core@lists.berlios.de; netdev@vger.kernel.org; Khor, Andrew
> Chih
> >> Howe; gregkh@suse.de; arjan@linux.intel.com; Wang, Qi; Wang, Yong Y
> >> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> >>
> >> Hi,
> >>
> >> 2010/8/11 Masayuki Ohtak <masa-korg@dsn.okisemi.com>:
> >>> CAN driver of Topcliff PCH
> >>>
> >>> Topcliff PCH is the platform controller hub that is going to be used in
> >>> Intel's upcoming general embedded platform. All IO peripherals in
> >>> Topcliff PCH are actually devices sitting on AMBA bus.
> >>> Topcliff PCH has CAN I/F. This driver enables CAN function.
> >>>
> >>> Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> >>
> >> I have a few questions:
> >>
> >> 1. Is your code based on Intel's CAN EP80579 ([1]) ?
> > No.
>
> For curiosity, is the controller similar to the OKI MSM9225 or ML9620?
The Topcliff IOH is developed by OKI actually.
>
> >> 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
> > Just take a look at kfifo.h. This structure has been changed. I remembered
> there was a spin_lock from kfifo previously. Currently it's been removed, good.
> > OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to
> use this structure and APIs?
>
> As I see it, the code related to that fifo is not used (== dead code)?
I'm not familiar with kfifo structure, and I didn't like it because there need a spin_lock to use it.
>
> > Daniel,
> >
> > We're anxious to integrate those codes now. Perhaps it'll take us quite a long
> time to use kfifo. How about implementing it with the next version?
>
> See above. What do you mean with the next version. The driver posted by
> Masayuki is far away from being accepted as it does not yet comply with
> the Socket-CAN driver API, to say the least.
I've few experience on CAN driver and it's also the first time for OKI-san to write Can driver. Would you please give us a reference and we'll follow it up. We only read 'can.txt' from kernel document. Thank you for your help in advance.
>
> Wolfgang.
^ permalink raw reply
* Re: [PATCH 2/2] platform: Facilitate the creation of pseudo-platform buses
From: Patrick Pannuto @ 2010-08-13 1:13 UTC (permalink / raw)
To: Patrick Pannuto
Cc: linux-kernel, linux-arm-msm, magnus.damm, grant.likely, gregkh,
Kevin Hilman, Paul Mundt, Magnus Damm, Rafael J. Wysocki,
Eric Miao, Dmitry Torokhov, netdev
In-Reply-To: <1281484174-32174-3-git-send-email-ppannuto@codeaurora.org>
On 08/10/2010 04:49 PM, Patrick Pannuto wrote:
> (lkml.org seems to have lost August 3rd...)
> RFC: http://lkml.indiana.edu/hypermail//linux/kernel/1008.0/01342.html
> v1: http://lkml.indiana.edu/hypermail//linux/kernel/1008.0/01942.html
>
> Based on the idea and code originally proposed by Kevin Hilman:
> http://www.mail-archive.com/linux-omap@vger.kernel.org/msg31161.html
>
> Changes from v1:
>
> * "Pseduo" buses are no longer init'd, they are [un]registered by:
> - pseudo_platform_bus_register(struct bus_type *)
> - pseudo_platform_bus_unregister(struct bus_type *)
> * These registrations [de]allocate a dev_pm_ops structure for the
> pseudo bus_type
> * Do not overwrite the parent if .bus is already set (that is, allow
> pseudo bus devices to be root devices)
>
> * Split into 2 patches:
> - 1/2: Already sent separately, but included here for clarity
> - 2/2: The real meat of the patch (this patch)
>
> INTRO
>
> As SOCs become more popular, the desire to quickly define a simple,
> but functional, bus type with only a few unique properties becomes
> desirable. As they become more complicated, the ability to nest these
> simple busses and otherwise orchestrate them to match the actual
> topology also becomes desirable.
>
> EXAMPLE USAGE
>
> /arch/ARCH/MY_ARCH/my_bus.c:
>
> #include <linux/device.h>
> #include <linux/platform_device.h>
>
> struct bus_type SOC_bus_type = {
> .name = "SOC-bus-type",
> };
> EXPORT_SYMBOL_GPL(SOC_bus_type);
>
> struct platform_device SOC_bus1 = {
> .name = "SOC-bus1",
> .id = -1,
> .dev.bus = &SOC_bus_type;
> };
> EXPORT_SYMBOL_GPL(SOC_bus1);
>
> struct platform_device SOC_bus2 = {
> .name = "SOC-bus2",
> .id = -2,
> .dev.bus = &SOC_bus_type;
> };
> EXPORT_SYMBOL_GPL(SOC_bus2);
>
> static int __init SOC_bus_init(void)
> {
> int error;
>
> error = pseudo_platform_bus_register(&SOC_bus_type);
> if (error)
> return error;
>
> error = platform_device_register(&SOC_bus1);
> if (error)
> goto fail_bus1;
>
> error = platform_device_register(&SOC_bus2);
> if (error)
> goto fail_bus2;
>
> return error;
>
> /* platform_device_unregister(&SOC_bus2); */
> fail_bus2:
> platform_device_unregister(&SOC_bus1);
> fail_bus1:
> pseudo_platform_bus_unregister(&SOC_bus_type);
>
> return error;
> }
>
> /drivers/my_driver.c:
> static struct platform_driver my_driver = {
> .driver = {
> .name = "my-driver",
> .owner = THIS_MODULE,
> .bus = &SOC_bus_type,
> },
> };
>
> /somewhere/my_device.c:
> static struct platform_device my_device = {
> .name = "my-device",
> .id = -1,
> .dev.bus = &my_bus_type,
> .dev.parent = &SOC_bus1.dev,
> };
>
> This will build a device tree that mirrors the actual system:
>
> /sys/bus
> |-- SOC-bus-type
> | |-- devices
> | | |-- SOC_bus1 -> ../../../devices/SOC_bus1
> | | |-- SOC_bus2 -> ../../../devices/SOC_bus2
> | | |-- my-device -> ../../../devices/SOC_bus1/my-device
> | |-- drivers
> | | |-- my-driver
>
> /sys/devices
> |-- SOC_bus1
> | |-- my-device
> |-- SOC_bus2
>
> Driver can drive any device on the SOC, which is logical, without
> actually being registered on multiple /bus_types/, even though the
> devices may be on different /physical buses/ (which are actually
> just devices).
>
> THOUGHTS:
>
> 1.
> Notice that for a device / driver, only 3 lines were added to
> switch from the platform bus to the new SOC_bus. This is
> especially valuable if we consider supporting a legacy SOCs
> and new SOCs where the same driver is used, but may need to
> be on either the platform bus or the new SOC_bus. The above
> code then becomes:
>
> (possibly in a header)
> #ifdef CONFIG_MY_BUS
> #define MY_BUS_TYPE &SOC_bus_type
> #else
> #define MY_BUS_TYPE NULL
> #endif
>
> /drivers/my_driver.c
> static struct platform_driver my_driver = {
> .driver = {
> .name = "my-driver",
> .owner = THIS_MODULE,
> .bus = MY_BUS_TYPE,
> },
> };
>
> Which will allow the same driver to easily to used on either
> the platform bus or the newly defined bus type.
>
> 2.
> Implementations wishing to make dynamic / run-time decisions on where
> devices are placed could easily create wrapper functions, that is
>
> int SOC_device_register(struct platform_device *pdev)
> {
> if (pdev->archdata->flag)
> pdev->dev.parent = &SOC_bus1.dev;
> else
> pdev->dev.parent = &SOC_bus2.dev;
>
> return platform_device_register(pdev);
> }
>
> A similar solution also would allow for run-time determination of dev.bus,
> if that were necessary for your platform.
>
> 3.
> I'm not convinced that dynamically allocating a new copy of dev_pm_ops is
> the best solution. I *AM*, however, convinced that removing const from
> struct bus_type {
> ...
> const struct dev_pm_ops *pm;
> ...
> };
> would be a mistake; it is far too easy to overwrite one of the function
> pointers on accident, and the const serves a very useful purpose here.
>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Signed-off-by: Patrick Pannuto <ppannuto@codeaurora.org>
> ---
> drivers/base/platform.c | 92 +++++++++++++++++++++++++++++++++++++-
> include/linux/platform_device.h | 3 +
> 2 files changed, 92 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> index b69ccb4..933e0c1 100644
> --- a/drivers/base/platform.c
> +++ b/drivers/base/platform.c
> @@ -238,8 +238,12 @@ int platform_device_add(struct platform_device *pdev)
> if (!pdev)
> return -EINVAL;
>
> - if (!pdev->dev.parent)
> - pdev->dev.parent = &platform_bus;
> + if (!pdev->dev.bus) {
> + pdev->dev.bus = &platform_bus_type;
> +
> + if (!pdev->dev.parent)
> + pdev->dev.parent = &platform_bus;
> + }
>
> pdev->dev.bus = &platform_bus_type;
^^^ small bug here, this line should be deleted; any other comments though?
>
> @@ -482,7 +486,8 @@ static void platform_drv_shutdown(struct device *_dev)
> */
> int platform_driver_register(struct platform_driver *drv)
> {
> - drv->driver.bus = &platform_bus_type;
> + if (!drv->driver.bus)
> + drv->driver.bus = &platform_bus_type;
> if (drv->probe)
> drv->driver.probe = platform_drv_probe;
> if (drv->remove)
> @@ -1017,6 +1022,87 @@ struct bus_type platform_bus_type = {
> };
> EXPORT_SYMBOL_GPL(platform_bus_type);
>
> +/** pseudo_platform_bus_register - register an "almost platform bus"
> + * @bus: partially complete bus type to register
> + *
> + * This init will fill in any ommitted fields in @bus, however, it
> + * also allocates memory and replaces the pm field in @bus, since
> + * pm is const, but some of its pointers may need this one-time
> + * initialziation overwrite.
> + *
> + * @bus's registered this way should be released with
> + * pseudo_platform_bus_unregister
> + */
> +int pseudo_platform_bus_register(struct bus_type *bus)
> +{
> + int error;
> + struct dev_pm_ops* heap_pm;
> + heap_pm = kmalloc(sizeof (*heap_pm), GFP_KERNEL);
> +
> + if (!heap_pm)
> + return -ENOMEM;
> +
> + if (!bus->dev_attrs)
> + bus->dev_attrs = platform_bus_type.dev_attrs;
> + if (!bus->match)
> + bus->match = platform_bus_type.match;
> + if (!bus->uevent)
> + bus->uevent = platform_bus_type.uevent;
> + if (!bus->pm)
> + memcpy(heap_pm, &platform_bus_type.pm, sizeof(*heap_pm));
> + else {
> + heap_pm->prepare = (bus->pm->prepare) ?
> + bus->pm->prepare : platform_pm_prepare;
> + heap_pm->complete = (bus->pm->complete) ?
> + bus->pm->complete : platform_pm_complete;
> + heap_pm->suspend = (bus->pm->suspend) ?
> + bus->pm->suspend : platform_pm_suspend;
> + heap_pm->resume = (bus->pm->resume) ?
> + bus->pm->resume : platform_pm_resume;
> + heap_pm->freeze = (bus->pm->freeze) ?
> + bus->pm->freeze : platform_pm_freeze;
> + heap_pm->thaw = (bus->pm->thaw) ?
> + bus->pm->thaw : platform_pm_thaw;
> + heap_pm->poweroff = (bus->pm->poweroff) ?
> + bus->pm->poweroff : platform_pm_poweroff;
> + heap_pm->restore = (bus->pm->restore) ?
> + bus->pm->restore : platform_pm_restore;
> + heap_pm->suspend_noirq = (bus->pm->suspend_noirq) ?
> + bus->pm->suspend_noirq : platform_pm_suspend_noirq;
> + heap_pm->resume_noirq = (bus->pm->resume_noirq) ?
> + bus->pm->resume_noirq : platform_pm_resume_noirq;
> + heap_pm->freeze_noirq = (bus->pm->freeze_noirq) ?
> + bus->pm->freeze_noirq : platform_pm_freeze_noirq;
> + heap_pm->thaw_noirq = (bus->pm->thaw_noirq) ?
> + bus->pm->thaw_noirq : platform_pm_thaw_noirq;
> + heap_pm->poweroff_noirq = (bus->pm->poweroff_noirq) ?
> + bus->pm->poweroff_noirq : platform_pm_poweroff_noirq;
> + heap_pm->restore_noirq = (bus->pm->restore_noirq) ?
> + bus->pm->restore_noirq : platform_pm_restore_noirq;
> + heap_pm->runtime_suspend = (bus->pm->runtime_suspend) ?
> + bus->pm->runtime_suspend : platform_pm_runtime_suspend;
> + heap_pm->runtime_resume = (bus->pm->runtime_resume) ?
> + bus->pm->runtime_resume : platform_pm_runtime_resume;
> + heap_pm->runtime_idle = (bus->pm->runtime_idle) ?
> + bus->pm->runtime_idle : platform_pm_runtime_idle;
> + }
> + bus->pm = heap_pm;
> +
> + error = bus_register(bus);
> + if (error)
> + kfree(bus->pm);
> +
> + return error;
> +}
> +EXPORT_SYMBOL_GPL(pseudo_platform_bus_register);
> +
> +void pseudo_platform_bus_unregister(struct bus_type *bus)
> +{
> + bus_unregister(bus);
> + kfree(bus->pm);
> +}
> +EXPORT_SYMBOL_GPL(pseudo_platform_bus_unregister);
> +
> int __init platform_bus_init(void)
> {
> int error;
> diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
> index 5417944..5ec827c 100644
> --- a/include/linux/platform_device.h
> +++ b/include/linux/platform_device.h
> @@ -79,6 +79,9 @@ extern int platform_driver_probe(struct platform_driver *driver,
> #define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev)
> #define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data))
>
> +extern int pseudo_platform_bus_register(struct bus_type *);
> +extern void pseudo_platform_bus_unregister(struct bus_type *);
> +
> extern struct platform_device *platform_create_bundle(struct platform_driver *driver,
> int (*probe)(struct platform_device *),
> struct resource *res, unsigned int n_res,
--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply
* Re: e1000e crashes with 2.6.34.x and ThinkPad T60
From: Marc Haber @ 2010-08-13 1:25 UTC (permalink / raw)
To: Allan, Bruce W
Cc: Tantilov, Emil S, Linux Kernel Developers,
Linux Kernel Network Developers, e1000-devel@lists.sf.net
In-Reply-To: <8DD2590731AB5D4C9DBF71A877482A900164D9279F@orsmsx509.amr.corp.intel.com>
Hi Bruce,
On Tue, Aug 10, 2010 at 09:34:52AM -0700, Allan, Bruce W wrote:
> We have had other recent reports of issues with this part that are due to
> ASPM L1 being enabled. Would you please try disabling L1 after the driver
> is loaded as follows (assuming your adapter is still PCI bus/device/number
> 02:00.0 as indicated in the lspci output you provided earlier):
> 1) First check the hexadecimal value of the LnkCtl register -
> # setpci -s 2:0.0 0xf0
> 2) Disable ASPM (both L0s and L1) by zeroing out bits 0 and 1 in the value
> returned by the previous step. For example, if it returned 42 (hex 42,
> that is) -
> # setpci -s 2:0.0 0xf0=0x40
> 3) Confirm ASPM is disabled by checking the output from lspci again.
It returned 42, and after setting 0x40, LnkCtl now says "ASPM Disabled".
I'll dock the system now and will report after the weekend or after
the first crash.
Greetings
Marc
--
-----------------------------------------------------------------------------
Marc Haber | "I don't trust Computers. They | Mailadresse im Header
Mannheim, Germany | lose things." Winona Ryder | Fon: *49 621 72739834
Nordisch by Nature | How to make an American Quilt | Fax: *49 3221 2323190
^ permalink raw reply
* Re: TAHI CN-6-4-1 failed on Linux 2.6.32 kernel
From: Brian Haley @ 2010-08-13 2:23 UTC (permalink / raw)
To: Steve Chen; +Cc: usagi-users-ctl, netdev
In-Reply-To: <AANLkTik5JOupTW97ikf1imsZrkmwgfPNsvBoSZp1S8JV@mail.gmail.com>
On 08/12/2010 07:04 PM, Steve Chen wrote:
> On Thu, Aug 12, 2010 at 4:10 PM, Brian Haley <brian.haley@hp.com> wrote:
>> Hi Steve,
>>
>> On 07/28/2010 11:20 PM, Steve Chen wrote:
>>> Hello,
>>>
>>> The TAHI correspondent node tests CN-6-4-1 (Processing in upper layer
>>> - Echo Checksum) failed for me in the 2.6.32 kernel. It appears that
>>> the Linux kernel is replying the ICMP echo request in
>>> icmpv6_echo_reply without much checking. Is this an intentional
>>> non-conformance to RFC3775 section 9.3.1?
>>
>> Sorry for the late reply. I've run these tests in the past against
>> SLES11 (2.6.27 ?) back in January 2009 and this one passed from looking
>> at my logs. I don't have that system around anymore to check the config,
>> etc. I didn't see any obvious commit that would have broken it from a
>> quick look, do you have a test setup to do some debugging? It will
>> take a little time for me to re-configure mine to run this test.
>
> Brian,
>
> I'm using mip6d from git://www.umip.org/git/umip.git commit id
> d1c240f3deb690af902ce1ff128780551ff6141c. Is that the correct version
> to use? Looking at the kernel code again, the checksum error should
> have been caught in icmpv6_rcv. There are probably something wrong
> with my setup. I'll dig around a bit more.
The system has long since been dismantled, so I'm not sure what version
of mip6d I used. Yes, icmpv6_rcv() does check for checksum errors, it
would be good to print-out three addresses to see which one is which,
in case they weren't swapped correctly or something. It would be good
to know what value skb->ip_summed was too, as a start.
> Tests 5-3-1 to 5-3-6 also failed for me. Did they pass for you?
I had no failures, but 5 warnings (2-1-6, 2-3-11, 4-7-1, 5-4-2, and
6-3-1). I'll see if I can get a CN test run done on my current
config.
-Brian
^ permalink raw reply
* dccp test-tree [PATCH 0/3] ccid-2: Congestion Window Validation, TCP code sharing
From: Gerrit Renker @ 2010-08-13 5:21 UTC (permalink / raw)
To: dccp; +Cc: netdev
In-Reply-To: <ccid2_cwv_dccp_test_tree>
This is a small set to enhance CCID-2, consisting mainly of Congestion Window
Validation (RFC 2681) ported over from TCP.
The first patch allows to make the TCP minimum RTO visible also to CCID-2. Since
CCID-3 also uses RTO (in the formula and for the nofeedback timer), I wonder
whether we should also do the same for CCID-3??
The changeset is:
Patch #1: makes TCP's minimum-RTO code available to CCID-2
Patch #2: simplifies the code by using an existing function
Patch #3: implements CWV for CCID-2 -- largely taken from TCP
The patches have been dusted off from my development tree. They have been tested,
though it is some time ago. Hence I'd very much appreciate review and comments.
git://eden-feed.erg.abdn.ac.uk/dccp_exp [subtree 'dccp']
^ permalink raw reply
* [PATCH 1/3] dccp ccid-2: Share TCP's minimum RTO code
From: Gerrit Renker @ 2010-08-13 5:21 UTC (permalink / raw)
To: dccp; +Cc: netdev, Gerrit Renker
In-Reply-To: <1281676901-7018-1-git-send-email-gerrit@erg.abdn.ac.uk>
Over the same link, DCCP and TCP face similar problems; and DCCP's
CCID-2 is in fact a restricted form of TCP.
Using the same RTO_MIN of 0.2 seconds was found to cause problems for CCID-2
over 802.11g: at least once per session there is a spurious timeout. It helped
to then increase the the value of RTO_MIN over this link.
Since the problem is the same as in TCP, this patch makes the solution from
commit "05bb1fad1cde025a864a90cfeb98dcbefe78a44a"
"[TCP]: Allow minimum RTO to be configurable via routing metrics."
available to DCCP.
This avoids reinventing the wheel, so that e.g. the following works in the
expected way now also for DCCP:
> ip route change 10.0.0.2 rto_min 800 dev ath0
Luckily this useful rto_min function was recently moved to net/tcp.h,
which simplifies sharing code originating from TCP.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
net/dccp/ccids/ccid2.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -267,8 +267,9 @@ static void ccid2_rtt_estimator(struct sock *sk, const long mrtt)
hc->tx_srtt = m << 3;
hc->tx_mdev = m << 1;
- hc->tx_mdev_max = max(TCP_RTO_MIN, hc->tx_mdev);
+ hc->tx_mdev_max = max(hc->tx_mdev, tcp_rto_min(sk));
hc->tx_rttvar = hc->tx_mdev_max;
+
hc->tx_rtt_seq = dccp_sk(sk)->dccps_gss;
} else {
/* Update scaled SRTT as SRTT += 1/8 * (m - SRTT) */
@@ -309,7 +310,7 @@ static void ccid2_rtt_estimator(struct sock *sk, const long mrtt)
hc->tx_rttvar -= (hc->tx_rttvar -
hc->tx_mdev_max) >> 2;
hc->tx_rtt_seq = dccp_sk(sk)->dccps_gss;
- hc->tx_mdev_max = TCP_RTO_MIN;
+ hc->tx_mdev_max = tcp_rto_min(sk);
}
}
^ permalink raw reply
* [PATCH 2/3] dccp ccid-2: Use existing function to test for data packets
From: Gerrit Renker @ 2010-08-13 5:21 UTC (permalink / raw)
To: dccp; +Cc: netdev, Gerrit Renker
In-Reply-To: <1281676901-7018-2-git-send-email-gerrit@erg.abdn.ac.uk>
This replaces a switch statement with a test using the equivalent function
dccp_data_packet(skb).
It also doubles the range of the field `rx_num_data_pkts' by changing the
type from `int' to `u32' (avoiding signed/unsigned comparison with the u16
field `dccps_r_ack_ratio').
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
net/dccp/ccids/ccid2.h | 6 +++++-
net/dccp/ccids/ccid2.c | 16 ++++++----------
2 files changed, 11 insertions(+), 11 deletions(-)
--- a/net/dccp/ccids/ccid2.h
+++ b/net/dccp/ccids/ccid2.h
@@ -88,8 +88,12 @@ static inline bool ccid2_cwnd_network_limited(struct ccid2_hc_tx_sock *hc)
return (hc->tx_pipe >= hc->tx_cwnd);
}
+/**
+ * struct ccid2_hc_rx_sock - Receiving end of CCID-2 half-connection
+ * @rx_num_data_pkts: number of data packets received since last feedback
+ */
struct ccid2_hc_rx_sock {
- int rx_data;
+ u32 rx_num_data_pkts;
};
static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk)
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -629,18 +629,14 @@ static void ccid2_hc_tx_exit(struct sock *sk)
static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
- const struct dccp_sock *dp = dccp_sk(sk);
struct ccid2_hc_rx_sock *hc = ccid2_hc_rx_sk(sk);
- switch (DCCP_SKB_CB(skb)->dccpd_type) {
- case DCCP_PKT_DATA:
- case DCCP_PKT_DATAACK:
- hc->rx_data++;
- if (hc->rx_data >= dp->dccps_r_ack_ratio) {
- dccp_send_ack(sk);
- hc->rx_data = 0;
- }
- break;
+ if (!dccp_data_packet(skb))
+ return;
+
+ if (++hc->rx_num_data_pkts >= dccp_sk(sk)->dccps_r_ack_ratio) {
+ dccp_send_ack(sk);
+ hc->rx_num_data_pkts = 0;
}
}
^ permalink raw reply
* [PATCH 3/3] dccp ccid-2: Perform congestion-window validation
From: Gerrit Renker @ 2010-08-13 5:21 UTC (permalink / raw)
To: dccp; +Cc: netdev, Gerrit Renker
In-Reply-To: <1281676901-7018-3-git-send-email-gerrit@erg.abdn.ac.uk>
CCID-2's cwnd increases exponentially during slow-start, like TCP.
This growth of cwnd has implications for
* the local Sequence Window value (should be > cwnd),
* the Ack Ratio value.
Hence an exponential growth, if it does not reflect the actual network
conditions, can quickly lead to instability (in fact this was observed, after
a long application-limited time the sender suddenly threw out a huge burst of
packets which lead to the receiver getting out of synch).
This patch adds congestion-window validation (RFC2861) to CCID-2:
* cwnd is constrained if the sender is application limited;
* cwnd is reduced after a long idle period, as suggested in the '90 paper
by Van Jacobson, in RFC 2581 (sec. 4.1);
* cwnd is never reduced below the RFC 3390 initial window.
As marked in the comments, the code is actually almost a direct copy of the
TCP congestion-window-validation algorithms. By continuing this work, it may
in future be possible to use the TCP code (not possible at the moment).
The mechanism can be turned off using a module parameter. Sampling of the
currently-used window (moving-maximum) is however done constantly, this is
used to determine the expected window, which can be exploited to regulate
DCCP's Sequence Window value.
This patch also sets slow-start-after-idle (RFC 4341, 5.1), i.e. it behaves like
TCP when net.ipv4.tcp_slow_start_after_idle = 1.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
net/dccp/ccids/ccid2.h | 10 ++++++
net/dccp/ccids/ccid2.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 91 insertions(+), 3 deletions(-)
--- a/net/dccp/ccids/ccid2.h
+++ b/net/dccp/ccids/ccid2.h
@@ -53,6 +53,10 @@ struct ccid2_seq {
* @tx_rttvar: moving average/maximum of @mdev_max
* @tx_rto: RTO value deriving from SRTT and RTTVAR (RFC 2988)
* @tx_rtt_seq: to decay RTTVAR at most once per flight
+ * @tx_cwnd_used: actually used cwnd, W_used of RFC 2861
+ * @tx_expected_wnd: moving average of @tx_cwnd_used
+ * @tx_cwnd_stamp: to track idle periods in CWV
+ * @tx_lsndtime: last time (in jiffies) a data packet was sent
* @tx_rpseq: last consecutive seqno
* @tx_rpdupack: dupacks since rpseq
* @tx_av_chunks: list of Ack Vectors received on current skb
@@ -76,6 +80,12 @@ struct ccid2_hc_tx_sock {
u64 tx_rtt_seq:48;
struct timer_list tx_rtotimer;
+ /* Congestion Window validation (optional, RFC 2861) */
+ u32 tx_cwnd_used,
+ tx_expected_wnd,
+ tx_cwnd_stamp,
+ tx_lsndtime;
+
u64 tx_rpseq;
int tx_rpdupack;
u32 tx_last_cong;
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -153,17 +153,93 @@ out:
sock_put(sk);
}
+/*
+ * Congestion window validation (RFC 2861).
+ */
+static int ccid2_do_cwv = 1;
+module_param(ccid2_do_cwv, bool, 0644);
+MODULE_PARM_DESC(ccid2_do_cwv, "Perform RFC2861 Congestion Window Validation");
+
+/**
+ * ccid2_update_used_window - Track how much of cwnd is actually used
+ * This is done in addition to CWV. The sender needs to have an idea of how many
+ * packets may be in flight, to set the local Sequence Window value accordingly
+ * (RFC 4340, 7.5.2). The CWV mechanism is exploited to keep track of the
+ * maximum-used window. We use an EWMA low-pass filter to filter out noise.
+ */
+static void ccid2_update_used_window(struct ccid2_hc_tx_sock *hc, u32 new_wnd)
+{
+ hc->tx_expected_wnd = (3 * hc->tx_expected_wnd + new_wnd) / 4;
+}
+
+/* This borrows the code of tcp_cwnd_application_limited() */
+static void ccid2_cwnd_application_limited(struct sock *sk, const u32 now)
+{
+ struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
+ /* don't reduce cwnd below the initial window (IW) */
+ u32 init_win = rfc3390_bytes_to_packets(dccp_sk(sk)->dccps_mss_cache),
+ win_used = max(hc->tx_cwnd_used, init_win);
+
+ if (win_used < hc->tx_cwnd) {
+ hc->tx_ssthresh = max(hc->tx_ssthresh,
+ (hc->tx_cwnd >> 1) + (hc->tx_cwnd >> 2));
+ hc->tx_cwnd = (hc->tx_cwnd + win_used) >> 1;
+ }
+ hc->tx_cwnd_used = 0;
+ hc->tx_cwnd_stamp = now;
+}
+
+/* This borrows the code of tcp_cwnd_restart() */
+static void ccid2_cwnd_restart(struct sock *sk, const u32 now)
+{
+ struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
+ u32 cwnd = hc->tx_cwnd, restart_cwnd,
+ iwnd = rfc3390_bytes_to_packets(dccp_sk(sk)->dccps_mss_cache);
+
+ hc->tx_ssthresh = max(hc->tx_ssthresh, (cwnd >> 1) + (cwnd >> 2));
+
+ /* don't reduce cwnd below the initial window (IW) */
+ restart_cwnd = min(cwnd, iwnd);
+ cwnd >>= (now - hc->tx_lsndtime) / hc->tx_rto;
+ hc->tx_cwnd = max(cwnd, restart_cwnd);
+
+ hc->tx_cwnd_stamp = now;
+ hc->tx_cwnd_used = 0;
+}
+
static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
{
struct dccp_sock *dp = dccp_sk(sk);
struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
+ const u32 now = ccid2_time_stamp;
struct ccid2_seq *next;
- hc->tx_pipe++;
+ /* slow-start after idle periods (RFC 2581, RFC 2861) */
+ if (ccid2_do_cwv && !hc->tx_pipe &&
+ (s32)(now - hc->tx_lsndtime) >= hc->tx_rto)
+ ccid2_cwnd_restart(sk, now);
+
+ hc->tx_lsndtime = now;
+ hc->tx_pipe += 1;
+
+ /* see whether cwnd was fully used (RFC 2861), update expected window */
+ if (ccid2_cwnd_network_limited(hc)) {
+ ccid2_update_used_window(hc, hc->tx_cwnd);
+ hc->tx_cwnd_used = 0;
+ hc->tx_cwnd_stamp = now;
+ } else {
+ if (hc->tx_pipe > hc->tx_cwnd_used)
+ hc->tx_cwnd_used = hc->tx_pipe;
+
+ ccid2_update_used_window(hc, hc->tx_cwnd_used);
+
+ if (ccid2_do_cwv && (s32)(now - hc->tx_cwnd_stamp) >= hc->tx_rto)
+ ccid2_cwnd_application_limited(sk, now);
+ }
hc->tx_seqh->ccid2s_seq = dp->dccps_gss;
hc->tx_seqh->ccid2s_acked = 0;
- hc->tx_seqh->ccid2s_sent = ccid2_time_stamp;
+ hc->tx_seqh->ccid2s_sent = now;
next = hc->tx_seqh->ccid2s_next;
/* check if we need to alloc more space */
@@ -596,6 +672,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
/* Use larger initial windows (RFC 3390, rfc2581bis) */
hc->tx_cwnd = rfc3390_bytes_to_packets(dp->dccps_mss_cache);
+ hc->tx_expected_wnd = hc->tx_cwnd;
/* Make sure that Ack Ratio is enabled and within bounds. */
max_ratio = DIV_ROUND_UP(hc->tx_cwnd, 2);
@@ -608,7 +685,8 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
hc->tx_rto = DCCP_TIMEOUT_INIT;
hc->tx_rpdupack = -1;
- hc->tx_last_cong = ccid2_time_stamp;
+ hc->tx_last_cong = hc->tx_lsndtime = hc->tx_cwnd_stamp = ccid2_time_stamp;
+ hc->tx_cwnd_used = 0;
setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire,
(unsigned long)sk);
INIT_LIST_HEAD(&hc->tx_av_chunks);
^ permalink raw reply
* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
From: Daniel Baluta @ 2010-08-13 6:11 UTC (permalink / raw)
To: Wang, Qi
Cc: Khor, Andrew Chih Howe,
socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
gregkh-l3A5Bk7waGM@public.gmane.org, Wang, Yong Y, Masayuki Ohtak,
meego-dev-WXzIur8shnEAvxtiuMwx3w@public.gmane.org,
arjan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org,
Wolfgang Grandegger
In-Reply-To: <D5AB6E638E5A3E4B8F4406B113A5A19A28EA2AB1-QQHDSDV1ERZpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
Hi,
> I'm not familiar with kfifo structure, and I didn't like it because there need a spin_lock to use it.
It seems that you don't need to use your own kfifo. Socket-CAN core has
it's internal queues, you only have to fit in this infrastructure.
>>
>> > Daniel,
>> >
>> > We're anxious to integrate those codes now. Perhaps it'll take us quite a long
>> time to use kfifo. How about implementing it with the next version?
>>
>> See above. What do you mean with the next version. The driver posted by
>> Masayuki is far away from being accepted as it does not yet comply with
>> the Socket-CAN driver API, to say the least.
> I've few experience on CAN driver and it's also the first time for OKI-san to write Can driver. Would you please give us a reference and we'll follow it up. We only read 'can.txt' from kernel document. Thank you for your help in advance.
Oliver's email should be your starting point. Read the code from net/can and see
how other drivers are built.
As I previously said I'm interested in writing a driver for CAN
EP80579 controller,
but the start is pretty slow. Since your controller seems to be pretty
similar we
can do some things in common.
I can help you, if you send me a pointer to your CAN controller
datasheet + eventually
grant me access to your repo.
thanks,
Daniel.
^ permalink raw reply
* [PATCHv2 NEXT 4/7] qlcnic: add eswitch statistics support
From: Amit Kumar Salecha @ 2010-08-13 6:57 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman
In-Reply-To: <1281682646-15990-1-git-send-email-amit.salecha@qlogic.com>
Adding eswitch statistics support. User can get
whole eswitch stats or stats of func belong to that eswitch.
Added:
o command to get statistics of eswitch and function.
o sysfs support to export eswitch and func statatistics.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 31 +++++++++
drivers/net/qlcnic/qlcnic_ctx.c | 125 ++++++++++++++++++++++++++++++++++++
drivers/net/qlcnic/qlcnic_main.c | 132 +++++++++++++++++++++++++++++++++++++-
3 files changed, 287 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 9703893..7f4e11b 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -555,6 +555,7 @@ struct qlcnic_recv_context {
#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026
#define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027
#define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028
+#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a
#define QLCNIC_RCODE_SUCCESS 0
#define QLCNIC_RCODE_TIMEOUT 17
@@ -1126,6 +1127,31 @@ struct qlcnic_esw_func_cfg {
u8 reserved;
};
+#define QLCNIC_STATS_VERSION 1
+#define QLCNIC_STATS_PORT 1
+#define QLCNIC_STATS_ESWITCH 2
+#define QLCNIC_QUERY_RX_COUNTER 0
+#define QLCNIC_QUERY_TX_COUNTER 1
+struct __qlcnic_esw_statistics {
+ __le16 context_id;
+ __le16 version;
+ __le16 size;
+ __le16 unused;
+ __le64 unicast_frames;
+ __le64 multicast_frames;
+ __le64 broadcast_frames;
+ __le64 dropped_frames;
+ __le64 errors;
+ __le64 local_frames;
+ __le64 numbytes;
+ __le64 rsvd[3];
+};
+
+struct qlcnic_esw_statistics {
+ struct __qlcnic_esw_statistics rx;
+ struct __qlcnic_esw_statistics tx;
+};
+
int qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val);
int qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val);
@@ -1252,6 +1278,11 @@ int qlcnic_toggle_eswitch(struct qlcnic_adapter *, u8, u8);
int qlcnic_config_switch_port(struct qlcnic_adapter *, u8, int, u8, u8,
u8, u8, u16);
int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8);
+int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8,
+ struct __qlcnic_esw_statistics *);
+int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8,
+ struct __qlcnic_esw_statistics *);
+int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
extern int qlcnic_config_tso;
/*
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index cc5d861..57c9b09 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -983,3 +983,128 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id,
return err;
}
+
+int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
+ const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
+
+ size_t stats_size = sizeof(struct __qlcnic_esw_statistics);
+ dma_addr_t stats_dma_t;
+ void *stats_addr;
+ u32 arg1;
+ int err;
+
+ if (esw_stats == NULL)
+ return -ENOMEM;
+
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC &&
+ func != adapter->ahw.pci_func) {
+ dev_err(&adapter->pdev->dev,
+ "Not privilege to query stats for func=%d", func);
+ return -EIO;
+ }
+
+ stats_addr = pci_alloc_consistent(adapter->pdev, stats_size,
+ &stats_dma_t);
+ if (!stats_addr) {
+ dev_err(&adapter->pdev->dev, "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+ memset(stats_addr, 0, stats_size);
+
+ arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
+ arg1 |= rx_tx << 15 | stats_size << 16;
+
+ err = qlcnic_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ adapter->fw_hal_version,
+ arg1,
+ MSD(stats_dma_t),
+ LSD(stats_dma_t),
+ QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
+
+ if (!err)
+ memcpy(esw_stats, stats_addr, stats_size);
+
+ pci_free_consistent(adapter->pdev, stats_size, stats_addr,
+ stats_dma_t);
+ return err;
+}
+
+int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
+ const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
+
+ struct __qlcnic_esw_statistics port_stats;
+ u8 i;
+ int ret = -EIO;
+
+ if (esw_stats == NULL)
+ return -ENOMEM;
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ return -EIO;
+ if (adapter->npars == NULL)
+ return -EIO;
+
+ memset(esw_stats, 0, sizeof(struct __qlcnic_esw_statistics));
+ esw_stats->context_id = eswitch;
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ if (adapter->npars[i].phy_port != eswitch)
+ continue;
+
+ memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics));
+ if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats))
+ continue;
+
+ esw_stats->size = port_stats.size;
+ esw_stats->version = port_stats.version;
+ esw_stats->unicast_frames += port_stats.unicast_frames;
+ esw_stats->multicast_frames += port_stats.multicast_frames;
+ esw_stats->broadcast_frames += port_stats.broadcast_frames;
+ esw_stats->dropped_frames += port_stats.dropped_frames;
+ esw_stats->errors += port_stats.errors;
+ esw_stats->local_frames += port_stats.local_frames;
+ esw_stats->numbytes += port_stats.numbytes;
+
+ ret = 0;
+ }
+ return ret;
+}
+
+int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
+ const u8 port, const u8 rx_tx)
+{
+
+ u32 arg1;
+
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ return -EIO;
+
+ if (func_esw == QLCNIC_STATS_PORT) {
+ if (port >= QLCNIC_MAX_PCI_FUNC)
+ goto err_ret;
+ } else if (func_esw == QLCNIC_STATS_ESWITCH) {
+ if (port >= QLCNIC_NIU_MAX_XG_PORTS)
+ goto err_ret;
+ } else {
+ goto err_ret;
+ }
+
+ if (rx_tx > QLCNIC_QUERY_TX_COUNTER)
+ goto err_ret;
+
+ arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
+ arg1 |= BIT_14 | rx_tx << 15;
+
+ return qlcnic_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ adapter->fw_hal_version,
+ arg1,
+ 0,
+ 0,
+ QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
+
+err_ret:
+ dev_err(&adapter->pdev->dev, "Invalid argument func_esw=%d port=%d"
+ "rx_ctx=%d\n", func_esw, port, rx_tx);
+ return -EIO;
+}
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index f98c4cf..692641e 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -3368,6 +3368,115 @@ qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
}
static ssize_t
+qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_statistics port_stats;
+ int ret;
+
+ if (size != sizeof(struct qlcnic_esw_statistics))
+ return QL_STATUS_INVALID_PARAM;
+
+ if (offset >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ memset(&port_stats, 0, size);
+ ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+ &port_stats.rx);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+ &port_stats.tx);
+ if (ret)
+ return ret;
+
+ memcpy(buf, &port_stats, size);
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_statistics esw_stats;
+ int ret;
+
+ if (size != sizeof(struct qlcnic_esw_statistics))
+ return QL_STATUS_INVALID_PARAM;
+
+ if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+ return QL_STATUS_INVALID_PARAM;
+
+ memset(&esw_stats, 0, size);
+ ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+ &esw_stats.rx);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+ &esw_stats.tx);
+ if (ret)
+ return ret;
+
+ memcpy(buf, &esw_stats, size);
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int ret;
+
+ if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+ return QL_STATUS_INVALID_PARAM;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+ QLCNIC_QUERY_RX_COUNTER);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+ QLCNIC_QUERY_TX_COUNTER);
+ if (ret)
+ return ret;
+
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int ret;
+
+ if (offset >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+ QLCNIC_QUERY_RX_COUNTER);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+ QLCNIC_QUERY_TX_COUNTER);
+ if (ret)
+ return ret;
+
+ return size;
+}
+
+static ssize_t
qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
{
@@ -3410,6 +3519,20 @@ static struct bin_attribute bin_attr_pci_config = {
.write = NULL,
};
+static struct bin_attribute bin_attr_port_stats = {
+ .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_get_port_stats,
+ .write = qlcnic_sysfs_clear_port_stats,
+};
+
+static struct bin_attribute bin_attr_esw_stats = {
+ .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_get_esw_stats,
+ .write = qlcnic_sysfs_clear_esw_stats,
+};
+
static struct bin_attribute bin_attr_esw_config = {
.attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
.size = 0,
@@ -3449,6 +3572,9 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
+ if (device_create_bin_file(dev, &bin_attr_port_stats))
+ dev_info(dev, "failed to create port stats sysfs entry");
+
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
return;
if (device_create_file(dev, &dev_attr_diag_mode))
@@ -3468,7 +3594,8 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
dev_info(dev, "failed to create esw config sysfs entry");
if (device_create_bin_file(dev, &bin_attr_pm_config))
dev_info(dev, "failed to create pm config sysfs entry");
-
+ if (device_create_bin_file(dev, &bin_attr_esw_stats))
+ dev_info(dev, "failed to create eswitch stats sysfs entry");
}
static void
@@ -3476,6 +3603,8 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
+ device_remove_bin_file(dev, &bin_attr_port_stats);
+
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
return;
device_remove_file(dev, &dev_attr_diag_mode);
@@ -3488,6 +3617,7 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
device_remove_bin_file(dev, &bin_attr_npar_config);
device_remove_bin_file(dev, &bin_attr_esw_config);
device_remove_bin_file(dev, &bin_attr_pm_config);
+ device_remove_bin_file(dev, &bin_attr_esw_stats);
}
#ifdef CONFIG_INET
--
1.6.0.2
^ permalink raw reply related
* [PATCHv2 NEXT 1/7] qlcnic: fix aer for virtual func
From: Amit Kumar Salecha @ 2010-08-13 6:57 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman
In-Reply-To: <1281682646-15990-1-git-send-email-amit.salecha@qlogic.com>
Virtual function are not privilge to initialize firmware.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index b9615bd..9cc8732 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -2723,7 +2723,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
if (qlcnic_api_lock(adapter))
return -EINVAL;
- if (first_func) {
+ if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
adapter->need_fw_reset = 1;
set_bit(__QLCNIC_START_FW, &adapter->state);
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
--
1.6.0.2
^ permalink raw reply related
* [PATCHv2 NEXT 3/7] qlcnic: fix for setting function modes
From: Amit Kumar Salecha @ 2010-08-13 6:57 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Rajesh Borundia
In-Reply-To: <1281682646-15990-1-git-send-email-amit.salecha@qlogic.com>
From: Rajesh Borundia <rajesh.borundia@qlogic.com>
function modes was not working with CNA device, in CNA mode
other function(FCOE) can be enabled before nic.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index b062188..f98c4cf 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -533,8 +533,6 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
ret = qlcnic_api_lock(adapter);
if (ret)
goto err_lock;
- if (QLC_DEV_CLR_REF_CNT(ref_count, adapter->ahw.pci_func))
- goto err_npar;
if (qlcnic_config_npars) {
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
@@ -552,7 +550,6 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
adapter->ahw.pci_func));
}
writel(data, priv_op);
-err_npar:
qlcnic_api_unlock(adapter);
err_lock:
return ret;
--
1.6.0.2
^ permalink raw reply related
* [PATCHv2 NEXT 2/7] qlcnic: device state management fixes for virtual func
From: Amit Kumar Salecha @ 2010-08-13 6:57 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman
In-Reply-To: <1281682646-15990-1-git-send-email-amit.salecha@qlogic.com>
o NPAR state should be set to operationl by Mangement function only.
o NPAR state should be set to non operational before device reset.
o VF function should wait for NPAR state to be operational.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_hdr.h | 5 +-
drivers/net/qlcnic/qlcnic_main.c | 80 +++++++++++++++++++++++---------------
2 files changed, 51 insertions(+), 34 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h
index 15fc320..bd346d9 100644
--- a/drivers/net/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/qlcnic/qlcnic_hdr.h
@@ -718,8 +718,9 @@ enum {
#define QLCNIC_DEV_FAILED 0x6
#define QLCNIC_DEV_QUISCENT 0x7
-#define QLCNIC_DEV_NPAR_NOT_RDY 0
-#define QLCNIC_DEV_NPAR_RDY 1
+#define QLCNIC_DEV_NPAR_NON_OPER 0 /* NON Operational */
+#define QLCNIC_DEV_NPAR_OPER 1 /* NPAR Operational */
+#define QLCNIC_DEV_NPAR_OPER_TIMEO 30 /* Operational time out */
#define QLC_DEV_CHECK_ACTIVE(VAL, FN) ((VAL) &= (1 << (FN * 4)))
#define QLC_DEV_SET_REF_CNT(VAL, FN) ((VAL) |= (1 << (FN * 4)))
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 9cc8732..b062188 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -2388,7 +2388,7 @@ qlcnic_fwinit_work(struct work_struct *work)
{
struct qlcnic_adapter *adapter = container_of(work,
struct qlcnic_adapter, fw_work.work);
- u32 dev_state = 0xf, npar_state;
+ u32 dev_state = 0xf;
if (qlcnic_api_lock(adapter))
goto err_ret;
@@ -2402,16 +2402,8 @@ qlcnic_fwinit_work(struct work_struct *work)
}
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
- npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
- if (npar_state == QLCNIC_DEV_NPAR_RDY) {
- qlcnic_api_unlock(adapter);
- goto wait_npar;
- } else {
- qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
- FW_POLL_DELAY);
- qlcnic_api_unlock(adapter);
- return;
- }
+ qlcnic_api_unlock(adapter);
+ goto wait_npar;
}
if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
@@ -2460,20 +2452,17 @@ wait_npar:
QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
switch (dev_state) {
- case QLCNIC_DEV_QUISCENT:
- case QLCNIC_DEV_NEED_QUISCENT:
- case QLCNIC_DEV_NEED_RESET:
- qlcnic_schedule_work(adapter,
- qlcnic_fwinit_work, FW_POLL_DELAY);
- return;
- case QLCNIC_DEV_FAILED:
- break;
-
- default:
+ case QLCNIC_DEV_READY:
if (!adapter->nic_ops->start_firmware(adapter)) {
qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
return;
}
+ case QLCNIC_DEV_FAILED:
+ break;
+ default:
+ qlcnic_schedule_work(adapter,
+ qlcnic_fwinit_work, FW_POLL_DELAY);
+ return;
}
err_ret:
@@ -2520,6 +2509,22 @@ err_ret:
}
+/*Transit NPAR state to NON Operational */
+static void
+qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter)
+{
+ u32 state;
+
+ state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ if (state == QLCNIC_DEV_NPAR_NON_OPER)
+ return;
+
+ if (qlcnic_api_lock(adapter))
+ return;
+ QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
+ qlcnic_api_unlock(adapter);
+}
+
/*Transit to RESET state from READY state only */
static void
qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
@@ -2538,6 +2543,7 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
qlcnic_idc_debug_info(adapter, 0);
}
+ QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
qlcnic_api_unlock(adapter);
}
@@ -2545,21 +2551,14 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
static void
qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
{
- u32 state;
-
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
- adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
+ adapter->op_mode != QLCNIC_MGMT_FUNC)
return;
if (qlcnic_api_lock(adapter))
return;
- state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
-
- if (state != QLCNIC_DEV_NPAR_RDY) {
- QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
- QLCNIC_DEV_NPAR_RDY);
- QLCDB(adapter, DRV, "NPAR READY state set\n");
- }
+ QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_OPER);
+ QLCDB(adapter, DRV, "NPAR operational state set\n");
qlcnic_api_unlock(adapter);
}
@@ -2621,8 +2620,11 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
qlcnic_dev_request_reset(adapter);
state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
- if (state == QLCNIC_DEV_NEED_RESET || state == QLCNIC_DEV_NEED_QUISCENT)
+ if (state == QLCNIC_DEV_NEED_RESET ||
+ state == QLCNIC_DEV_NEED_QUISCENT) {
+ qlcnic_set_npar_non_operational(adapter);
adapter->need_fw_reset = 1;
+ }
heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
if (heartbit != adapter->heartbit) {
@@ -2812,11 +2814,25 @@ static int
qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
{
int err;
+ u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO;
+ u32 npar_state;
err = qlcnic_can_start_firmware(adapter);
if (err)
return err;
+ npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) {
+ msleep(1000);
+ npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ }
+
+ if (!npar_opt_timeo) {
+ dev_err(&adapter->pdev->dev,
+ "Waiting for NPAR state to opertional timeout\n");
+ return -EIO;
+ }
+
qlcnic_check_options(adapter);
adapter->need_fw_reset = 0;
--
1.6.0.2
^ permalink raw reply related
* [PATCHv2 NEXT 0/7]qlcnic: enhancement and fixes
From: Amit Kumar Salecha @ 2010-08-13 6:57 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman
Hi
Sending v2 series of 7 patches. In previous set of patches author
email id was incorrect and a minor fix in lro/rxcsum patch.
Please ignore v1 patches.
-Amit
^ permalink raw reply
* [PATCHv2 NEXT 7/7] qlcnic: turn off lro when rxcsum is disabled.
From: Amit Kumar Salecha @ 2010-08-13 6:57 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Sucheta Chakraborty
In-Reply-To: <1281682646-15990-1-git-send-email-amit.salecha@qlogic.com>
From: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
o Also dont allow lro to be turn on, if rx csum is disabled
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 1 +
drivers/net/qlcnic/qlcnic_ethtool.c | 23 +++++++++++++++++++++++
drivers/net/qlcnic/qlcnic_main.c | 2 +-
3 files changed, 25 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 7f4e11b..f6b887d 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -894,6 +894,7 @@ struct qlcnic_mac_req {
#define QLCNIC_MSI_ENABLED 0x02
#define QLCNIC_MSIX_ENABLED 0x04
#define QLCNIC_LRO_ENABLED 0x08
+#define QLCNIC_LRO_DISABLED 0x00
#define QLCNIC_BRIDGE_ENABLED 0X10
#define QLCNIC_DIAG_ENABLED 0x20
#define QLCNIC_ESWITCH_ENABLED 0x40
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 3d4655d..e38fc3d 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -818,7 +818,21 @@ static u32 qlcnic_get_rx_csum(struct net_device *dev)
static int qlcnic_set_rx_csum(struct net_device *dev, u32 data)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
+
+ if (!!data) {
+ adapter->rx_csum = !!data;
+ return 0;
+ }
+
+ if (adapter->flags & QLCNIC_LRO_ENABLED) {
+ if (qlcnic_config_hw_lro(adapter, QLCNIC_LRO_DISABLED))
+ return -EIO;
+
+ dev->features &= ~NETIF_F_LRO;
+ qlcnic_send_lro_cleanup(adapter);
+ }
adapter->rx_csum = !!data;
+ dev_info(&adapter->pdev->dev, "disabling LRO as rx_csum is off\n");
return 0;
}
@@ -1001,6 +1015,15 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data)
if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
return -EINVAL;
+ if (!adapter->rx_csum) {
+ dev_info(&adapter->pdev->dev, "rx csum is off, "
+ "cannot toggle lro\n");
+ return -EINVAL;
+ }
+
+ if ((data & ETH_FLAG_LRO) && (adapter->flags & QLCNIC_LRO_ENABLED))
+ return 0;
+
if (data & ETH_FLAG_LRO) {
hw_lro = QLCNIC_LRO_ENABLED;
netdev->features |= NETIF_F_LRO;
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 28985a9..92385e7 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -985,7 +985,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
qlcnic_config_intr_coalesce(adapter);
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+ if (netdev->features & NETIF_F_LRO)
qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED);
qlcnic_napi_enable(adapter);
--
1.6.0.2
^ permalink raw reply related
* [PATCHv2 NEXT 5/7] qlcnic: fix link status message
From: Amit Kumar Salecha @ 2010-08-13 6:57 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Sony Chacko
In-Reply-To: <1281682646-15990-1-git-send-email-amit.salecha@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
Display interface name for link status message.
With dev_info pci number get printed.
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 692641e..28985a9 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -1934,14 +1934,16 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
struct net_device *netdev = adapter->netdev;
if (adapter->ahw.linkup && !linkup) {
- dev_info(&netdev->dev, "NIC Link is down\n");
+ printk(KERN_INFO "%s: %s NIC Link is down\n",
+ qlcnic_driver_name, netdev->name);
adapter->ahw.linkup = 0;
if (netif_running(netdev)) {
netif_carrier_off(netdev);
netif_stop_queue(netdev);
}
} else if (!adapter->ahw.linkup && linkup) {
- dev_info(&netdev->dev, "NIC Link is up\n");
+ printk(KERN_INFO "%s: %s NIC Link is up\n",
+ qlcnic_driver_name, netdev->name);
adapter->ahw.linkup = 1;
if (netif_running(netdev)) {
netif_carrier_on(netdev);
--
1.6.0.2
^ permalink raw reply related
* [PATCHv2 NEXT 6/7] qlcnic: fix link diag test
From: Amit Kumar Salecha @ 2010-08-13 6:57 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Sony Chacko
In-Reply-To: <1281682646-15990-1-git-send-email-amit.salecha@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
o Give sufficient time for all makes of PHY modules
to establish the link after loopback test.
o Perform online test before offline test.
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_ethtool.c | 17 ++++++++---------
drivers/net/qlcnic/qlcnic_hw.c | 1 +
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 9328d59..3d4655d 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -747,6 +747,14 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
{
memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
+ data[0] = qlcnic_reg_test(dev);
+ if (data[0])
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+
+ data[1] = (u64) qlcnic_test_link(dev);
+ if (data[1])
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+
if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
data[2] = qlcnic_irq_test(dev);
if (data[2])
@@ -757,15 +765,6 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
eth_test->flags |= ETH_TEST_FL_FAILED;
}
-
- data[0] = qlcnic_reg_test(dev);
- if (data[0])
- eth_test->flags |= ETH_TEST_FL_FAILED;
-
- /* link test */
- data[1] = (u64) qlcnic_test_link(dev);
- if (data[1])
- eth_test->flags |= ETH_TEST_FL_FAILED;
}
static void
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index e08c8b0..9d40ce0 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -1245,4 +1245,5 @@ void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter)
mode = VPORT_MISS_MODE_ACCEPT_MULTI;
qlcnic_nic_set_promisc(adapter, mode);
+ msleep(1000);
}
--
1.6.0.2
^ permalink raw reply related
* Re: e1000e crashes with 2.6.34.x and ThinkPad T60
From: Marc Haber @ 2010-08-13 8:07 UTC (permalink / raw)
To: Allan, Bruce W, Tantilov, Emil S, Linux Kernel Developers,
Linux Kernel Network Developers <ne
In-Reply-To: <20100813012551.GA25398@torres.zugschlus.de>
On Fri, Aug 13, 2010 at 03:25:51AM +0200, Marc Haber wrote:
> On Tue, Aug 10, 2010 at 09:34:52AM -0700, Allan, Bruce W wrote:
> > We have had other recent reports of issues with this part that are due to
> > ASPM L1 being enabled. Would you please try disabling L1 after the driver
> > is loaded as follows (assuming your adapter is still PCI bus/device/number
> > 02:00.0 as indicated in the lspci output you provided earlier):
> > 1) First check the hexadecimal value of the LnkCtl register -
> > # setpci -s 2:0.0 0xf0
> > 2) Disable ASPM (both L0s and L1) by zeroing out bits 0 and 1 in the value
> > returned by the previous step. For example, if it returned 42 (hex 42,
> > that is) -
> > # setpci -s 2:0.0 0xf0=0x40
> > 3) Confirm ASPM is disabled by checking the output from lspci again.
>
> It returned 42, and after setting 0x40, LnkCtl now says "ASPM Disabled".
>
> I'll dock the system now and will report after the weekend or after
> the first crash.
Didn't work, freeze within the first 60 minutes after starting serious
work. The system did sit idle for the night though without freezing.
Greetings
Marc
--
-----------------------------------------------------------------------------
Marc Haber | "I don't trust Computers. They | Mailadresse im Header
Mannheim, Germany | lose things." Winona Ryder | Fon: *49 621 72739834
Nordisch by Nature | How to make an American Quilt | Fax: *49 3221 2323190
^ permalink raw reply
* tproxy related crash in inet_hashtables
From: Stephen Buck @ 2010-08-13 8:15 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 5089 bytes --]
Recently I encountered a number of crashes related to tproxy on the
2.6.34.1 (x86_64 SMP) kernel. These usually manifested as a bug like the
following (Although the bug was confirmed to be present on a vanilla
kernel, this particular trace is from a kernel with some customisations):
[ 1504.765077] BUG: unable to handle kernel NULL pointer dereference at
(null)
[ 1504.848183] IP: [<ffffffff8135a79b>] inet_bind_bucket_destroy+0x1b/0x30
[ 1504.927126] PGD 1a9933067 PUD 1ad909067 PMD 0
[ 1504.980125] Thread overran stack, or stack corrupted
[ 1505.039325] Oops: 0002 #1 SMP
[ 1505.077775] last sysfs file:
/sys/devices/system/cpu/cpu15/topology/thread_siblings
[ 1505.169166] CPU 0
[ 1505.193070] Modules linked in: sch_sfq cls_fw sch_htb xt_physdev
8021q bridge stp llc
[ 1505.923769] Pid: 0, comm: swapper Not tainted 2.6.31-12EXINDAsmp #0
PowerEdge R710
[ 1506.014118] RIP: 0010:[<ffffffff8135a79b>] [<ffffffff8135a79b>]
inet_bind_bucket_destroy+0x1b/0x30
[ 1506.122242] RSP: 0018:ffffc90000003e10 EFLAGS: 00010246
[ 1506.185655] RAX: 0000000000000000 RBX: ffffc900164a02a0 RCX:
ffffea00098e24b0
[ 1506.270863] RDX: 0000000000000000 RSI: ffff8802e1186280 RDI:
ffffffff815b4600
[ 1506.356077] RBP: ffffc90000003e10 R08: 0000000000000016 R09:
0000000000000001
[ 1506.441284] R10: 0000000000000000 R11: 0000000000000000 R12:
ffff88011b894fc0
[ 1506.526500] R13: ffffffff81744c80 R14: ffffffff815fe6c0 R15:
0000000000000003
[ 1506.611722] FS: 0000000000000000(0000) GS:ffffc90000000000(0000)
knlGS:0000000000000000
[ 1506.708410] CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b
[ 1506.777011] CR2: 0000000000000000 CR3: 00000001ae17a000 CR4:
00000000000006f0
[ 1506.862225] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
0000000000000000
[ 1506.947442] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7:
0000000000000400
[ 1507.032650] Process swapper (pid: 0, threadinfo ffffffff815b0000,
task ffffffff815b6bc0)
[ 1507.129345] Stack:
[ 1507.153299] ffffc90000003e40 ffffffff8135b834 0000000000000001
ffff88011b894fc0
[ 1507.239581] <0> ffffffff815fe560 0000000000000002 ffffc90000003e80
ffffffff8135bbf6
[ 1507.331133] <0> ffffffff815fe560 ffffffff815fe560 ffffffff815fe6c0
ffffc90000003eb0
[ 1507.424833] Call Trace:
[ 1507.453976] <IRQ>
[ 1507.478971] [<ffffffff8135b834>] __inet_twsk_kill+0xb4/0xf0
[ 1507.546538] [<ffffffff8135bbf6>] inet_twdr_do_twkill_work+0x66/0xd0
[ 1507.622408] [<ffffffff8135bd40>] ? inet_twdr_hangman+0x0/0xd0
[ 1507.692041] [<ffffffff8135bd95>] inet_twdr_hangman+0x55/0xd0
[ 1507.760650] [<ffffffff810515ec>] run_timer_softirq+0x18c/0x220
[ 1507.831330] [<ffffffff8104c3b8>] __do_softirq+0xc8/0x1f0
[ 1507.895799] [<ffffffff8100cf5c>] call_softirq+0x1c/0x30
[ 1507.959209] [<ffffffff8100e5f5>] do_softirq+0x45/0x80
[ 1508.020538] [<ffffffff8104c2e7>] irq_exit+0x87/0x90
[ 1508.079797] [<ffffffff813bd0c1>] smp_apic_timer_interrupt+0x71/0x9d
[ 1508.155667] [<ffffffff8100c933>] apic_timer_interrupt+0x13/0x20
[ 1508.227385] <EOI>
[ 1508.252383] [<ffffffff8101317e>] ? mwait_idle+0x7e/0x110
[ 1508.316836] [<ffffffff813bb0bd>] ? __atomic_notifier_call_chain+0xd/0x10
[ 1508.397903] [<ffffffff813bb0d1>] ? atomic_notifier_call_chain+0x11/0x20
[ 1508.477928] [<ffffffff8100ac31>] ? cpu_idle+0x51/0x90
[ 1508.539265] [<ffffffff813aa92b>] ? rest_init+0x6b/0x80
[ 1508.601639] [<ffffffff816230f5>] ? start_kernel+0x2c5/0x370
[ 1508.669200] [<ffffffff81622611>] ? x86_64_start_reservations+0x81/0xc0
[ 1508.748192] [<ffffffff81622726>] ? x86_64_start_kernel+0xd6/0x100
[ 1508.821979] Code: 64 10 40 eb 94 0f 1f 44 00 00 66 0f 1f 44 00 00 55
48 89 e5 0f 1f 44 00 00 48 83 7e 18 00 75 19 48 8b 46 08 48 8b 56 10
[ 1509.048123] RIP [<ffffffff8135a79b>] inet_bind_bucket_destroy+0x1b/0x30
[ 1509.128157] RSP <ffffc90000003e10>
[ 1509.169759] CR2: 0000000000000000
After spending a while tracking it down, I discovered that the wrong
locks get held when operating on the bind hash table's chains.
This is due to the listen socket and the child socket having different
local ports when __inet_inherit_port() is called. The lock is held based
on the child socket's port, but the list operated on is the one the
listen socket belongs to.
e.g.
There is a transparent proxy listening on port 9999.
A new http connection (with port 80) is redirected to the proxy.
The inet_bind_hashbucket locked in this case is table->bhash[80].lock,
but the inet_bind_bucket the child socket is added to is in the chain of
the table->bhash[9999] inet_bind_hashbucket. This means that if another
connection with a different local port arrived and was redirected to the
proxy, they could both be operating on the list at the same time.
Attached is a patch that should fix this by looking up the correct
inet_bind_bucket based on the child's local port when the
inet_bind_bucket from the listen socket has a different port to the
child's inet_num. It was built against 2.6.34.1, but should apply to any
mainline kernel.
It is also possible the same bug exists in the IPv6 code as well. As I
have not had to deal with IPv6 yet, I have not had a look.
[-- Attachment #2: tproxy-bind-fix.patch --]
[-- Type: text/x-patch, Size: 1443 bytes --]
commit f517f61e37907ea66e48f224c135a9e1c257bb04
Author: Stephen Buck <stephen.buck@exinda.com>
Date: Thu Aug 12 16:19:19 2010 +1000
Fix locking issue in inet_hashtables when using tproxy
When __inet_inherit_port() is called on a tproxy connection the wrong locks
are held for the inet_bind_bucket it is added to.
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 2b79377..1ba982f 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -105,13 +105,24 @@ EXPORT_SYMBOL(inet_put_port);
void __inet_inherit_port(struct sock *sk, struct sock *child)
{
struct inet_hashinfo *table = sk->sk_prot->h.hashinfo;
- const int bhash = inet_bhashfn(sock_net(sk), inet_sk(child)->inet_num,
+ unsigned short port = inet_sk(child)->inet_num;
+ const int bhash = inet_bhashfn(sock_net(sk), port,
table->bhash_size);
struct inet_bind_hashbucket *head = &table->bhash[bhash];
struct inet_bind_bucket *tb;
spin_lock(&head->lock);
tb = inet_csk(sk)->icsk_bind_hash;
+ if (tb->port != port) {
+ struct hlist_node *node;
+ inet_bind_bucket_for_each(tb, node, &head->chain) {
+ if (net_eq(ib_net(tb), sock_net(sk)) && tb->port == port)
+ break;
+ }
+ if (!node)
+ tb = inet_bind_bucket_create(table->bind_bucket_cachep,
+ sock_net(sk), head, port);
+ }
sk_add_bind_node(child, &tb->owners);
inet_csk(child)->icsk_bind_hash = tb;
spin_unlock(&head->lock);
^ permalink raw reply related
* Re: [PATCH 08/12] ptp: Added a brand new class driver for ptp clocks.
From: Richard Cochran @ 2010-08-13 9:34 UTC (permalink / raw)
To: Grant Likely
Cc: netdev, devicetree-discuss, linuxppc-dev, linux-arm-kernel,
Krzysztof Halasa, Thomas Gleixner
In-Reply-To: <AANLkTinYjzfChsN0AB5W6kOh6xJYPJtoEq941pG8WbmS@mail.gmail.com>
On Tue, Jun 15, 2010 at 01:11:30PM -0600, Grant Likely wrote:
> On Tue, Jun 15, 2010 at 10:09 AM, Richard Cochran
> > +static DEFINE_SPINLOCK(clocks_lock); /* protects 'clocks' */
>
> Doesn't appear that clocks is manipulated at atomic context. Mutex instead?
...
> If the spinlock is changed to a mutex that is held for the entire
> function call, then the logic here can be simpler.
Grant,
I am working on another go at this patch series. Stupid question:
The caller of ptp_clock_register(), which takes the clocks_lock, is
always a module_init() function. Is this always a safe context in
which to call mutex_lock?
Thanks,
Richard
^ permalink raw reply
* [PATCH] iputils: arping fails to set correct broadcast address
From: Jesper Dangaard Brouer @ 2010-08-13 9:44 UTC (permalink / raw)
To: YOSHIFUJI Hideaki; +Cc: netdev, 585591, Noah Meyerhans, Paul Martin, hawk
From: Paul Martin <pm@debian.org>
There seems to have been introduced a bug in iputils release s20100418.
This patch is based upon git://www.linux-ipv6.org/gitroot/iputils.git
(git commit fe342ca3148)
The regression is caused by commit 56018bf1b3
arping: Support link-layer type with larger link-layer address.
As reported by: Paul Martin <pm@debian.org> in Debian bugreport #585591.
There's a logic error in the function that parses the interface's
broadcast address, causing it not to fill the broadcast address array
correctly.
Please apply.
Reported-by: Paul Martin <pm@debian.org>
Tested-by: Jesper Dangaard Brouer <hawk@comx.dk>
Signed-off-by: Jesper Dangaard Brouer <hawk@comx.dk>
---
arping.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arping.c b/arping.c
index 9bd6927..2613a12 100644
--- a/arping.c
+++ b/arping.c
@@ -336,7 +336,7 @@ void set_device_broadcast(char *device, unsigned char *ba, size_t balen)
}
for (p = ba, ch = 0; p < ba + balen; p++, ch += 3)
- *p++ = strtoul(brdcast->value + ch * 3, NULL, 16);
+ *p = strtoul(brdcast->value + ch, NULL, 16);
return;
}
^ permalink raw reply related
* Re: Problem with non aligned DMA in usbnet on ARM
From: Martin Fuzzey @ 2010-08-13 10:06 UTC (permalink / raw)
To: Matthieu CASTET
Cc: Russell King - ARM Linux, Gary King,
linux-arm-kernel@lists.infradead.org, linux-usb,
netdev@vger.kernel.org, Greg KH
In-Reply-To: <4C642AA9.1060404@parrot.com>
Matthieu CASTET wrote:
> memmove is our friend :
> the buffer allocated in usbnet got an offset.
> All you have to do it remove this offset and memmove the data. That
> what I did [1], and why it is better to do it in usb driver.
>
>
> [1] http://article.gmane.org/gmane.linux.usb.general/28700
The problem I see with this approach is that it requires the usb driver
to be aware of the device controller's quirks (hence the
gadget_dma32()) your patch adds. That appears to be the norm (and maybe
unavoidable) on the gadget side but on the host side things aren't
supposed to work like that.
The expectation for USB hosts is that any properly written usb driver
will work with any properly written host controller driver. I don't
think it's reasonable to expect driver developers to test their code
with all the HCDs, nor expect HCD developers to test their code with all
the drivers.
So I think a policy needs to be defined to ensure this and enforced in
the code. I can see two possible methods:
1) Require that usb drivers submit buffers obtained from kmalloc() and
friends with no extra offsets. If they want some other alignment later
they can use memmove in the completion handler. Enforce this in the core
by checking the buffer pointers are aligned to ARCH_KMALLOC_MINALIGN
or
2) Require that usb_submit_urb() accept byte aligned buffers. Enforce
this by a new test in usbtest (which all HCDs are expected to pass).
Implement it either in individual HCDs that require it or by letting
HCDs inform the core of their requirements and have the core do the
alignment (as it already does the dma mapping). Of course HCDs that can
implement byte aligned transfers (either natively or using tricks such
as the one Russell suggested) should do so.
I think 2) is the better solution because:
a) Solution 1 will impose a runtime overhead even on platforms / HCDs
that don't need it (including the most common cases)
b) There are more drivers than HCDs
Martin
^ permalink raw reply
* 2.6.35, netfilter/iptables not working with 32bit userspace + 64bit kernel?
From: Jussi Kivilinna @ 2010-08-13 10:47 UTC (permalink / raw)
To: netdev
Hello!
I have server/firewall running Debian lenny with 32bit userspace and
64bit kernel. After upgrading from 2.6.34 to 2.6.35, I couldn't get
any new chains work. Simply doing (with 32bit iptables)
iptables -N new_chain
iptables -A OUTPUT -j new_chain
iptables -A OUTPUT -j ACCEPT
cause output to freeze. "iptables -L -vn" shows:
Chain OUTPUT (policy ACCEPT 3397 packets, 637K bytes)
pkts bytes target prot opt in out source destination
3 252 new_chain all -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0
Ping shows "ping: sendmsg: Operation not permitted".
With recompiled 64bit iptables, example above works fine.
-Jussi
^ permalink raw reply
* Re: tproxy related crash in inet_hashtables
From: Eric Dumazet @ 2010-08-13 10:54 UTC (permalink / raw)
To: Stephen Buck
Cc: netdev, Netfilter Development Mailinglist, Patrick McHardy,
KOVACS Krisztian
In-Reply-To: <4C64FF2E.6060509@exinda.com>
Le vendredi 13 août 2010 à 18:15 +1000, Stephen Buck a écrit :
> Recently I encountered a number of crashes related to tproxy on the
> 2.6.34.1 (x86_64 SMP) kernel. These usually manifested as a bug like the
> following (Although the bug was confirmed to be present on a vanilla
> kernel, this particular trace is from a kernel with some customisations):
>
> [ 1504.765077] BUG: unable to handle kernel NULL pointer dereference at
> (null)
> [ 1504.848183] IP: [<ffffffff8135a79b>] inet_bind_bucket_destroy+0x1b/0x30
> [ 1504.927126] PGD 1a9933067 PUD 1ad909067 PMD 0
> [ 1504.980125] Thread overran stack, or stack corrupted
> [ 1505.039325] Oops: 0002 #1 SMP
> [ 1505.077775] last sysfs file:
> /sys/devices/system/cpu/cpu15/topology/thread_siblings
> [ 1505.169166] CPU 0
> [ 1505.193070] Modules linked in: sch_sfq cls_fw sch_htb xt_physdev
> 8021q bridge stp llc
> [ 1505.923769] Pid: 0, comm: swapper Not tainted 2.6.31-12EXINDAsmp #0
> PowerEdge R710
> [ 1506.014118] RIP: 0010:[<ffffffff8135a79b>] [<ffffffff8135a79b>]
> inet_bind_bucket_destroy+0x1b/0x30
> [ 1506.122242] RSP: 0018:ffffc90000003e10 EFLAGS: 00010246
> [ 1506.185655] RAX: 0000000000000000 RBX: ffffc900164a02a0 RCX:
> ffffea00098e24b0
> [ 1506.270863] RDX: 0000000000000000 RSI: ffff8802e1186280 RDI:
> ffffffff815b4600
> [ 1506.356077] RBP: ffffc90000003e10 R08: 0000000000000016 R09:
> 0000000000000001
> [ 1506.441284] R10: 0000000000000000 R11: 0000000000000000 R12:
> ffff88011b894fc0
> [ 1506.526500] R13: ffffffff81744c80 R14: ffffffff815fe6c0 R15:
> 0000000000000003
> [ 1506.611722] FS: 0000000000000000(0000) GS:ffffc90000000000(0000)
> knlGS:0000000000000000
> [ 1506.708410] CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b
> [ 1506.777011] CR2: 0000000000000000 CR3: 00000001ae17a000 CR4:
> 00000000000006f0
> [ 1506.862225] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
> 0000000000000000
> [ 1506.947442] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7:
> 0000000000000400
> [ 1507.032650] Process swapper (pid: 0, threadinfo ffffffff815b0000,
> task ffffffff815b6bc0)
> [ 1507.129345] Stack:
> [ 1507.153299] ffffc90000003e40 ffffffff8135b834 0000000000000001
> ffff88011b894fc0
> [ 1507.239581] <0> ffffffff815fe560 0000000000000002 ffffc90000003e80
> ffffffff8135bbf6
> [ 1507.331133] <0> ffffffff815fe560 ffffffff815fe560 ffffffff815fe6c0
> ffffc90000003eb0
> [ 1507.424833] Call Trace:
> [ 1507.453976] <IRQ>
> [ 1507.478971] [<ffffffff8135b834>] __inet_twsk_kill+0xb4/0xf0
> [ 1507.546538] [<ffffffff8135bbf6>] inet_twdr_do_twkill_work+0x66/0xd0
> [ 1507.622408] [<ffffffff8135bd40>] ? inet_twdr_hangman+0x0/0xd0
> [ 1507.692041] [<ffffffff8135bd95>] inet_twdr_hangman+0x55/0xd0
> [ 1507.760650] [<ffffffff810515ec>] run_timer_softirq+0x18c/0x220
> [ 1507.831330] [<ffffffff8104c3b8>] __do_softirq+0xc8/0x1f0
> [ 1507.895799] [<ffffffff8100cf5c>] call_softirq+0x1c/0x30
> [ 1507.959209] [<ffffffff8100e5f5>] do_softirq+0x45/0x80
> [ 1508.020538] [<ffffffff8104c2e7>] irq_exit+0x87/0x90
> [ 1508.079797] [<ffffffff813bd0c1>] smp_apic_timer_interrupt+0x71/0x9d
> [ 1508.155667] [<ffffffff8100c933>] apic_timer_interrupt+0x13/0x20
> [ 1508.227385] <EOI>
> [ 1508.252383] [<ffffffff8101317e>] ? mwait_idle+0x7e/0x110
> [ 1508.316836] [<ffffffff813bb0bd>] ? __atomic_notifier_call_chain+0xd/0x10
> [ 1508.397903] [<ffffffff813bb0d1>] ? atomic_notifier_call_chain+0x11/0x20
> [ 1508.477928] [<ffffffff8100ac31>] ? cpu_idle+0x51/0x90
> [ 1508.539265] [<ffffffff813aa92b>] ? rest_init+0x6b/0x80
> [ 1508.601639] [<ffffffff816230f5>] ? start_kernel+0x2c5/0x370
> [ 1508.669200] [<ffffffff81622611>] ? x86_64_start_reservations+0x81/0xc0
> [ 1508.748192] [<ffffffff81622726>] ? x86_64_start_kernel+0xd6/0x100
> [ 1508.821979] Code: 64 10 40 eb 94 0f 1f 44 00 00 66 0f 1f 44 00 00 55
> 48 89 e5 0f 1f 44 00 00 48 83 7e 18 00 75 19 48 8b 46 08 48 8b 56 10
> [ 1509.048123] RIP [<ffffffff8135a79b>] inet_bind_bucket_destroy+0x1b/0x30
> [ 1509.128157] RSP <ffffc90000003e10>
> [ 1509.169759] CR2: 0000000000000000
>
>
> After spending a while tracking it down, I discovered that the wrong
> locks get held when operating on the bind hash table's chains.
>
> This is due to the listen socket and the child socket having different
> local ports when __inet_inherit_port() is called. The lock is held based
> on the child socket's port, but the list operated on is the one the
> listen socket belongs to.
>
> e.g.
> There is a transparent proxy listening on port 9999.
> A new http connection (with port 80) is redirected to the proxy.
>
> The inet_bind_hashbucket locked in this case is table->bhash[80].lock,
> but the inet_bind_bucket the child socket is added to is in the chain of
> the table->bhash[9999] inet_bind_hashbucket. This means that if another
> connection with a different local port arrived and was redirected to the
> proxy, they could both be operating on the list at the same time.
>
>
> Attached is a patch that should fix this by looking up the correct
> inet_bind_bucket based on the child's local port when the
> inet_bind_bucket from the listen socket has a different port to the
> child's inet_num. It was built against 2.6.34.1, but should apply to any
> mainline kernel.
>
> It is also possible the same bug exists in the IPv6 code as well. As I
> have not had to deal with IPv6 yet, I have not had a look.
Hi Stephen
CC netfilter-devel & Patrick & Krisztian
I cannot convince myself this patch is a right fix.
This probably should be fixed in netfilter tree, not in
net/ipv4/inet_hashtables.c ?
Once tproxy is involved, the original port (80) should be changed to
9999 by tproxy (for SYN packet) and conntrack for following ones.
So listening socket and its children all use source port 9999 ?
(inet_sk(child)->inet_num == inet_sk(parent)->inet_num)
You claim wrong lock is taken at insert time, but are you sure the right
lock is taken at deletion time ?
Hmm...
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
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