Netdev List
 help / color / mirror / Atom feed
* Re: net-next: 2.6.34-rc1 regression: panic when running diagnostic on interface with IPv6
From: David Miller @ 2010-04-05 23:53 UTC (permalink / raw)
  To: emil.s.tantilov; +Cc: shemminger, netdev
In-Reply-To: <EA929A9653AAE14F841771FB1DE5A1365FE4E2E334@rrsmsx501.amr.corp.intel.com>

From: "Tantilov, Emil S" <emil.s.tantilov@intel.com>
Date: Mon, 5 Apr 2010 17:50:38 -0600

> David Miller wrote:
>> From: "Tantilov, Emil S" <emil.s.tantilov@intel.com>
>> Date: Mon, 5 Apr 2010 17:03:56 -0600
>> 
>>> David Miller wrote:
>>>> From: "Tantilov, Emil S" <emil.s.tantilov@intel.com>
>>>> Date: Tue, 23 Mar 2010 12:28:08 -0600
>>>> 
>>>>> Bisecting points to this patch:
>>>>> http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=commitdiff;h=84e8b803f1e16f3a2b8b80f80a63fa2f2f8a9be6
>>>>> 
>>>>> And I confirmed that the issue goes away after reverting it.
>>>>> 
>>>>> Steps to reproduce:
>>>>> 1. Load the driver and configure IPv6 address.
>>>>> 2. Run ethtool diag:
>>>>> ethtool -t eth0
>>>>> 
>>>>> 3. If this doesn't brake it try again, or just do ifdown/up. Other
>>>>> operations on the interface will eventually panic the system:
>>>> 
>>>> Stephen please fix this, thanks.
>>> 
>>> Just FYI - I still see this issue with latest pull from net-2.6.
>> 
>> It's net-next-2.6 that introduced the problem and has the follow-on
>> fixes, not net-2.6
> 
> Same in net-next:

Ok, Stephen please look into this, we've had this regression
for almost two weeks now.

^ permalink raw reply

* RE: net-next: 2.6.34-rc1 regression: panic when running diagnostic on interface with IPv6
From: Tantilov, Emil S @ 2010-04-05 23:50 UTC (permalink / raw)
  To: David Miller; +Cc: shemminger@vyatta.com, netdev@vger.kernel.org
In-Reply-To: <20100405.161221.159637463.davem@davemloft.net>

David Miller wrote:
> From: "Tantilov, Emil S" <emil.s.tantilov@intel.com>
> Date: Mon, 5 Apr 2010 17:03:56 -0600
> 
>> David Miller wrote:
>>> From: "Tantilov, Emil S" <emil.s.tantilov@intel.com>
>>> Date: Tue, 23 Mar 2010 12:28:08 -0600
>>> 
>>>> Bisecting points to this patch:
>>>> http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=commitdiff;h=84e8b803f1e16f3a2b8b80f80a63fa2f2f8a9be6
>>>> 
>>>> And I confirmed that the issue goes away after reverting it.
>>>> 
>>>> Steps to reproduce:
>>>> 1. Load the driver and configure IPv6 address.
>>>> 2. Run ethtool diag:
>>>> ethtool -t eth0
>>>> 
>>>> 3. If this doesn't brake it try again, or just do ifdown/up. Other
>>>> operations on the interface will eventually panic the system:
>>> 
>>> Stephen please fix this, thanks.
>> 
>> Just FYI - I still see this issue with latest pull from net-2.6.
> 
> It's net-next-2.6 that introduced the problem and has the follow-on
> fixes, not net-2.6

Same in net-next:

[   55.706583] WARNING: at net/ipv6/ip6_fib.c:1170 fib6_del+0x44/0x39f [ipv6]()
[   55.714851] Hardware name: S5520HC
[   55.719037] Modules linked in: ipv6 e1000e e1000
[   55.724866] Pid: 5599, comm: ifconfig Not tainted 2.6.34-rc1-net-next-e1000e-040510 #9
[   55.734418] Call Trace:
[   55.737540]  [<ffffffff81033a3e>] ? __wake_up+0x43/0x50
[   55.743773]  [<ffffffffa006cb4e>] ? fib6_del+0x44/0x39f [ipv6]
[   55.750687]  [<ffffffff81038b1e>] warn_slowpath_common+0x77/0x8f
[   55.757793]  [<ffffffff81038b45>] warn_slowpath_null+0xf/0x11
[   55.764608]  [<ffffffffa006cb4e>] fib6_del+0x44/0x39f [ipv6]
[   55.771314]  [<ffffffffa006a13b>] __ip6_del_rt+0x49/0x68 [ipv6]
[   55.778319]  [<ffffffffa006a2aa>] ip6_del_rt+0x38/0x3a [ipv6]
[   55.785136]  [<ffffffffa0065573>] __ipv6_ifa_notify+0x141/0x17d [ipv6]
[   55.792816]  [<ffffffffa00660a4>] addrconf_ifdown+0x1ed/0x2cb [ipv6]
[   55.800300]  [<ffffffffa0067126>] addrconf_notify+0x705/0x7b6 [ipv6]
[   55.807788]  [<ffffffff810456ce>] ? spin_unlock_irqrestore+0x9/0xb
[   55.815088]  [<ffffffff81045b80>] ? __mod_timer+0x125/0x137
[   55.821703]  [<ffffffff8144eb60>] ? _raw_write_unlock_bh+0x12/0x14
[   55.828995]  [<ffffffff8103e37d>] ? local_bh_enable_ip+0x9/0xb
[   55.835906]  [<ffffffff8144ec75>] ? _raw_spin_unlock_bh+0x12/0x14
[   55.843109]  [<ffffffffa006ca9b>] ? fib6_run_gc+0xca/0xcf [ipv6]
[   55.850213]  [<ffffffff81451b29>] notifier_call_chain+0x33/0x5b
[   55.857216]  [<ffffffff81055575>] __raw_notifier_call_chain+0x9/0xb
[   55.864604]  [<ffffffff81055586>] raw_notifier_call_chain+0xf/0x11
[   55.871901]  [<ffffffff81397d8f>] call_netdevice_notifiers+0x16/0x18
[   55.879390]  [<ffffffff81397eb2>] __dev_notify_flags+0x35/0x59
[   55.886293]  [<ffffffff81397f1c>] dev_change_flags+0x46/0x52
[   55.893007]  [<ffffffff813f0844>] devinet_ioctl+0x27f/0x54b
[   55.899614]  [<ffffffff813f2c18>] inet_ioctl+0x8a/0xa2
[   55.905733]  [<ffffffff81387275>] sock_do_ioctl+0x26/0x46
[   55.912149]  [<ffffffff81387490>] sock_ioctl+0x1fb/0x20e
[   55.918461]  [<ffffffff810e7b4b>] vfs_ioctl+0x2a/0x9d
[   55.924495]  [<ffffffff810e80c2>] do_vfs_ioctl+0x48c/0x4dd
[   55.930999]  [<ffffffff810e816a>] sys_ioctl+0x57/0x7a
[   55.937033]  [<ffffffff81002a2b>] system_call_fastpath+0x16/0x1b
[   55.944123] ---[ end trace c1c390412f982fb6 ]---
[   55.949677] Freeing alive inet6 address ffff8801eee32000
[   56.034060] fib6_clean_node: del failed: rt=ffff8801ec984e00@(null) err=-2

Emil

^ permalink raw reply

* Re: [PATCH 33/37] sound/soc: use .dev.of_node instead of .node in struct of_device
From: Grant Likely @ 2010-04-05 23:47 UTC (permalink / raw)
  To: Ben Dooks
  Cc: monstr-pSz03upnqPeHXe+LvDLADg, gregkh-l3A5Bk7waGM,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q, sfr-3FnU+UHB4dNDw9hX6IcOSA,
	jgarzik-e+AXbWqSrlAAvxtiuMwx3w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	jeremy.kerr-Z7WLFzj8eWMS+FvcfC7Uqw, James.Bottomley-l3A5Bk7waGM,
	broonie-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
	microblaze-uclinux-rVRm/Wmeqae7NGdpmJTKYQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	sparclinux-u79uwXL29TY76Z2rM5mHXA,
	linux-ide-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-scsi-u79uwXL29TY76Z2rM5mHXA,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
In-Reply-To: <20100405230301.GF32401-elnMNo+KYs3pIgCt6eIbzw@public.gmane.org>

Hi Ben, thanks for the comment.  Reply below...

On Mon, Apr 5, 2010 at 5:03 PM, Ben Dooks <ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org> wrote:
> On Thu, Mar 11, 2010 at 11:06:50AM -0700, Grant Likely wrote:
>> .node is being removed
[...]
>> --- a/sound/soc/fsl/mpc8610_hpcd.c
>> +++ b/sound/soc/fsl/mpc8610_hpcd.c
>> @@ -202,7 +202,7 @@ static struct snd_soc_ops mpc8610_hpcd_ops = {
>>  static int mpc8610_hpcd_probe(struct of_device *ofdev,
>>       const struct of_device_id *match)
>>  {
>> -     struct device_node *np = ofdev->node;
>> +     struct device_node *np = ofdev->dev.of_node;
>>       struct device_node *codec_np = NULL;
>>       struct device_node *guts_np = NULL;
>>       struct device_node *dma_np = NULL;
>
> This looks like one case where an inline function would have been a
> help.

In what regard (how would you like it to look)?  The node pointer
location is very unlikely to move again, and I prefer the clarity of
direct dereferencing.

g.

^ permalink raw reply

* Re: net-next: 2.6.34-rc1 regression: panic when running diagnostic on interface with IPv6
From: David Miller @ 2010-04-05 23:12 UTC (permalink / raw)
  To: emil.s.tantilov; +Cc: shemminger, netdev
In-Reply-To: <EA929A9653AAE14F841771FB1DE5A1365FE4E2E26C@rrsmsx501.amr.corp.intel.com>

From: "Tantilov, Emil S" <emil.s.tantilov@intel.com>
Date: Mon, 5 Apr 2010 17:03:56 -0600

> David Miller wrote:
>> From: "Tantilov, Emil S" <emil.s.tantilov@intel.com>
>> Date: Tue, 23 Mar 2010 12:28:08 -0600
>> 
>>> Bisecting points to this patch:
>>> http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=commitdiff;h=84e8b803f1e16f3a2b8b80f80a63fa2f2f8a9be6
>>> 
>>> And I confirmed that the issue goes away after reverting it.
>>> 
>>> Steps to reproduce:
>>> 1. Load the driver and configure IPv6 address.
>>> 2. Run ethtool diag:
>>> ethtool -t eth0
>>> 
>>> 3. If this doesn't brake it try again, or just do ifdown/up. Other
>>> operations on the interface will eventually panic the system: 
>> 
>> Stephen please fix this, thanks.
> 
> Just FYI - I still see this issue with latest pull from net-2.6.

It's net-next-2.6 that introduced the problem and has the follow-on
fixes, not net-2.6

^ permalink raw reply

* RE: net-next: 2.6.34-rc1 regression: panic when running diagnostic on interface with IPv6
From: Tantilov, Emil S @ 2010-04-05 23:03 UTC (permalink / raw)
  To: shemminger@vyatta.com; +Cc: netdev@vger.kernel.org, David Miller
In-Reply-To: <20100323.233323.93371615.davem@davemloft.net>

David Miller wrote:
> From: "Tantilov, Emil S" <emil.s.tantilov@intel.com>
> Date: Tue, 23 Mar 2010 12:28:08 -0600
> 
>> Bisecting points to this patch:
>> http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=commitdiff;h=84e8b803f1e16f3a2b8b80f80a63fa2f2f8a9be6
>> 
>> And I confirmed that the issue goes away after reverting it.
>> 
>> Steps to reproduce:
>> 1. Load the driver and configure IPv6 address.
>> 2. Run ethtool diag:
>> ethtool -t eth0
>> 
>> 3. If this doesn't brake it try again, or just do ifdown/up. Other
>> operations on the interface will eventually panic the system: 
> 
> Stephen please fix this, thanks.

Just FYI - I still see this issue with latest pull from net-2.6.

Thanks,
Emil

^ permalink raw reply

* Re: [PATCH 33/37] sound/soc: use .dev.of_node instead of .node in struct of_device
From: Ben Dooks @ 2010-04-05 23:03 UTC (permalink / raw)
  To: Grant Likely
  Cc: monstr-pSz03upnqPeHXe+LvDLADg, gregkh-l3A5Bk7waGM,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q, sfr-3FnU+UHB4dNDw9hX6IcOSA,
	jgarzik-e+AXbWqSrlAAvxtiuMwx3w, ben-linux-elnMNo+KYs3YtjvyW6yDsg,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, jeremy.kerr-Z7WLFzj8eWMS+FvcfC7Uqw,
	James.Bottomley-l3A5Bk7waGM,
	broonie-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
	microblaze-uclinux-rVRm/Wmeqae7NGdpmJTKYQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	sparclinux-u79uwXL29TY76Z2rM5mHXA,
	linux-ide-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-scsi-u79uwXL29TY76Z2rM5mHXA,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
In-Reply-To: <20100311180649.4824.10368.stgit@angua>

On Thu, Mar 11, 2010 at 11:06:50AM -0700, Grant Likely wrote:
> .node is being removed
> 
> Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> ---
> 
>  sound/soc/fsl/mpc8610_hpcd.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
> index ef67d1c..d7e1b9a 100644
> --- a/sound/soc/fsl/mpc8610_hpcd.c
> +++ b/sound/soc/fsl/mpc8610_hpcd.c
> @@ -202,7 +202,7 @@ static struct snd_soc_ops mpc8610_hpcd_ops = {
>  static int mpc8610_hpcd_probe(struct of_device *ofdev,
>  	const struct of_device_id *match)
>  {
> -	struct device_node *np = ofdev->node;
> +	struct device_node *np = ofdev->dev.of_node;
>  	struct device_node *codec_np = NULL;
>  	struct device_node *guts_np = NULL;
>  	struct device_node *dma_np = NULL;

This looks like one case where an inline function would have been a
help.


-- 
Ben (ben-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

^ permalink raw reply

* Re: [PATCH net-next-2.6] net: Add a missing local_irq_enable()
From: David Miller @ 2010-04-05 22:42 UTC (permalink / raw)
  To: eric.dumazet; +Cc: xiaosuo, therbert, netdev
In-Reply-To: <1270507307.9013.43.camel@edumazet-laptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 06 Apr 2010 00:41:47 +0200

> Le mardi 06 avril 2010 à 06:23 +0800, Changli Gao a écrit :
> 
>> It seems that irq isn't enabled when breaking the loop. Please add
>>    local_irq_enable();
>> after rps_unlock(queue);
> 
> Gah.. you are right, following patch needed, since David already applied
> Tom's patch.
> 
> [PATCH net-next-2.6] net: Add a missing local_irq_enable()
> 
> As noticed by Changli Gao, we must call local_irq_enable() after
> rps_unlock()
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied, hope it's fully resolved now :-)

^ permalink raw reply

* [PATCH net-next-2.6] net: Add a missing local_irq_enable()
From: Eric Dumazet @ 2010-04-05 22:41 UTC (permalink / raw)
  To: Changli Gao; +Cc: Tom Herbert, davem, netdev
In-Reply-To: <z2m412e6f7f1004051523p6198556ak3e2ab9a52a3167d4@mail.gmail.com>

Le mardi 06 avril 2010 à 06:23 +0800, Changli Gao a écrit :

> It seems that irq isn't enabled when breaking the loop. Please add
>    local_irq_enable();
> after rps_unlock(queue);

Gah.. you are right, following patch needed, since David already applied
Tom's patch.

[PATCH net-next-2.6] net: Add a missing local_irq_enable()

As noticed by Changli Gao, we must call local_irq_enable() after
rps_unlock()

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
diff --git a/net/core/dev.c b/net/core/dev.c
index 74f77ca..b98ddc6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3121,6 +3121,7 @@ static int process_backlog(struct napi_struct *napi, int quota)
 		if (!skb) {
 			__napi_complete(napi);
 			rps_unlock(queue);
+			local_irq_enable();
 			break;
 		}
 		rps_unlock(queue);



^ permalink raw reply related

* [PATCH 4/4] xfrm: CONFIG_COMPAT support for x86 architecture
From: Florian Westphal @ 2010-04-05 22:27 UTC (permalink / raw)
  To: netdev; +Cc: johannes, Florian Westphal
In-Reply-To: <1270506431-25578-1-git-send-email-fw@strlen.de>

on x86_64, struct xfrm_userpolicy_info/usersa_info have four
additional bytes of padding at the end compared to x86.

Thus, when calling nlmsg_parse(.., sizeof(struct xfrm_userpolicy_info),
trailing attributes are not parsed correctly by the kernel when
the message was sent from an x86 32bit task.

Furthermore, those structures are contained inside
a few other structures, e.g. struct xfrm_user_acquire.

When dealing with incoming data from userland,
those structures need special treatment in the "userland is 32bit"
case.

When sending data to userland, it is sent in both 32bit and native
format.

Errors when building the compat message are not visisble to user
space; data will then be sent without the compat payload.

refer to 1dacc76d0014a034b8aca14237c127d7c19d7726
(net/compat/wext: send different messages to compat tasks) for
more information on netlink compat handling.

With suggestions from Johannes Berg.

Cc: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Florian Westphal <fwestphal@astaro.com>
---
 net/xfrm/Kconfig     |    1 +
 net/xfrm/xfrm_user.c |  369 ++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 340 insertions(+), 30 deletions(-)

diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig
index 6d08167..0b30357 100644
--- a/net/xfrm/Kconfig
+++ b/net/xfrm/Kconfig
@@ -9,6 +9,7 @@ config XFRM
 config XFRM_USER
 	tristate "Transformation user configuration interface"
 	depends on INET && XFRM
+	select WANT_COMPAT_NETLINK_MESSAGES if COMPAT_FOR_U64_ALIGNMENT
 	---help---
 	  Support for Transformation(XFRM) user configuration interface
 	  like IPsec used by native Linux tools.
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 3aba167..6fa9930 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -10,6 +10,7 @@
  *
  */
 
+#include <linux/compat.h>
 #include <linux/crypto.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -31,6 +32,149 @@
 #include <linux/in6.h>
 #endif
 
+#ifdef CONFIG_COMPAT_FOR_U64_ALIGNMENT
+struct compat_xfrm_lifetime_cfg {
+	compat_u64 soft_byte_limit, hard_byte_limit;
+	compat_u64 soft_packet_limit, hard_packet_limit;
+	compat_u64 soft_add_expires_seconds, hard_add_expires_seconds;
+	compat_u64 soft_use_expires_seconds, hard_use_expires_seconds;
+};
+
+struct compat_xfrm_lifetime_cur {
+	compat_u64 bytes, packets, add_time, use_time;
+};
+
+struct compat_xfrm_userpolicy_info {
+	struct xfrm_selector sel;
+	struct compat_xfrm_lifetime_cfg lft;
+	struct compat_xfrm_lifetime_cur curlft;
+	u32 priority, index;
+	u8 dir, action, flags, share;
+	/* 4 bytes additional padding on 64bit */
+};
+
+struct compat_xfrm_usersa_info {
+	struct xfrm_selector sel;
+	struct xfrm_id id;
+	xfrm_address_t saddr;
+	struct compat_xfrm_lifetime_cfg lft;
+	struct compat_xfrm_lifetime_cur curlft;
+	struct xfrm_stats stats;
+	u32 seq, reqid;
+	u16 family;
+	u8 mode, replay_window, flags;
+	/* 4 bytes additional padding on 64bit */
+};
+
+struct compat_xfrm_user_acquire {
+	struct xfrm_id id;
+	xfrm_address_t saddr;
+	struct xfrm_selector sel;
+	struct compat_xfrm_userpolicy_info policy;
+	/* 4 bytes additional padding on 64bit */
+	u32 aalgos, ealgos, calgos, seq;
+};
+
+struct compat_xfrm_userspi_info {
+	struct compat_xfrm_usersa_info info;
+	/* 4 bytes additional padding on 64bit */
+	u32 min, max;
+};
+
+struct compat_xfrm_user_expire {
+	struct compat_xfrm_usersa_info state;
+	/* 4 bytes additional padding on 64bit */
+	u8 hard;
+};
+
+struct compat_xfrm_user_polexpire {
+	struct compat_xfrm_userpolicy_info pol;
+	/* 4 bytes additional padding on 64bit */
+	u8 hard;
+};
+
+static bool xfrm_msg_compat(const struct sk_buff *skb)
+{
+	return unlikely(NETLINK_CB(skb).msg_compat);
+}
+
+static struct sk_buff *xfrm_add_compatskb(struct sk_buff *skb,
+					  unsigned int len, gfp_t gfp)
+{
+	struct sk_buff *compatskb = nlmsg_new(len, gfp);
+
+	WARN_ON(skb_shinfo(skb)->frag_list);
+
+	skb_shinfo(skb)->frag_list = compatskb;
+	return compatskb;
+}
+#else
+static inline bool xfrm_msg_compat(const struct sk_buff *skb)
+{
+	return false;
+}
+
+static inline struct sk_buff *xfrm_add_compatskb(struct sk_buff *skb,
+						 unsigned int len, gfp_t gfp)
+{
+	return NULL;
+}
+
+/*
+ * avoids #ifdefs all over the place. Use of these must be conditional via
+ * xfrm_msg_compat/xfrm_add_compatskb so compiler can remove branches.
+ */
+#define compat_xfrm_user_expire     xfrm_user_expire
+#define compat_xfrm_user_acquire    xfrm_user_acquire
+#define compat_xfrm_user_polexpire  xfrm_user_polexpire
+#define compat_xfrm_userpolicy_info xfrm_userpolicy_info
+#define compat_xfrm_usersa_info     xfrm_usersa_info
+#define compat_xfrm_userspi_info    xfrm_userspi_info
+
+#endif /* CONFIG_COMPAT_FOR_U64_ALIGNMENT */
+
+/*
+ * userspace size of some structures is smaller due to different u64
+ * u64 alignment on x86 platform.
+ *
+ * Some of the structures need to use the compat_* structure definition
+ * when accessing certain members, see compat_ structures above.
+ */
+#define XMSGDELTA(type) (sizeof(struct type) - sizeof(struct compat_##type))
+static const u8 xfrm_msg_min_compat_pad[XFRM_NR_MSGTYPES] = {
+	[XFRM_MSG_NEWSA     - XFRM_MSG_BASE] = XMSGDELTA(xfrm_usersa_info),
+	[XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = XMSGDELTA(xfrm_userpolicy_info),
+	[XFRM_MSG_ALLOCSPI  - XFRM_MSG_BASE] = XMSGDELTA(xfrm_userspi_info),
+	[XFRM_MSG_ACQUIRE   - XFRM_MSG_BASE] = XMSGDELTA(xfrm_user_acquire),
+	[XFRM_MSG_EXPIRE    - XFRM_MSG_BASE] = XMSGDELTA(xfrm_user_expire),
+	[XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGDELTA(xfrm_userpolicy_info),
+	[XFRM_MSG_UPDSA     - XFRM_MSG_BASE] = XMSGDELTA(xfrm_usersa_info),
+	[XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = XMSGDELTA(xfrm_user_polexpire),
+};
+#undef XMSGDELTA
+
+static int get_user_expire_hard(const struct sk_buff *skb,
+				const struct xfrm_user_expire *ue)
+{
+	if (xfrm_msg_compat(skb)) {
+		const struct compat_xfrm_user_expire *cmpt;
+		cmpt = (const struct compat_xfrm_user_expire *) ue;
+		return cmpt->hard;
+	}
+	return ue->hard;
+}
+
+static int get_user_polexpire_hard(const struct sk_buff *skb,
+				   const struct xfrm_user_polexpire *ue)
+{
+	if (xfrm_msg_compat(skb)) {
+		const struct compat_xfrm_user_polexpire *cmpt;
+		cmpt = (const struct compat_xfrm_user_polexpire *) ue;
+		return cmpt->hard;
+	}
+	return ue->hard;
+}
+
 static inline int aead_len(struct xfrm_algo_aead *alg)
 {
 	return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
@@ -701,7 +845,7 @@ nla_put_failure:
 }
 
 static int copy_one_state(struct sk_buff *skb, struct xfrm_state *x,
-			  struct xfrm_dump_info *sp)
+			  struct xfrm_dump_info *sp, bool compat)
 {
 	struct sk_buff *in_skb = sp->in_skb;
 	struct xfrm_usersa_info *p;
@@ -709,6 +853,9 @@ static int copy_one_state(struct sk_buff *skb, struct xfrm_state *x,
 	size_t len = sizeof(*p);
 	int err;
 
+	if (compat)
+		len = sizeof(struct compat_xfrm_usersa_info);
+
 	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq,
 			XFRM_MSG_NEWSA, len, sp->nlmsg_flags);
 	if (nlh == NULL)
@@ -732,7 +879,14 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
 {
 	struct xfrm_dump_info *sp = ptr;
 	struct sk_buff *skb = sp->out_skb;
-	int ret = copy_one_state(skb, x, sp);
+	int ret = copy_one_state(skb, x, sp, false);
+#ifdef CONFIG_COMPAT_FOR_U64_ALIGNMENT
+	if (ret == 0) {
+		skb = skb_shinfo(skb)->frag_list;
+		if (skb)
+			copy_one_state(skb, x, sp, true);
+	}
+#endif
 	return ret;
 }
 
@@ -762,6 +916,8 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
 		xfrm_state_walk_init(walk, 0);
 	}
 
+	xfrm_add_compatskb(skb, NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+
 	(void) xfrm_state_walk(net, walk, dump_one_state, &info);
 
 	return skb->len;
@@ -782,6 +938,8 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
 	info.nlmsg_seq = seq;
 	info.nlmsg_flags = 0;
 
+	xfrm_add_compatskb(skb, NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+
 	if (dump_one_state(x, 0, &info)) {
 		kfree_skb(skb);
 		return NULL;
@@ -953,6 +1111,29 @@ static int verify_userspi_info(struct xfrm_userspi_info *p)
 	return 0;
 }
 
+static int compat_verify_userspi_info(struct xfrm_userspi_info *p)
+{
+	struct compat_xfrm_userspi_info *compat;
+
+	compat = (struct compat_xfrm_userspi_info  *) p;
+
+	switch (p->info.id.proto) {
+	case IPPROTO_AH:
+	case IPPROTO_ESP:
+		break;
+	case IPPROTO_COMP:
+		if (compat->max >= 0x10000)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (compat->min > compat->max)
+		return -EINVAL;
+	return 0;
+}
+
 static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
 		struct nlattr **attrs)
 {
@@ -967,7 +1148,10 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct xfrm_mark m;
 
 	p = nlmsg_data(nlh);
-	err = verify_userspi_info(p);
+	if (xfrm_msg_compat(skb))
+		err = compat_verify_userspi_info(p);
+	else
+		err = verify_userspi_info(p);
 	if (err)
 		goto out_noput;
 
@@ -993,8 +1177,14 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
 	err = -ENOENT;
 	if (x == NULL)
 		goto out_noput;
+	if (xfrm_msg_compat(skb)) {
+		struct compat_xfrm_userspi_info *compat;
+		compat = (struct compat_xfrm_userspi_info *) p;
+		err = xfrm_alloc_spi(x, compat->min, compat->max);
+	} else {
+		err = xfrm_alloc_spi(x, p->min, p->max);
+	}
 
-	err = xfrm_alloc_spi(x, p->min, p->max);
 	if (err)
 		goto out;
 
@@ -1368,13 +1558,16 @@ static inline int copy_to_user_policy_type(u8 type, struct sk_buff *skb)
 #endif
 
 static int copy_one_policy(struct sk_buff *skb, struct xfrm_policy *xp,
-			   int dir, struct xfrm_dump_info *sp)
+			   int dir, struct xfrm_dump_info *sp, bool compat)
 {
 	struct xfrm_userpolicy_info *p;
 	struct sk_buff *in_skb = sp->in_skb;
 	struct nlmsghdr *nlh;
 	size_t len = sizeof(*p);
 
+	if (compat)
+		len = sizeof(struct compat_xfrm_userpolicy_info);
+
 	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq,
 			XFRM_MSG_NEWPOLICY, len, sp->nlmsg_flags);
 	if (nlh == NULL)
@@ -1405,7 +1598,14 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir,
 {
 	struct xfrm_dump_info *sp = ptr;
 	struct sk_buff *skb = sp->out_skb;
-	int ret = copy_one_policy(skb, xp, dir, sp);
+	int ret = copy_one_policy(skb, xp, dir, sp, false);
+#ifdef CONFIG_COMPAT_FOR_U64_ALIGNMENT
+	if (ret == 0) {
+		skb = skb_shinfo(skb)->frag_list;
+		if (skb)
+			copy_one_policy(skb, xp, dir, sp, true);
+	}
+#endif
 	return ret;
 }
 
@@ -1436,6 +1636,8 @@ static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb)
 		xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY);
 	}
 
+	xfrm_add_compatskb(skb, NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+
 	(void) xfrm_policy_walk(net, walk, dump_one_policy, &info);
 
 	return skb->len;
@@ -1457,6 +1659,8 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
 	info.nlmsg_seq = seq;
 	info.nlmsg_flags = 0;
 
+	xfrm_add_compatskb(skb, NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+
 	if (dump_one_policy(xp, dir, 0, &info) < 0) {
 		kfree_skb(skb);
 		return NULL;
@@ -1791,7 +1995,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 		goto out;
 
 	err = 0;
-	hard = up->hard;
+	hard = get_user_polexpire_hard(skb, up);
 	if (hard) {
 		uid_t loginuid = NETLINK_CB(skb).loginuid;
 		uid_t sessionid = NETLINK_CB(skb).sessionid;
@@ -1831,7 +2035,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 	err = -EINVAL;
 	if (x->km.state != XFRM_STATE_VALID)
 		goto out;
-	hard = ue->hard;
+	hard = get_user_expire_hard(skb, ue);
 	km_state_expired(x, hard, current->pid);
 
 	if (hard) {
@@ -1848,6 +2052,23 @@ out:
 	return err;
 }
 
+static void acquire_extract_algos(const struct sk_buff *skb,
+				   struct xfrm_tmpl *t,
+				   const struct xfrm_user_acquire *ua)
+{
+	if (!xfrm_msg_compat(skb)) {
+		t->aalgos = ua->aalgos;
+		t->ealgos = ua->ealgos;
+		t->calgos = ua->calgos;
+	} else {
+		const struct compat_xfrm_user_acquire *compat_ua;
+		compat_ua = (const struct compat_xfrm_user_acquire *) ua;
+		t->aalgos = compat_ua->aalgos;
+		t->ealgos = compat_ua->ealgos;
+		t->calgos = compat_ua->calgos;
+	}
+}
+
 static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
 		struct nlattr **attrs)
 {
@@ -1889,9 +2110,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
 		x->props.mode = t->mode;
 		x->props.reqid = t->reqid;
 		x->props.family = ut->family;
-		t->aalgos = ua->aalgos;
-		t->ealgos = ua->ealgos;
-		t->calgos = ua->calgos;
+		acquire_extract_algos(skb, t, ua);
 		err = km_query(x, t, xp);
 
 	}
@@ -2173,6 +2392,13 @@ static struct xfrm_link {
 	[XFRM_MSG_GETSPDINFO  - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo   },
 };
 
+static int xfrm_msg_hdrlen(const struct sk_buff *skb, int type)
+{
+	if (xfrm_msg_compat(skb))
+		return xfrm_msg_min[type] - xfrm_msg_min_compat_pad[type];
+	return xfrm_msg_min[type];
+}
+
 static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
@@ -2200,7 +2426,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		return netlink_dump_start(net->xfrm.nlsk, skb, nlh, link->dump, link->done);
 	}
 
-	err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX,
+	err = nlmsg_parse(nlh, xfrm_msg_hdrlen(skb, type), attrs, XFRMA_MAX,
 			  xfrma_policy);
 	if (err < 0)
 		return err;
@@ -2246,10 +2472,27 @@ nla_put_failure:
 	return -EMSGSIZE;
 }
 
+static void compat_build_expire(struct sk_buff *skb, struct xfrm_state *x,
+				struct km_event *c)
+{
+	struct compat_xfrm_user_expire *compat_ue;
+	struct nlmsghdr *nlh;
+
+	nlh = nlmsg_put(skb, c->pid, 0, XFRM_MSG_EXPIRE, sizeof(*compat_ue), 0);
+	if (nlh == NULL)
+		return;
+
+	compat_ue = nlmsg_data(nlh);
+	copy_to_user_state(x, (struct xfrm_usersa_info *) &compat_ue->state);
+	compat_ue->hard = (c->data.hard != 0) ? 1 : 0;
+
+	nlmsg_end(skb, nlh);
+}
+
 static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
 {
 	struct net *net = xs_net(x);
-	struct sk_buff *skb;
+	struct sk_buff *skb, *cskb;
 
 	skb = nlmsg_new(xfrm_expire_msgsize(), GFP_ATOMIC);
 	if (skb == NULL)
@@ -2260,6 +2503,9 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
 		return -EMSGSIZE;
 	}
 
+	if ((cskb = xfrm_add_compatskb(skb, xfrm_expire_msgsize(), GFP_ATOMIC)))
+		compat_build_expire(cskb, x, c);
+
 	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
 }
 
@@ -2354,8 +2600,16 @@ static int xfrm_notify_sa_headlen(const struct km_event *c)
 	return sizeof(struct xfrm_usersa_info);
 }
 
+static int compat_xfrm_notify_sa_headlen(const struct km_event *c)
+{
+	if (c->event == XFRM_MSG_DELSA)
+		return sizeof(struct xfrm_usersa_id);
+	return sizeof(struct compat_xfrm_usersa_info);
+}
+
 static int copy_to_user_xfrm_notify_sa(struct sk_buff *skb,
-				       struct xfrm_state *x, struct km_event *c)
+				       struct xfrm_state *x,
+				       struct km_event *c, bool compat)
 {
 	struct xfrm_usersa_info *p;
 	struct xfrm_usersa_id *id;
@@ -2363,6 +2617,11 @@ static int copy_to_user_xfrm_notify_sa(struct sk_buff *skb,
 	int sizeof_usersa_info = sizeof(*p);
 	int headlen = xfrm_notify_sa_headlen(c);
 
+	if (compat) {
+		headlen = compat_xfrm_notify_sa_headlen(c);
+		sizeof_usersa_info = sizeof(struct compat_xfrm_usersa_info);
+	}
+
 	nlh = nlmsg_put(skb, c->pid, c->seq, c->event, headlen, 0);
 	if (nlh == NULL)
 		goto nla_put_failure;
@@ -2397,7 +2656,7 @@ nla_put_failure:
 
 static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
 {
-	struct sk_buff *skb;
+	struct sk_buff *skb, *cskb;
 	struct net *net = xs_net(x);
 	int len = xfrm_notify_sa_len(x, c);
 
@@ -2405,9 +2664,12 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
 	if (skb == NULL)
 		return -ENOMEM;
 
-	if (copy_to_user_xfrm_notify_sa(skb, x, c))
+	if (copy_to_user_xfrm_notify_sa(skb, x, c, false))
 		goto nla_put_failure;
 
+	if ((cskb = xfrm_add_compatskb(skb, len, GFP_ATOMIC)))
+		copy_to_user_xfrm_notify_sa(cskb, x, c, true);
+
 	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC);
 
 nla_put_failure:
@@ -2452,12 +2714,16 @@ static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x,
 
 static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
 			 struct xfrm_tmpl *xt, struct xfrm_policy *xp,
-			 int dir)
+			 int dir, bool compat)
 {
 	struct xfrm_user_acquire *ua;
 	size_t len = sizeof(*ua);
 	struct nlmsghdr *nlh;
 	__u32 seq = xfrm_get_acqseq();
+	struct compat_xfrm_user_acquire *compat_ua;
+
+	if (compat)
+		len = sizeof(*compat_ua);
 
 	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_ACQUIRE, len, 0);
 	if (nlh == NULL)
@@ -2468,10 +2734,19 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
 	memcpy(&ua->saddr, &x->props.saddr, sizeof(ua->saddr));
 	memcpy(&ua->sel, &x->sel, sizeof(ua->sel));
 	copy_to_user_policy(xp, &ua->policy, dir);
-	ua->aalgos = xt->aalgos;
-	ua->ealgos = xt->ealgos;
-	ua->calgos = xt->calgos;
-	ua->seq = x->km.seq = seq;
+
+	if (compat) {
+		compat_ua = nlmsg_data(nlh);
+		compat_ua->aalgos = xt->aalgos;
+		compat_ua->ealgos = xt->ealgos;
+		compat_ua->calgos = xt->calgos;
+		compat_ua->seq = x->km.seq = seq;
+	} else {
+		ua->aalgos = xt->aalgos;
+		ua->ealgos = xt->ealgos;
+		ua->calgos = xt->calgos;
+		ua->seq = x->km.seq = seq;
+	}
 
 	if (copy_to_user_tmpl(xp, skb) < 0)
 		goto nlmsg_failure;
@@ -2494,15 +2769,19 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
 			     struct xfrm_policy *xp, int dir)
 {
 	struct net *net = xs_net(x);
-	struct sk_buff *skb;
+	struct sk_buff *skb, *cskb;
 
 	skb = nlmsg_new(xfrm_acquire_msgsize(x, xp), GFP_ATOMIC);
 	if (skb == NULL)
 		return -ENOMEM;
 
-	if (build_acquire(skb, x, xt, xp, dir) < 0)
+	if (build_acquire(skb, x, xt, xp, dir, false) < 0)
 		BUG();
 
+	cskb = xfrm_add_compatskb(skb, xfrm_acquire_msgsize(x, xp), GFP_ATOMIC);
+	if (cskb)
+		build_acquire(cskb, x, xt, xp, dir, true);
+
 	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC);
 }
 
@@ -2576,12 +2855,16 @@ static inline size_t xfrm_polexpire_msgsize(struct xfrm_policy *xp)
 }
 
 static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
-			   int dir, struct km_event *c)
+			   int dir, struct km_event *c, bool compat)
 {
 	struct xfrm_user_polexpire *upe;
 	size_t len = sizeof(*upe);
 	struct nlmsghdr *nlh;
 	int hard = c->data.hard;
+	struct compat_xfrm_user_polexpire *upe_cmpt;
+
+	if (compat)
+		len = sizeof(*upe_cmpt);
 
 	nlh = nlmsg_put(skb, c->pid, 0, XFRM_MSG_POLEXPIRE, len, 0);
 	if (nlh == NULL)
@@ -2597,7 +2880,13 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
 		goto nlmsg_failure;
 	if (xfrm_mark_put(skb, &xp->mark))
 		goto nla_put_failure;
-	upe->hard = !!hard;
+
+	if (compat) {
+		upe_cmpt = nlmsg_data(nlh);
+		upe_cmpt->hard = !!hard;
+	} else {
+		upe->hard = !!hard;
+	}
 
 	return nlmsg_end(skb, nlh);
 
@@ -2610,15 +2899,19 @@ nlmsg_failure:
 static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
 {
 	struct net *net = xp_net(xp);
-	struct sk_buff *skb;
+	struct sk_buff *skb, *cskb;
 
 	skb = nlmsg_new(xfrm_polexpire_msgsize(xp), GFP_ATOMIC);
 	if (skb == NULL)
 		return -ENOMEM;
 
-	if (build_polexpire(skb, xp, dir, c) < 0)
+	if (build_polexpire(skb, xp, dir, c, false) < 0)
 		BUG();
 
+	cskb = xfrm_add_compatskb(skb, xfrm_polexpire_msgsize(xp), GFP_ATOMIC);
+	if (cskb)
+		build_polexpire(cskb, xp, dir, c, true);
+
 	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
 }
 
@@ -2644,9 +2937,16 @@ static int xfrm_notify_policy_headlen(const struct km_event *c)
 	return sizeof(struct xfrm_userpolicy_info);
 }
 
+static int compat_xfrm_notify_policy_headlen(const struct km_event *c)
+{
+	if (c->event == XFRM_MSG_DELPOLICY)
+		return sizeof(struct xfrm_userpolicy_id);
+	return sizeof(struct compat_xfrm_userpolicy_info);
+}
+
 static int copy_to_user_xfrm_notify_policy(struct sk_buff *skb, int dir,
 					   struct xfrm_policy *xp,
-					   struct km_event *c)
+					   struct km_event *c, bool compat)
 {
 	struct xfrm_userpolicy_info *p;
 	struct xfrm_userpolicy_id *id;
@@ -2654,6 +2954,12 @@ static int copy_to_user_xfrm_notify_policy(struct sk_buff *skb, int dir,
 	int sizeof_userpol_info = sizeof(*p);
 	int headlen = xfrm_notify_policy_headlen(c);
 
+	if (compat) {
+		sizeof_userpol_info =
+				sizeof(struct compat_xfrm_userpolicy_info);
+		headlen = compat_xfrm_notify_policy_headlen(c);
+	}
+
 	nlh = nlmsg_put(skb, c->pid, c->seq, c->event, headlen, 0);
 	if (nlh == NULL)
 		goto nlmsg_failure;
@@ -2699,15 +3005,18 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir,
 			      struct km_event *c)
 {
 	struct net *net = xp_net(xp);
-	struct sk_buff *skb;
+	struct sk_buff *skb, *cskb;
 	int len = xfrm_notify_policy_len(xp, c);
 
 	skb = nlmsg_new(len, GFP_ATOMIC);
 	if (skb == NULL)
 		return -ENOMEM;
-	if (copy_to_user_xfrm_notify_policy(skb, dir, xp, c))
+	if (copy_to_user_xfrm_notify_policy(skb, dir, xp, c, false))
 		goto nlmsg_failure;
 
+	if ((cskb = xfrm_add_compatskb(skb, len, GFP_ATOMIC)))
+		copy_to_user_xfrm_notify_policy(cskb, dir, xp, c, true);
+
 	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
 
 nlmsg_failure:
-- 
1.6.4.4


^ permalink raw reply related

* [PATCH 3/4] xfrm: split nlmsg allocation and data copying
From: Florian Westphal @ 2010-04-05 22:27 UTC (permalink / raw)
  To: netdev; +Cc: johannes, Florian Westphal
In-Reply-To: <1270506431-25578-1-git-send-email-fw@strlen.de>

To support 32bit userland with different u64 alignment requirements
than a 64bit kernel (COMPAT_FOR_U64_ALIGNMENT), it is
necessary to prepare messages containing affected structures
twice: once in the format expected by 64bit listeners, one
in the format expected by 32bit applications.

In order to minimize copy & pasting and re-use existing
code where possible, split nlmsg allocation and data copying.

Also, replace foo(..., sizeof(*structure)) with

len = sizeof(*structure);
foo(..., len);

so len can be made conditional if we are preparing a compat message.
This will be done in a followup-patch.

With suggestions from Johannes Berg.

Cc: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/xfrm/xfrm_user.c |  163 ++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 120 insertions(+), 43 deletions(-)

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index a267fbd..3aba167 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -700,17 +700,17 @@ nla_put_failure:
 	return -EMSGSIZE;
 }
 
-static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
+static int copy_one_state(struct sk_buff *skb, struct xfrm_state *x,
+			  struct xfrm_dump_info *sp)
 {
-	struct xfrm_dump_info *sp = ptr;
 	struct sk_buff *in_skb = sp->in_skb;
-	struct sk_buff *skb = sp->out_skb;
 	struct xfrm_usersa_info *p;
 	struct nlmsghdr *nlh;
+	size_t len = sizeof(*p);
 	int err;
 
 	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq,
-			XFRM_MSG_NEWSA, sizeof(*p), sp->nlmsg_flags);
+			XFRM_MSG_NEWSA, len, sp->nlmsg_flags);
 	if (nlh == NULL)
 		return -EMSGSIZE;
 
@@ -728,6 +728,14 @@ nla_put_failure:
 	return err;
 }
 
+static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
+{
+	struct xfrm_dump_info *sp = ptr;
+	struct sk_buff *skb = sp->out_skb;
+	int ret = copy_one_state(skb, x, sp);
+	return ret;
+}
+
 static int xfrm_dump_sa_done(struct netlink_callback *cb)
 {
 	struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
@@ -1359,16 +1367,16 @@ static inline int copy_to_user_policy_type(u8 type, struct sk_buff *skb)
 }
 #endif
 
-static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr)
+static int copy_one_policy(struct sk_buff *skb, struct xfrm_policy *xp,
+			   int dir, struct xfrm_dump_info *sp)
 {
-	struct xfrm_dump_info *sp = ptr;
 	struct xfrm_userpolicy_info *p;
 	struct sk_buff *in_skb = sp->in_skb;
-	struct sk_buff *skb = sp->out_skb;
 	struct nlmsghdr *nlh;
+	size_t len = sizeof(*p);
 
 	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq,
-			XFRM_MSG_NEWPOLICY, sizeof(*p), sp->nlmsg_flags);
+			XFRM_MSG_NEWPOLICY, len, sp->nlmsg_flags);
 	if (nlh == NULL)
 		return -EMSGSIZE;
 
@@ -1392,6 +1400,15 @@ nlmsg_failure:
 	return -EMSGSIZE;
 }
 
+static int dump_one_policy(struct xfrm_policy *xp, int dir,
+			   int count, void *ptr)
+{
+	struct xfrm_dump_info *sp = ptr;
+	struct sk_buff *skb = sp->out_skb;
+	int ret = copy_one_policy(skb, xp, dir, sp);
+	return ret;
+}
+
 static int xfrm_dump_policy_done(struct netlink_callback *cb)
 {
 	struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
@@ -1733,7 +1750,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct xfrm_user_polexpire *up = nlmsg_data(nlh);
 	struct xfrm_userpolicy_info *p = &up->pol;
 	u8 type = XFRM_POLICY_TYPE_MAIN;
-	int err = -ENOENT;
+	int hard, err = -ENOENT;
 	struct xfrm_mark m;
 	u32 mark = xfrm_mark_get(attrs, &m);
 
@@ -1774,7 +1791,8 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 		goto out;
 
 	err = 0;
-	if (up->hard) {
+	hard = up->hard;
+	if (hard) {
 		uid_t loginuid = NETLINK_CB(skb).loginuid;
 		uid_t sessionid = NETLINK_CB(skb).sessionid;
 		u32 sid = NETLINK_CB(skb).sid;
@@ -1785,7 +1803,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 		// reset the timers here?
 		printk("Dont know what to do with soft policy expire\n");
 	}
-	km_policy_expired(xp, p->dir, up->hard, current->pid);
+	km_policy_expired(xp, p->dir, hard, current->pid);
 
 out:
 	xfrm_pol_put(xp);
@@ -1797,7 +1815,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 {
 	struct net *net = sock_net(skb->sk);
 	struct xfrm_state *x;
-	int err;
+	int hard, err;
 	struct xfrm_user_expire *ue = nlmsg_data(nlh);
 	struct xfrm_usersa_info *p = &ue->state;
 	struct xfrm_mark m;
@@ -1813,9 +1831,10 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 	err = -EINVAL;
 	if (x->km.state != XFRM_STATE_VALID)
 		goto out;
-	km_state_expired(x, ue->hard, current->pid);
+	hard = ue->hard;
+	km_state_expired(x, hard, current->pid);
 
-	if (ue->hard) {
+	if (hard) {
 		uid_t loginuid = NETLINK_CB(skb).loginuid;
 		uid_t sessionid = NETLINK_CB(skb).sessionid;
 		u32 sid = NETLINK_CB(skb).sid;
@@ -2313,27 +2332,36 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x)
 	return l;
 }
 
-static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
+static int xfrm_notify_sa_len(struct xfrm_state *x, const struct km_event *c)
 {
-	struct net *net = xs_net(x);
-	struct xfrm_usersa_info *p;
-	struct xfrm_usersa_id *id;
-	struct nlmsghdr *nlh;
-	struct sk_buff *skb;
 	int len = xfrm_sa_len(x);
-	int headlen;
+	int headlen = sizeof(struct xfrm_usersa_info);
 
-	headlen = sizeof(*p);
 	if (c->event == XFRM_MSG_DELSA) {
 		len += nla_total_size(headlen);
-		headlen = sizeof(*id);
+		headlen = sizeof(struct xfrm_usersa_id);
 		len += nla_total_size(sizeof(struct xfrm_mark));
 	}
 	len += NLMSG_ALIGN(headlen);
 
-	skb = nlmsg_new(len, GFP_ATOMIC);
-	if (skb == NULL)
-		return -ENOMEM;
+	return len;
+}
+
+static int xfrm_notify_sa_headlen(const struct km_event *c)
+{
+	if (c->event == XFRM_MSG_DELSA)
+		return sizeof(struct xfrm_usersa_id);
+	return sizeof(struct xfrm_usersa_info);
+}
+
+static int copy_to_user_xfrm_notify_sa(struct sk_buff *skb,
+				       struct xfrm_state *x, struct km_event *c)
+{
+	struct xfrm_usersa_info *p;
+	struct xfrm_usersa_id *id;
+	struct nlmsghdr *nlh;
+	int sizeof_usersa_info = sizeof(*p);
+	int headlen = xfrm_notify_sa_headlen(c);
 
 	nlh = nlmsg_put(skb, c->pid, c->seq, c->event, headlen, 0);
 	if (nlh == NULL)
@@ -2349,7 +2377,7 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
 		id->family = x->props.family;
 		id->proto = x->id.proto;
 
-		attr = nla_reserve(skb, XFRMA_SA, sizeof(*p));
+		attr = nla_reserve(skb, XFRMA_SA, sizeof_usersa_info);
 		if (attr == NULL)
 			goto nla_put_failure;
 
@@ -2360,6 +2388,25 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
 		goto nla_put_failure;
 
 	nlmsg_end(skb, nlh);
+	return 0;
+nla_put_failure:
+	/* Somebody screwed up with xfrm_sa_len! */
+	WARN_ON(1);
+	return -1;
+}
+
+static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
+{
+	struct sk_buff *skb;
+	struct net *net = xs_net(x);
+	int len = xfrm_notify_sa_len(x, c);
+
+	skb = nlmsg_new(len, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+
+	if (copy_to_user_xfrm_notify_sa(skb, x, c))
+		goto nla_put_failure;
 
 	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC);
 
@@ -2408,10 +2455,11 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
 			 int dir)
 {
 	struct xfrm_user_acquire *ua;
+	size_t len = sizeof(*ua);
 	struct nlmsghdr *nlh;
 	__u32 seq = xfrm_get_acqseq();
 
-	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_ACQUIRE, sizeof(*ua), 0);
+	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_ACQUIRE, len, 0);
 	if (nlh == NULL)
 		return -EMSGSIZE;
 
@@ -2531,10 +2579,11 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
 			   int dir, struct km_event *c)
 {
 	struct xfrm_user_polexpire *upe;
+	size_t len = sizeof(*upe);
 	struct nlmsghdr *nlh;
 	int hard = c->data.hard;
 
-	nlh = nlmsg_put(skb, c->pid, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe), 0);
+	nlh = nlmsg_put(skb, c->pid, 0, XFRM_MSG_POLEXPIRE, len, 0);
 	if (nlh == NULL)
 		return -EMSGSIZE;
 
@@ -2573,28 +2622,37 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve
 	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
 }
 
-static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
+static int xfrm_notify_policy_len(struct xfrm_policy *xp, struct km_event *c)
 {
-	struct net *net = xp_net(xp);
-	struct xfrm_userpolicy_info *p;
-	struct xfrm_userpolicy_id *id;
-	struct nlmsghdr *nlh;
-	struct sk_buff *skb;
 	int len = nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
-	int headlen;
+	int headlen = sizeof(struct xfrm_userpolicy_info);
 
-	headlen = sizeof(*p);
 	if (c->event == XFRM_MSG_DELPOLICY) {
 		len += nla_total_size(headlen);
-		headlen = sizeof(*id);
+		headlen = sizeof(struct xfrm_userpolicy_id);
 	}
 	len += userpolicy_type_attrsize();
 	len += nla_total_size(sizeof(struct xfrm_mark));
 	len += NLMSG_ALIGN(headlen);
+	return len;
+}
 
-	skb = nlmsg_new(len, GFP_ATOMIC);
-	if (skb == NULL)
-		return -ENOMEM;
+static int xfrm_notify_policy_headlen(const struct km_event *c)
+{
+	if (c->event == XFRM_MSG_DELPOLICY)
+		return sizeof(struct xfrm_userpolicy_id);
+	return sizeof(struct xfrm_userpolicy_info);
+}
+
+static int copy_to_user_xfrm_notify_policy(struct sk_buff *skb, int dir,
+					   struct xfrm_policy *xp,
+					   struct km_event *c)
+{
+	struct xfrm_userpolicy_info *p;
+	struct xfrm_userpolicy_id *id;
+	struct nlmsghdr *nlh;
+	int sizeof_userpol_info = sizeof(*p);
+	int headlen = xfrm_notify_policy_headlen(c);
 
 	nlh = nlmsg_put(skb, c->pid, c->seq, c->event, headlen, 0);
 	if (nlh == NULL)
@@ -2612,7 +2670,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *
 		else
 			memcpy(&id->sel, &xp->selector, sizeof(id->sel));
 
-		attr = nla_reserve(skb, XFRMA_POLICY, sizeof(*p));
+		attr = nla_reserve(skb, XFRMA_POLICY, sizeof_userpol_info);
 		if (attr == NULL)
 			goto nlmsg_failure;
 
@@ -2630,10 +2688,29 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *
 
 	nlmsg_end(skb, nlh);
 
-	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
+	return 0;
 
 nla_put_failure:
 nlmsg_failure:
+	return -1;
+}
+
+static int xfrm_notify_policy(struct xfrm_policy *xp, int dir,
+			      struct km_event *c)
+{
+	struct net *net = xp_net(xp);
+	struct sk_buff *skb;
+	int len = xfrm_notify_policy_len(xp, c);
+
+	skb = nlmsg_new(len, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+	if (copy_to_user_xfrm_notify_policy(skb, dir, xp, c))
+		goto nlmsg_failure;
+
+	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
+
+nlmsg_failure:
 	kfree_skb(skb);
 	return -1;
 }
-- 
1.6.4.4


^ permalink raw reply related

* [PATCH 2/4] netlink: store MSG_CMSG_COMPAT flag in netlink_skb_parms
From: Florian Westphal @ 2010-04-05 22:27 UTC (permalink / raw)
  To: netdev; +Cc: johannes, Florian Westphal
In-Reply-To: <1270506431-25578-1-git-send-email-fw@strlen.de>

This allows the netlink processing context to determine if the data
needs any 32 bit fixups.

Cc: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/linux/netlink.h  |    1 +
 net/netlink/af_netlink.c |    3 +++
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 6eaca5e..031e528 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -164,6 +164,7 @@ struct netlink_skb_parms {
 	__u32			loginuid;	/* Login (audit) uid */
 	__u32			sessionid;	/* Session id (audit) */
 	__u32			sid;		/* SELinux security id */
+	bool			msg_compat;	/* Message needs 32bit fixups */
 };
 
 #define NETLINK_CB(skb)		(*(struct netlink_skb_parms*)&((skb)->cb))
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index beaada0..47c8314 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1339,6 +1339,9 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	NETLINK_CB(skb).dst_group = dst_group;
 	NETLINK_CB(skb).loginuid = audit_get_loginuid(current);
 	NETLINK_CB(skb).sessionid = audit_get_sessionid(current);
+#ifdef CONFIG_COMPAT_NETLINK_MESSAGES
+	NETLINK_CB(skb).msg_compat = !!(msg->msg_flags & MSG_CMSG_COMPAT);
+#endif
 	security_task_getsecid(current, &(NETLINK_CB(skb).sid));
 	memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 
-- 
1.6.4.4


^ permalink raw reply related

* [PATCH 1/4] netlink: append NLMSG_DONE to compatskb, too
From: Florian Westphal @ 2010-04-05 22:27 UTC (permalink / raw)
  To: netdev; +Cc: johannes, Florian Westphal, Florian Westphal
In-Reply-To: <1270506431-25578-1-git-send-email-fw@strlen.de>

From: Florian Westphal <fwestphal@astaro.com>

modules using netlink may supply a 2nd skb, (via frag_list)
that contains an alternative data set meant for applications
using 32bit compatibility mode.

In such a case, netlink_recvmsg will use this 2nd skb instead of the
original one.

Without this patch, such compat applications will retrieve
all netlink dump data, but will then get an unexpected EOF.

Cc: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netlink/af_netlink.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 274d977..beaada0 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1709,6 +1709,14 @@ static int netlink_dump(struct sock *sk)
 
 	memcpy(nlmsg_data(nlh), &len, sizeof(len));
 
+#ifdef CONFIG_COMPAT_NETLINK_MESSAGES
+	if (unlikely(skb_shinfo(skb)->frag_list)) {
+		nlh = nlmsg_put_answer(skb_shinfo(skb)->frag_list, cb,
+					NLMSG_DONE, sizeof(len), NLM_F_MULTI);
+		if (nlh)
+			memcpy(nlmsg_data(nlh), &len, sizeof(len));
+	}
+#endif
 	if (sk_filter(sk, skb))
 		kfree_skb(skb);
 	else {
-- 
1.6.4.4


^ permalink raw reply related

* [PATCH v3 0/4] xfrm: add x86 CONFIG_COMPAT support
From: Florian Westphal @ 2010-04-05 22:27 UTC (permalink / raw)
  To: netdev; +Cc: johannes

3rd version of xfrm x86-compat patch set.

No changes since v2, except patch 5/5, which I dropped from the set.

This has the consequence that compat support is restricted to
applications that use sendmsg() to talk to the kernel (e.g. iproute2
would work); because write() will not go through the socket compat
layer (and thus, the MSG_CMSG_COMPAT won't be set on messages sent
by means of write() ).

I sent a patch that solved this by adding a sys_compat_write syscall
and a ->compat_aio_write() to struct file_operations to the
vfs mailing list, but that patch was ignored by the vfs people,
and the x86 folks did not exactly like the idea either.

So this leaves three alternatives:
1 - drop the whole idea and keep the current status.
2 - Add new structure definitions (with new numbering) that would work
    everywhere, keep the old ones for backwards compatibility (This
    was suggested by Arnd Bergmann).
3 - apply this patch set and tell userspace to move the sendmsg() when
    they want to work with xfrm on x86_64 with 32 bit userland.

Other than that, I am out of ideas.

Patch set description:

At the moment it is not possible to use the xfrm netlink interface on
x86_64 with a 32bit userland.

The problem exists because a few structures, e.g. struct xfrm_usersa_info,
have different sizes in user/kernelspace (3 byte padding on x86, 7
byte on x86_64) due to different alignment requirements of "u64".

First two patches add necessary CONFIG_COMPAT_NETLINK_MESSAGES
infrastructure to netlink in/output path.

Patch 3 is a refactoring patch to split functionality (especially
nlmsg allocation and adding data to the nlmsg) in order to
re-use code and ease review.

Patch 4 adds CONFIG_COMPAT_FOR_U64_ALIGNMENT support to xfrm.

Florian Westphal (4):
      netlink: append NLMSG_DONE to compatskb, too
      netlink: store MSG_CMSG_COMPAT flag in netlink_skb_parms
      xfrm: split nlmsg allocation and data copying
      xfrm: CONFIG_COMPAT support for x86 architecture

 include/linux/netlink.h  |    1 +
 net/netlink/af_netlink.c |   11 +
 net/xfrm/Kconfig         |    1 +
 net/xfrm/xfrm_user.c     |  508 ++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 460 insertions(+), 61 deletions(-)

^ permalink raw reply

* [PATCH 11/11 v2] drivers/uwb: Rename dev_info to wdi
From: Joe Perches @ 2010-04-05 22:24 UTC (permalink / raw)
  To: Andrew Morton; +Cc: David Vrabel, netdev, linux-kernel
In-Reply-To: <6bd4d4dacf32631b72c3827a3b133a26e2e8b889.1270493677.git.joe@perches.com>

Neglected to check-in the include file changed

There is a macro called dev_info that prints struct device specific
information.  Having variables with the same name can be confusing and
prevents conversion of the macro to a function.

Rename the existing dev_info variables to something else in preparation
to converting the dev_info macro to a function.

Signed-off-by: Joe Perches <joe@perches.com>
---
 drivers/uwb/i1480/i1480u-wlp/lc.c |   16 ++++++------
 drivers/uwb/wlp/messages.c        |   40 ++++++++++++++++----------------
 drivers/uwb/wlp/sysfs.c           |   46 ++++++++++++++++++------------------
 drivers/uwb/wlp/wlp-lc.c          |   12 +++++-----
 include/linux/wlp.h               |    2 +-
 5 files changed, 58 insertions(+), 58 deletions(-)

diff --git a/drivers/uwb/i1480/i1480u-wlp/lc.c b/drivers/uwb/i1480/i1480u-wlp/lc.c
index f272dfe..bd52675 100644
--- a/drivers/uwb/i1480/i1480u-wlp/lc.c
+++ b/drivers/uwb/i1480/i1480u-wlp/lc.c
@@ -92,28 +92,28 @@ void i1480u_init(struct i1480u *i1480u)
  * information elements have intuitive mappings, other not.
  */
 static
-void i1480u_fill_device_info(struct wlp *wlp, struct wlp_device_info *dev_info)
+void i1480u_fill_device_info(struct wlp *wlp, struct wlp_device_info *wdi)
 {
 	struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp);
 	struct usb_device *usb_dev = i1480u->usb_dev;
 	/* Treat device name and model name the same */
 	if (usb_dev->descriptor.iProduct) {
 		usb_string(usb_dev, usb_dev->descriptor.iProduct,
-			   dev_info->name, sizeof(dev_info->name));
+			   wdi->name, sizeof(wdi->name));
 		usb_string(usb_dev, usb_dev->descriptor.iProduct,
-			   dev_info->model_name, sizeof(dev_info->model_name));
+			   wdi->model_name, sizeof(wdi->model_name));
 	}
 	if (usb_dev->descriptor.iManufacturer)
 		usb_string(usb_dev, usb_dev->descriptor.iManufacturer,
-			   dev_info->manufacturer,
-			   sizeof(dev_info->manufacturer));
-	scnprintf(dev_info->model_nr, sizeof(dev_info->model_nr), "%04x",
+			   wdi->manufacturer,
+			   sizeof(wdi->manufacturer));
+	scnprintf(wdi->model_nr, sizeof(wdi->model_nr), "%04x",
 		  __le16_to_cpu(usb_dev->descriptor.bcdDevice));
 	if (usb_dev->descriptor.iSerialNumber)
 		usb_string(usb_dev, usb_dev->descriptor.iSerialNumber,
-			   dev_info->serial, sizeof(dev_info->serial));
+			   wdi->serial, sizeof(wdi->serial));
 	/* FIXME: where should we obtain category? */
-	dev_info->prim_dev_type.category = cpu_to_le16(WLP_DEV_CAT_OTHER);
+	wdi->prim_dev_type.category = cpu_to_le16(WLP_DEV_CAT_OTHER);
 	/* FIXME: Complete OUI and OUIsubdiv attributes */
 }
 
diff --git a/drivers/uwb/wlp/messages.c b/drivers/uwb/wlp/messages.c
index 7516486..4057942 100644
--- a/drivers/uwb/wlp/messages.c
+++ b/drivers/uwb/wlp/messages.c
@@ -712,7 +712,7 @@ static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss,
 	struct sk_buff *_skb;
 	void *d1_itr;
 
-	if (wlp->dev_info == NULL) {
+	if (wlp->wdi == NULL) {
 		result = __wlp_setup_device_info(wlp);
 		if (result < 0) {
 			dev_err(dev, "WLP: Unable to setup device "
@@ -720,7 +720,7 @@ static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss,
 			goto error;
 		}
 	}
-	info = wlp->dev_info;
+	info = wlp->wdi;
 	_skb = dev_alloc_skb(sizeof(*_d1)
 		      + sizeof(struct wlp_attr_uuid_e)
 		      + sizeof(struct wlp_attr_wss_sel_mthd)
@@ -794,7 +794,7 @@ int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss,
 	void *d2_itr;
 	size_t mem_needed;
 
-	if (wlp->dev_info == NULL) {
+	if (wlp->wdi == NULL) {
 		result = __wlp_setup_device_info(wlp);
 		if (result < 0) {
 			dev_err(dev, "WLP: Unable to setup device "
@@ -802,7 +802,7 @@ int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss,
 			goto error;
 		}
 	}
-	info = wlp->dev_info;
+	info = wlp->wdi;
 	mem_needed = sizeof(*_d2)
 		      + sizeof(struct wlp_attr_uuid_e)
 		      + sizeof(struct wlp_attr_uuid_r)
@@ -970,7 +970,7 @@ error_parse:
  */
 static
 int wlp_get_variable_info(struct wlp *wlp, void *data,
-			  struct wlp_device_info *dev_info, ssize_t len)
+			  struct wlp_device_info *wdi, ssize_t len)
 {
 	struct device *dev = &wlp->rc->uwb_dev.dev;
 	size_t used = 0;
@@ -993,7 +993,7 @@ int wlp_get_variable_info(struct wlp *wlp, void *data,
 				goto error_parse;
 			}
 			result = wlp_get_manufacturer(wlp, data + used,
-						      dev_info->manufacturer,
+						      wdi->manufacturer,
 						      len - used);
 			if (result < 0) {
 				dev_err(dev, "WLP: Unable to obtain "
@@ -1011,7 +1011,7 @@ int wlp_get_variable_info(struct wlp *wlp, void *data,
 				goto error_parse;
 			}
 			result = wlp_get_model_name(wlp, data + used,
-						    dev_info->model_name,
+						    wdi->model_name,
 						    len - used);
 			if (result < 0) {
 				dev_err(dev, "WLP: Unable to obtain Model "
@@ -1028,7 +1028,7 @@ int wlp_get_variable_info(struct wlp *wlp, void *data,
 				goto error_parse;
 			}
 			result = wlp_get_model_nr(wlp, data + used,
-						  dev_info->model_nr,
+						  wdi->model_nr,
 						  len - used);
 			if (result < 0) {
 				dev_err(dev, "WLP: Unable to obtain Model "
@@ -1045,7 +1045,7 @@ int wlp_get_variable_info(struct wlp *wlp, void *data,
 				goto error_parse;
 			}
 			result = wlp_get_serial(wlp, data + used,
-						dev_info->serial, len - used);
+						wdi->serial, len - used);
 			if (result < 0) {
 				dev_err(dev, "WLP: Unable to obtain Serial "
 					"number attribute from D1 message.\n");
@@ -1061,7 +1061,7 @@ int wlp_get_variable_info(struct wlp *wlp, void *data,
 				goto error_parse;
 			}
 			result = wlp_get_prim_dev_type(wlp, data + used,
-						       &dev_info->prim_dev_type,
+						       &wdi->prim_dev_type,
 						       len - used);
 			if (result < 0) {
 				dev_err(dev, "WLP: Unable to obtain Primary "
@@ -1069,10 +1069,10 @@ int wlp_get_variable_info(struct wlp *wlp, void *data,
 					"message.\n");
 				goto error_parse;
 			}
-			dev_info->prim_dev_type.category =
-				le16_to_cpu(dev_info->prim_dev_type.category);
-			dev_info->prim_dev_type.subID =
-				le16_to_cpu(dev_info->prim_dev_type.subID);
+			wdi->prim_dev_type.category =
+				le16_to_cpu(wdi->prim_dev_type.category);
+			wdi->prim_dev_type.subID =
+				le16_to_cpu(wdi->prim_dev_type.subID);
 			last = WLP_ATTR_PRI_DEV_TYPE;
 			used += result;
 			break;
@@ -1098,7 +1098,7 @@ static
 int wlp_parse_d1_frame(struct wlp *wlp, struct sk_buff *skb,
 		       struct wlp_uuid *uuid_e,
 		       enum wlp_wss_sel_mthd *sel_mthd,
-		       struct wlp_device_info *dev_info,
+		       struct wlp_device_info *wdi,
 		       enum wlp_assc_error *assc_err)
 {
 	struct device *dev = &wlp->rc->uwb_dev.dev;
@@ -1123,7 +1123,7 @@ int wlp_parse_d1_frame(struct wlp *wlp, struct sk_buff *skb,
 		goto error_parse;
 	}
 	used += result;
-	result = wlp_get_dev_name(wlp, ptr + used, dev_info->name,
+	result = wlp_get_dev_name(wlp, ptr + used, wdi->name,
 				     len - used);
 	if (result < 0) {
 		dev_err(dev, "WLP: unable to obtain Device Name from D1 "
@@ -1131,7 +1131,7 @@ int wlp_parse_d1_frame(struct wlp *wlp, struct sk_buff *skb,
 		goto error_parse;
 	}
 	used += result;
-	result = wlp_get_variable_info(wlp, ptr + used, dev_info, len - used);
+	result = wlp_get_variable_info(wlp, ptr + used, wdi, len - used);
 	if (result < 0) {
 		dev_err(dev, "WLP: unable to obtain Device Information from "
 			"D1 message.\n");
@@ -1171,15 +1171,15 @@ void wlp_handle_d1_frame(struct work_struct *ws)
 	struct device *dev = &wlp->rc->uwb_dev.dev;
 	struct wlp_uuid uuid_e;
 	enum wlp_wss_sel_mthd sel_mthd = 0;
-	struct wlp_device_info dev_info;
+	struct wlp_device_info wdi;
 	enum wlp_assc_error assc_err;
 	struct sk_buff *resp = NULL;
 
 	/* Parse D1 frame */
 	mutex_lock(&wss->mutex);
 	mutex_lock(&wlp->mutex); /* to access wlp->uuid */
-	memset(&dev_info, 0, sizeof(dev_info));
-	result = wlp_parse_d1_frame(wlp, skb, &uuid_e, &sel_mthd, &dev_info,
+	memset(&wdi, 0, sizeof(wdi));
+	result = wlp_parse_d1_frame(wlp, skb, &uuid_e, &sel_mthd, &wdi,
 				    &assc_err);
 	if (result < 0) {
 		dev_err(dev, "WLP: Unable to parse incoming D1 frame.\n");
diff --git a/drivers/uwb/wlp/sysfs.c b/drivers/uwb/wlp/sysfs.c
index 6627c94..b24751c 100644
--- a/drivers/uwb/wlp/sysfs.c
+++ b/drivers/uwb/wlp/sysfs.c
@@ -333,12 +333,12 @@ ssize_t wlp_dev_##type##_show(struct wlp *wlp, char *buf)		\
 {									\
 	ssize_t result = 0;						\
 	mutex_lock(&wlp->mutex);					\
-	if (wlp->dev_info == NULL) {					\
+	if (wlp->wdi == NULL) {						\
 		result = __wlp_setup_device_info(wlp);			\
 		if (result < 0)						\
 			goto out;					\
 	}								\
-	result = scnprintf(buf, PAGE_SIZE, "%s\n", wlp->dev_info->type);\
+	result = scnprintf(buf, PAGE_SIZE, "%s\n", wlp->wdi->type);	\
 out:									\
 	mutex_unlock(&wlp->mutex);					\
 	return result;							\
@@ -360,14 +360,14 @@ ssize_t wlp_dev_##type##_store(struct wlp *wlp, const char *buf, size_t size)\
 	ssize_t result;							\
 	char format[10];						\
 	mutex_lock(&wlp->mutex);					\
-	if (wlp->dev_info == NULL) {					\
+	if (wlp->wdi == NULL) {						\
 		result = __wlp_alloc_device_info(wlp);			\
 		if (result < 0)						\
 			goto out;					\
 	}								\
-	memset(wlp->dev_info->type, 0, sizeof(wlp->dev_info->type));	\
+	memset(wlp->wdi->type, 0, sizeof(wlp->wdi->type));		\
 	sprintf(format, "%%%uc", len);					\
-	result = sscanf(buf, format, wlp->dev_info->type);		\
+	result = sscanf(buf, format, wlp->wdi->type);			\
 out:									\
 	mutex_unlock(&wlp->mutex);					\
 	return result < 0 ? result : size;				\
@@ -409,13 +409,13 @@ ssize_t wlp_dev_prim_category_show(struct wlp *wlp, char *buf)
 {
 	ssize_t result = 0;
 	mutex_lock(&wlp->mutex);
-	if (wlp->dev_info == NULL) {
+	if (wlp->wdi == NULL) {
 		result = __wlp_setup_device_info(wlp);
 		if (result < 0)
 			goto out;
 	}
 	result = scnprintf(buf, PAGE_SIZE, "%s\n",
-		  wlp_dev_category_str(wlp->dev_info->prim_dev_type.category));
+		  wlp_dev_category_str(wlp->wdi->prim_dev_type.category));
 out:
 	mutex_unlock(&wlp->mutex);
 	return result;
@@ -428,7 +428,7 @@ ssize_t wlp_dev_prim_category_store(struct wlp *wlp, const char *buf,
 	ssize_t result;
 	u16 cat;
 	mutex_lock(&wlp->mutex);
-	if (wlp->dev_info == NULL) {
+	if (wlp->wdi == NULL) {
 		result = __wlp_alloc_device_info(wlp);
 		if (result < 0)
 			goto out;
@@ -436,7 +436,7 @@ ssize_t wlp_dev_prim_category_store(struct wlp *wlp, const char *buf,
 	result = sscanf(buf, "%hu", &cat);
 	if ((cat >= WLP_DEV_CAT_COMPUTER && cat <= WLP_DEV_CAT_TELEPHONE)
 	    || cat == WLP_DEV_CAT_OTHER)
-		wlp->dev_info->prim_dev_type.category = cat;
+		wlp->wdi->prim_dev_type.category = cat;
 	else
 		result = -EINVAL;
 out:
@@ -449,15 +449,15 @@ ssize_t wlp_dev_prim_OUI_show(struct wlp *wlp, char *buf)
 {
 	ssize_t result = 0;
 	mutex_lock(&wlp->mutex);
-	if (wlp->dev_info == NULL) {
+	if (wlp->wdi == NULL) {
 		result = __wlp_setup_device_info(wlp);
 		if (result < 0)
 			goto out;
 	}
 	result = scnprintf(buf, PAGE_SIZE, "%02x:%02x:%02x\n",
-			   wlp->dev_info->prim_dev_type.OUI[0],
-			   wlp->dev_info->prim_dev_type.OUI[1],
-			   wlp->dev_info->prim_dev_type.OUI[2]);
+			   wlp->wdi->prim_dev_type.OUI[0],
+			   wlp->wdi->prim_dev_type.OUI[1],
+			   wlp->wdi->prim_dev_type.OUI[2]);
 out:
 	mutex_unlock(&wlp->mutex);
 	return result;
@@ -469,7 +469,7 @@ ssize_t wlp_dev_prim_OUI_store(struct wlp *wlp, const char *buf, size_t size)
 	ssize_t result;
 	u8 OUI[3];
 	mutex_lock(&wlp->mutex);
-	if (wlp->dev_info == NULL) {
+	if (wlp->wdi == NULL) {
 		result = __wlp_alloc_device_info(wlp);
 		if (result < 0)
 			goto out;
@@ -480,7 +480,7 @@ ssize_t wlp_dev_prim_OUI_store(struct wlp *wlp, const char *buf, size_t size)
 		result = -EINVAL;
 		goto out;
 	} else
-		memcpy(wlp->dev_info->prim_dev_type.OUI, OUI, sizeof(OUI));
+		memcpy(wlp->wdi->prim_dev_type.OUI, OUI, sizeof(OUI));
 out:
 	mutex_unlock(&wlp->mutex);
 	return result < 0 ? result : size;
@@ -492,13 +492,13 @@ ssize_t wlp_dev_prim_OUI_sub_show(struct wlp *wlp, char *buf)
 {
 	ssize_t result = 0;
 	mutex_lock(&wlp->mutex);
-	if (wlp->dev_info == NULL) {
+	if (wlp->wdi == NULL) {
 		result = __wlp_setup_device_info(wlp);
 		if (result < 0)
 			goto out;
 	}
 	result = scnprintf(buf, PAGE_SIZE, "%u\n",
-			   wlp->dev_info->prim_dev_type.OUIsubdiv);
+			   wlp->wdi->prim_dev_type.OUIsubdiv);
 out:
 	mutex_unlock(&wlp->mutex);
 	return result;
@@ -512,14 +512,14 @@ ssize_t wlp_dev_prim_OUI_sub_store(struct wlp *wlp, const char *buf,
 	unsigned sub;
 	u8 max_sub = ~0;
 	mutex_lock(&wlp->mutex);
-	if (wlp->dev_info == NULL) {
+	if (wlp->wdi == NULL) {
 		result = __wlp_alloc_device_info(wlp);
 		if (result < 0)
 			goto out;
 	}
 	result = sscanf(buf, "%u", &sub);
 	if (sub <= max_sub)
-		wlp->dev_info->prim_dev_type.OUIsubdiv = sub;
+		wlp->wdi->prim_dev_type.OUIsubdiv = sub;
 	else
 		result = -EINVAL;
 out:
@@ -532,13 +532,13 @@ ssize_t wlp_dev_prim_subcat_show(struct wlp *wlp, char *buf)
 {
 	ssize_t result = 0;
 	mutex_lock(&wlp->mutex);
-	if (wlp->dev_info == NULL) {
+	if (wlp->wdi == NULL) {
 		result = __wlp_setup_device_info(wlp);
 		if (result < 0)
 			goto out;
 	}
 	result = scnprintf(buf, PAGE_SIZE, "%u\n",
-			   wlp->dev_info->prim_dev_type.subID);
+			   wlp->wdi->prim_dev_type.subID);
 out:
 	mutex_unlock(&wlp->mutex);
 	return result;
@@ -552,14 +552,14 @@ ssize_t wlp_dev_prim_subcat_store(struct wlp *wlp, const char *buf,
 	unsigned sub;
 	__le16 max_sub = ~0;
 	mutex_lock(&wlp->mutex);
-	if (wlp->dev_info == NULL) {
+	if (wlp->wdi == NULL) {
 		result = __wlp_alloc_device_info(wlp);
 		if (result < 0)
 			goto out;
 	}
 	result = sscanf(buf, "%u", &sub);
 	if (sub <= max_sub)
-		wlp->dev_info->prim_dev_type.subID = sub;
+		wlp->wdi->prim_dev_type.subID = sub;
 	else
 		result = -EINVAL;
 out:
diff --git a/drivers/uwb/wlp/wlp-lc.c b/drivers/uwb/wlp/wlp-lc.c
index 13db739..530613e 100644
--- a/drivers/uwb/wlp/wlp-lc.c
+++ b/drivers/uwb/wlp/wlp-lc.c
@@ -39,9 +39,9 @@ void wlp_neighbor_init(struct wlp_neighbor_e *neighbor)
 int __wlp_alloc_device_info(struct wlp *wlp)
 {
 	struct device *dev = &wlp->rc->uwb_dev.dev;
-	BUG_ON(wlp->dev_info != NULL);
-	wlp->dev_info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL);
-	if (wlp->dev_info == NULL) {
+	BUG_ON(wlp->wdi != NULL);
+	wlp->wdi = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL);
+	if (wlp->wdi == NULL) {
 		dev_err(dev, "WLP: Unable to allocate memory for "
 			"device information.\n");
 		return -ENOMEM;
@@ -58,7 +58,7 @@ int __wlp_alloc_device_info(struct wlp *wlp)
 static
 void __wlp_fill_device_info(struct wlp *wlp)
 {
-	wlp->fill_device_info(wlp, wlp->dev_info);
+	wlp->fill_device_info(wlp, wlp->wdi);
 }
 
 /**
@@ -538,8 +538,8 @@ void wlp_remove(struct wlp *wlp)
 	uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
 	wlp_eda_release(&wlp->eda);
 	mutex_lock(&wlp->mutex);
-	if (wlp->dev_info != NULL)
-		kfree(wlp->dev_info);
+	if (wlp->wdi != NULL)
+		kfree(wlp->wdi);
 	mutex_unlock(&wlp->mutex);
 	wlp->rc = NULL;
 }
diff --git a/include/linux/wlp.h b/include/linux/wlp.h
index ac95ce6..e8e3ff2 100644
--- a/include/linux/wlp.h
+++ b/include/linux/wlp.h
@@ -655,7 +655,7 @@ struct wlp {
 	struct mutex nbmutex; /* Neighbor mutex protects neighbors list */
 	struct list_head neighbors; /* Elements are wlp_neighbor_e */
 	struct uwb_notifs_handler uwb_notifs_handler;
-	struct wlp_device_info *dev_info;
+	struct wlp_device_info *wdi;
 	void (*fill_device_info)(struct wlp *wlp, struct wlp_device_info *info);
 	int (*xmit_frame)(struct wlp *, struct sk_buff *,
 			  struct uwb_dev_addr *);



^ permalink raw reply related

* Re: [PATCH] rps: fixed missed rps_unlock
From: Changli Gao @ 2010-04-05 22:23 UTC (permalink / raw)
  To: Tom Herbert; +Cc: davem, netdev
In-Reply-To: <alpine.DEB.1.00.1004051426140.22393@pokey.mtv.corp.google.com>

On Tue, Apr 6, 2010 at 5:30 AM, Tom Herbert <therbert@google.com> wrote:
> Fix spin_unlock_irq which needs to be rps_unlock.
>
> Signed-off-by: Tom Herbert <therbert@google.com>
> ---
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 2a9b7dd..74f77ca 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -3120,7 +3120,7 @@ static int process_backlog(struct napi_struct *napi, int quota)
>                skb = __skb_dequeue(&queue->input_pkt_queue);
>                if (!skb) {
>                        __napi_complete(napi);
> -                       spin_unlock_irq(&queue->input_pkt_queue.lock);
> +                       rps_unlock(queue);
>                        break;
>                }
>                rps_unlock(queue);

It seems that irq isn't enabled when breaking the loop. Please add
   local_irq_enable();
after rps_unlock(queue);



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

^ permalink raw reply

* Re: [PATCH 11/11] drivers/uwb: Rename dev_info to wdi
From: David Miller @ 2010-04-05 21:51 UTC (permalink / raw)
  To: joe; +Cc: akpm, david.vrabel, netdev, linux-kernel
In-Reply-To: <1270503858.31062.43.camel@Joe-Laptop.home>

From: Joe Perches <joe@perches.com>
Date: Mon, 05 Apr 2010 14:44:18 -0700

> On Mon, 2010-04-05 at 12:05 -0700, Joe Perches wrote:
>> There is a macro called dev_info that prints struct device specific
>> information.  Having variables with the same name can be confusing and
>> prevents conversion of the macro to a function.
>> 
>> Rename the existing dev_info variables to something else in preparation
>> to converting the dev_info macro to a function.
> 
> http://patchwork.ozlabs.org/patch/49421/
> 
> This marked as RFC in patchwork.
> It's not intended to be.

Because I can't apply the entire set, I'd like someone else
to take this in since it's not really a networking specific
patch.

^ permalink raw reply

* Re: [PATCH 11/11] drivers/uwb: Rename dev_info to wdi
From: Joe Perches @ 2010-04-05 21:44 UTC (permalink / raw)
  To: Andrew Morton, David Miller; +Cc: David Vrabel, netdev, linux-kernel
In-Reply-To: <6bd4d4dacf32631b72c3827a3b133a26e2e8b889.1270493677.git.joe@perches.com>

On Mon, 2010-04-05 at 12:05 -0700, Joe Perches wrote:
> There is a macro called dev_info that prints struct device specific
> information.  Having variables with the same name can be confusing and
> prevents conversion of the macro to a function.
> 
> Rename the existing dev_info variables to something else in preparation
> to converting the dev_info macro to a function.

http://patchwork.ozlabs.org/patch/49421/

This marked as RFC in patchwork.
It's not intended to be.



^ permalink raw reply

* Re: [PATCH] rps: fixed missed rps_unlock
From: Tom Herbert @ 2010-04-05 21:40 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: davem, netdev
In-Reply-To: <1270503358.9013.38.camel@edumazet-laptop>

-
>
> Yes, and rps_lock()/rps_unlock() are not well chosen either, but no
> clever names come to my mind right now.
>
input_queue_lock/input_queue_unlock ?

> Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
>
>
>

^ permalink raw reply

* Re: [PATCH] rps: fixed missed rps_unlock
From: David Miller @ 2010-04-05 21:37 UTC (permalink / raw)
  To: therbert; +Cc: netdev
In-Reply-To: <alpine.DEB.1.00.1004051426140.22393@pokey.mtv.corp.google.com>

From: Tom Herbert <therbert@google.com>
Date: Mon, 5 Apr 2010 14:30:58 -0700 (PDT)

> Fix spin_unlock_irq which needs to be rps_unlock.
> 
> Signed-off-by: Tom Herbert <therbert@google.com>

Applied, thanks Tom.

^ permalink raw reply

* Re: [PATCH] rps: fixed missed rps_unlock
From: Eric Dumazet @ 2010-04-05 21:35 UTC (permalink / raw)
  To: Tom Herbert; +Cc: davem, netdev
In-Reply-To: <alpine.DEB.1.00.1004051426140.22393@pokey.mtv.corp.google.com>

Le lundi 05 avril 2010 à 14:30 -0700, Tom Herbert a écrit :
> Fix spin_unlock_irq which needs to be rps_unlock.
> 
> Signed-off-by: Tom Herbert <therbert@google.com>
> ---
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 2a9b7dd..74f77ca 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -3120,7 +3120,7 @@ static int process_backlog(struct napi_struct *napi, int quota)
>  		skb = __skb_dequeue(&queue->input_pkt_queue);
>  		if (!skb) {
>  			__napi_complete(napi);
> -			spin_unlock_irq(&queue->input_pkt_queue.lock);
> +			rps_unlock(queue);
>  			break;
>  		}
>  		rps_unlock(queue);
> --

Yes, and rps_lock()/rps_unlock() are not well chosen either, but no
clever names come to my mind right now.

Acked-by: Eric Dumazet <eric.dumazet@gmail.com>



^ permalink raw reply

* RE: [PATCH] [V3] Add non-Virtex5 support for LL TEMAC driver
From: John Linn @ 2010-04-05 21:33 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: netdev, linuxppc-dev, grant.likely, jwboyer, john.williams,
	michal.simek, John Tyner
In-Reply-To: <1270502993.9013.36.camel@edumazet-laptop>

> -----Original Message-----
> From: Eric Dumazet [mailto:eric.dumazet@gmail.com]
> Sent: Monday, April 05, 2010 3:30 PM
> To: John Linn
> Cc: netdev@vger.kernel.org; linuxppc-dev@ozlabs.org; grant.likely@secretlab.ca;
> jwboyer@linux.vnet.ibm.com; john.williams@petalogix.com; michal.simek@petalogix.com; John Tyner
> Subject: Re: [PATCH] [V3] Add non-Virtex5 support for LL TEMAC driver
> 
> Le lundi 05 avril 2010 à 15:11 -0600, John Linn a écrit :
> > This patch adds support for using the LL TEMAC Ethernet driver on
> > non-Virtex 5 platforms by adding support for accessing the Soft DMA
> > registers as if they were memory mapped instead of solely through the
> > DCR's (available on the Virtex 5).
> >
> > The patch also updates the driver so that it runs on the MicroBlaze.
> > The changes were tested on the PowerPC 440, PowerPC 405, and the
> > MicroBlaze platforms.
> >
> > Signed-off-by: John Tyner <jtyner@cs.ucr.edu>
> > Signed-off-by: John Linn <john.linn@xilinx.com>
> >
> > ---
> 
> > +/* Align the IP data in the packet on word boundaries as MicroBlaze
> > + * needs it.
> > + */
> > +
> >  #define XTE_ALIGN       32
> > -#define BUFFER_ALIGN(adr) ((XTE_ALIGN - ((u32) adr)) % XTE_ALIGN)
> > +#define BUFFER_ALIGN(adr) ((34 - ((u32) adr)) % XTE_ALIGN)
> >
> 
> Very interesting way of doing this, but why such convoluted thing ?

Grant might have insight into why this started this way, I just updated to help with MicroBlaze alignment.

> 
> Because of the % 32, this is equivalent to :
> 
> #define BUFFER_ALIGN(adr) ((2 - ((u32) adr)) % XTE_ALIGN)
> 
> But wait, dont we recognise the magic constant NET_IP_ALIGN ?
> 
> So, I ask, cant you use netdev_alloc_skb_ip_align() in this driver ?
> 
> 
Will have to look at it to better understand, maybe.

Thanks,
John


This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

^ permalink raw reply

* RE: [PATCH] [V2] Add non-Virtex5 support for LL TEMAC driver
From: John Linn @ 2010-04-05 21:28 UTC (permalink / raw)
  To: David Miller, grant.likely
  Cc: netdev, linuxppc-dev, jwboyer, john.williams, michal.simek,
	jtyner
In-Reply-To: <20100405.121647.91426186.davem@davemloft.net>

> -----Original Message-----
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Monday, April 05, 2010 1:17 PM
> To: grant.likely@secretlab.ca
> Cc: netdev@vger.kernel.org; linuxppc-dev@ozlabs.org;
jwboyer@linux.vnet.ibm.com;
> john.williams@petalogix.com; michal.simek@petalogix.com;
jtyner@cs.ucr.edu; John Linn
> Subject: Re: [PATCH] [V2] Add non-Virtex5 support for LL TEMAC driver
> 
> From: Grant Likely <grant.likely@secretlab.ca>
> Date: Mon, 5 Apr 2010 12:10:51 -0600
> 
> > David, are you going to pick up this patch, or would you like me to?
> 
> The submitter, when asked, stated that he couldn't even get
> the driver to build on microblaze against mainline.
> 
> So I marked the patch "changed requested" because being able
> to build is... you know... sort of a requirement for integration.

Pushed out V3 of the patch, forgot to copy you David.

Thanks,
John

This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.



^ permalink raw reply

* [PATCH] rps: fixed missed rps_unlock
From: Tom Herbert @ 2010-04-05 21:30 UTC (permalink / raw)
  To: davem, netdev

Fix spin_unlock_irq which needs to be rps_unlock.

Signed-off-by: Tom Herbert <therbert@google.com>
---
diff --git a/net/core/dev.c b/net/core/dev.c
index 2a9b7dd..74f77ca 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3120,7 +3120,7 @@ static int process_backlog(struct napi_struct *napi, int quota)
 		skb = __skb_dequeue(&queue->input_pkt_queue);
 		if (!skb) {
 			__napi_complete(napi);
-			spin_unlock_irq(&queue->input_pkt_queue.lock);
+			rps_unlock(queue);
 			break;
 		}
 		rps_unlock(queue);

^ permalink raw reply related

* Re: [PATCH] [V3] Add non-Virtex5 support for LL TEMAC driver
From: Eric Dumazet @ 2010-04-05 21:29 UTC (permalink / raw)
  To: John Linn
  Cc: netdev, linuxppc-dev, grant.likely, jwboyer, john.williams,
	michal.simek, John Tyner
In-Reply-To: <d9134316-bd07-46a8-91d4-c30f27baeb60@SG2EHSMHS007.ehs.local>

Le lundi 05 avril 2010 à 15:11 -0600, John Linn a écrit :
> This patch adds support for using the LL TEMAC Ethernet driver on
> non-Virtex 5 platforms by adding support for accessing the Soft DMA
> registers as if they were memory mapped instead of solely through the
> DCR's (available on the Virtex 5).
> 
> The patch also updates the driver so that it runs on the MicroBlaze.
> The changes were tested on the PowerPC 440, PowerPC 405, and the
> MicroBlaze platforms.
> 
> Signed-off-by: John Tyner <jtyner@cs.ucr.edu>
> Signed-off-by: John Linn <john.linn@xilinx.com>
> 
> ---

> +/* Align the IP data in the packet on word boundaries as MicroBlaze
> + * needs it.
> + */
> +
>  #define XTE_ALIGN       32
> -#define BUFFER_ALIGN(adr) ((XTE_ALIGN - ((u32) adr)) % XTE_ALIGN)
> +#define BUFFER_ALIGN(adr) ((34 - ((u32) adr)) % XTE_ALIGN)
>  

Very interesting way of doing this, but why such convoluted thing ?

Because of the % 32, this is equivalent to :

#define BUFFER_ALIGN(adr) ((2 - ((u32) adr)) % XTE_ALIGN)

But wait, dont we recognise the magic constant NET_IP_ALIGN ?

So, I ask, cant you use netdev_alloc_skb_ip_align() in this driver ?



^ permalink raw reply

* [PATCH] [V3] Add non-Virtex5 support for LL TEMAC driver
From: John Linn @ 2010-04-05 21:11 UTC (permalink / raw)
  To: netdev, linuxppc-dev, grant.likely, jwboyer
  Cc: john.williams, michal.simek, John Linn, John Tyner

This patch adds support for using the LL TEMAC Ethernet driver on
non-Virtex 5 platforms by adding support for accessing the Soft DMA
registers as if they were memory mapped instead of solely through the
DCR's (available on the Virtex 5).

The patch also updates the driver so that it runs on the MicroBlaze.
The changes were tested on the PowerPC 440, PowerPC 405, and the
MicroBlaze platforms.

Signed-off-by: John Tyner <jtyner@cs.ucr.edu>
Signed-off-by: John Linn <john.linn@xilinx.com>

---

V2 - Incorporated comments from Grant and added more logic to allow the driver
to work on MicroBlaze.

V3 - Only updated it to apply to head, minor change to include slab.h. Also
verified that it now builds for MicroBlaze. Retested on PowerPC and MicroBlaze.
---
 drivers/net/Kconfig         |    1 -
 drivers/net/ll_temac.h      |   17 +++++-
 drivers/net/ll_temac_main.c |  124 ++++++++++++++++++++++++++++++++++---------
 3 files changed, 113 insertions(+), 29 deletions(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 0ba5b8e..17044dc 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2435,7 +2435,6 @@ config MV643XX_ETH
 config XILINX_LL_TEMAC
 	tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
 	select PHYLIB
-	depends on PPC_DCR_NATIVE
 	help
 	  This driver supports the Xilinx 10/100/1000 LocalLink TEMAC
 	  core used in Xilinx Spartan and Virtex FPGAs
diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h
index 1af66a1..915aa34 100644
--- a/drivers/net/ll_temac.h
+++ b/drivers/net/ll_temac.h
@@ -5,8 +5,11 @@
 #include <linux/netdevice.h>
 #include <linux/of.h>
 #include <linux/spinlock.h>
+
+#ifdef CONFIG_PPC_DCR
 #include <asm/dcr.h>
 #include <asm/dcr-regs.h>
+#endif
 
 /* packet size info */
 #define XTE_HDR_SIZE			14      /* size of Ethernet header */
@@ -290,8 +293,12 @@ This option defaults to enabled (set) */
 
 #define TX_CONTROL_CALC_CSUM_MASK   1
 
+/* Align the IP data in the packet on word boundaries as MicroBlaze
+ * needs it.
+ */
+
 #define XTE_ALIGN       32
-#define BUFFER_ALIGN(adr) ((XTE_ALIGN - ((u32) adr)) % XTE_ALIGN)
+#define BUFFER_ALIGN(adr) ((34 - ((u32) adr)) % XTE_ALIGN)
 
 #define MULTICAST_CAM_TABLE_NUM 4
 
@@ -335,9 +342,15 @@ struct temac_local {
 	struct mii_bus *mii_bus;	/* MII bus reference */
 	int mdio_irqs[PHY_MAX_ADDR];	/* IRQs table for MDIO bus */
 
-	/* IO registers and IRQs */
+	/* IO registers, dma functions and IRQs */
 	void __iomem *regs;
+	void __iomem *sdma_regs;
+#ifdef CONFIG_PPC_DCR
 	dcr_host_t sdma_dcrs;
+#endif
+	u32 (*dma_in)(struct temac_local *, int);
+	void (*dma_out)(struct temac_local *, int, u32);
+
 	int tx_irq;
 	int rx_irq;
 	int emac_num;
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index ba617e3..801b076 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -20,9 +20,6 @@
  *   or rx, so this should be okay.
  *
  * TODO:
- * - Fix driver to work on more than just Virtex5.  Right now the driver
- *   assumes that the locallink DMA registers are accessed via DCR
- *   instructions.
  * - Factor out locallink DMA code into separate driver
  * - Fix multicast assignment.
  * - Fix support for hardware checksumming.
@@ -116,17 +113,86 @@ void temac_indirect_out32(struct temac_local *lp, int reg, u32 value)
 	temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg);
 }
 
+/**
+ * temac_dma_in32 - Memory mapped DMA read, this function expects a
+ * register input that is based on DCR word addresses which
+ * are then converted to memory mapped byte addresses
+ */
 static u32 temac_dma_in32(struct temac_local *lp, int reg)
 {
-	return dcr_read(lp->sdma_dcrs, reg);
+	return in_be32((u32 *)(lp->sdma_regs + (reg << 2)));
 }
 
+/**
+ * temac_dma_out32 - Memory mapped DMA read, this function expects a
+ * register input that is based on DCR word addresses which
+ * are then converted to memory mapped byte addresses
+ */
 static void temac_dma_out32(struct temac_local *lp, int reg, u32 value)
 {
+	out_be32((u32 *)(lp->sdma_regs + (reg << 2)), value);
+}
+
+/* DMA register access functions can be DCR based or memory mapped.
+ * The PowerPC 440 is DCR based, the PowerPC 405 and MicroBlaze are both
+ * memory mapped.
+ */
+#ifdef CONFIG_PPC_DCR
+
+/**
+ * temac_dma_dcr_in32 - DCR based DMA read
+ */
+static u32 temac_dma_dcr_in(struct temac_local *lp, int reg)
+{
+	return dcr_read(lp->sdma_dcrs, reg);
+}
+
+/**
+ * temac_dma_dcr_out32 - DCR based DMA write
+ */
+static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value)
+{
 	dcr_write(lp->sdma_dcrs, reg, value);
 }
 
 /**
+ * temac_dcr_setup - If the DMA is DCR based, then setup the address and
+ * I/O  functions
+ */
+static int temac_dcr_setup(struct temac_local *lp, struct of_device *op,
+				struct device_node *np)
+{
+	unsigned int dcrs;
+
+	/* setup the dcr address mapping if it's in the device tree */
+
+	dcrs = dcr_resource_start(np, 0);
+	if (dcrs != 0) {
+		lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
+		lp->dma_in = temac_dma_dcr_in;
+		lp->dma_out = temac_dma_dcr_out;
+		dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
+		return 0;
+	}
+	/* no DCR in the device tree, indicate a failure */
+	return -1;
+}
+
+#else
+
+/*
+ * temac_dcr_setup - This is a stub for when DCR is not supported,
+ * such as with MicroBlaze
+ */
+static int temac_dcr_setup(struct temac_local *lp, struct of_device *op,
+				struct device_node *np)
+{
+	return -1;
+}
+
+#endif
+
+/**
  * temac_dma_bd_init - Setup buffer descriptor rings
  */
 static int temac_dma_bd_init(struct net_device *ndev)
@@ -173,23 +239,23 @@ static int temac_dma_bd_init(struct net_device *ndev)
 		lp->rx_bd_v[i].app0 = STS_CTRL_APP0_IRQONEND;
 	}
 
-	temac_dma_out32(lp, TX_CHNL_CTRL, 0x10220400 |
+	lp->dma_out(lp, TX_CHNL_CTRL, 0x10220400 |
 					  CHNL_CTRL_IRQ_EN |
 					  CHNL_CTRL_IRQ_DLY_EN |
 					  CHNL_CTRL_IRQ_COAL_EN);
 	/* 0x10220483 */
 	/* 0x00100483 */
-	temac_dma_out32(lp, RX_CHNL_CTRL, 0xff010000 |
+	lp->dma_out(lp, RX_CHNL_CTRL, 0xff010000 |
 					  CHNL_CTRL_IRQ_EN |
 					  CHNL_CTRL_IRQ_DLY_EN |
 					  CHNL_CTRL_IRQ_COAL_EN |
 					  CHNL_CTRL_IRQ_IOE);
 	/* 0xff010283 */
 
-	temac_dma_out32(lp, RX_CURDESC_PTR,  lp->rx_bd_p);
-	temac_dma_out32(lp, RX_TAILDESC_PTR,
+	lp->dma_out(lp, RX_CURDESC_PTR,  lp->rx_bd_p);
+	lp->dma_out(lp, RX_TAILDESC_PTR,
 		       lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
-	temac_dma_out32(lp, TX_CURDESC_PTR, lp->tx_bd_p);
+	lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p);
 
 	return 0;
 }
@@ -427,9 +493,9 @@ static void temac_device_reset(struct net_device *ndev)
 	temac_indirect_out32(lp, XTE_RXC1_OFFSET, val & ~XTE_RXC1_RXEN_MASK);
 
 	/* Reset Local Link (DMA) */
-	temac_dma_out32(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
+	lp->dma_out(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
 	timeout = 1000;
-	while (temac_dma_in32(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) {
+	while (lp->dma_in(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) {
 		udelay(1);
 		if (--timeout == 0) {
 			dev_err(&ndev->dev,
@@ -437,7 +503,7 @@ static void temac_device_reset(struct net_device *ndev)
 			break;
 		}
 	}
-	temac_dma_out32(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE);
+	lp->dma_out(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE);
 
 	temac_dma_bd_init(ndev);
 
@@ -598,7 +664,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 		lp->tx_bd_tail = 0;
 
 	/* Kick off the transfer */
-	temac_dma_out32(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
+	lp->dma_out(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
 
 	return NETDEV_TX_OK;
 }
@@ -664,7 +730,7 @@ static void ll_temac_recv(struct net_device *ndev)
 		cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
 		bdstat = cur_p->app0;
 	}
-	temac_dma_out32(lp, RX_TAILDESC_PTR, tail_p);
+	lp->dma_out(lp, RX_TAILDESC_PTR, tail_p);
 
 	spin_unlock_irqrestore(&lp->rx_lock, flags);
 }
@@ -675,8 +741,8 @@ static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev)
 	struct temac_local *lp = netdev_priv(ndev);
 	unsigned int status;
 
-	status = temac_dma_in32(lp, TX_IRQ_REG);
-	temac_dma_out32(lp, TX_IRQ_REG, status);
+	status = lp->dma_in(lp, TX_IRQ_REG);
+	lp->dma_out(lp, TX_IRQ_REG, status);
 
 	if (status & (IRQ_COAL | IRQ_DLY))
 		temac_start_xmit_done(lp->ndev);
@@ -693,8 +759,8 @@ static irqreturn_t ll_temac_rx_irq(int irq, void *_ndev)
 	unsigned int status;
 
 	/* Read and clear the status registers */
-	status = temac_dma_in32(lp, RX_IRQ_REG);
-	temac_dma_out32(lp, RX_IRQ_REG, status);
+	status = lp->dma_in(lp, RX_IRQ_REG);
+	lp->dma_out(lp, RX_IRQ_REG, status);
 
 	if (status & (IRQ_COAL | IRQ_DLY))
 		ll_temac_recv(lp->ndev);
@@ -795,7 +861,7 @@ static ssize_t temac_show_llink_regs(struct device *dev,
 	int i, len = 0;
 
 	for (i = 0; i < 0x11; i++)
-		len += sprintf(buf + len, "%.8x%s", temac_dma_in32(lp, i),
+		len += sprintf(buf + len, "%.8x%s", lp->dma_in(lp, i),
 			       (i % 8) == 7 ? "\n" : " ");
 	len += sprintf(buf + len, "\n");
 
@@ -821,7 +887,6 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
 	struct net_device *ndev;
 	const void *addr;
 	int size, rc = 0;
-	unsigned int dcrs;
 
 	/* Init network device structure */
 	ndev = alloc_etherdev(sizeof(*lp));
@@ -871,13 +936,20 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
 		goto nodev;
 	}
 
-	dcrs = dcr_resource_start(np, 0);
-	if (dcrs == 0) {
-		dev_err(&op->dev, "could not get DMA register address\n");
-		goto nodev;
+	/* Setup the DMA register accesses, could be DCR or memory mapped */
+	if (temac_dcr_setup(lp, op, np)) {
+
+		/* no DCR in the device tree, try non-DCR */
+		lp->sdma_regs = of_iomap(np, 0);
+		if (lp->sdma_regs) {
+			lp->dma_in = temac_dma_in32;
+			lp->dma_out = temac_dma_out32;
+			dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs);
+		} else {
+			dev_err(&op->dev, "unable to map DMA registers\n");
+			goto nodev;
+		}
 	}
-	lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
-	dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
 
 	lp->rx_irq = irq_of_parse_and_map(np, 0);
 	lp->tx_irq = irq_of_parse_and_map(np, 1);
-- 
1.6.2.1



This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.



^ permalink raw reply related


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