Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next] net: struct sock cleanups
From: David Miller @ 2012-06-25 23:09 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <1340605369.10893.3.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 25 Jun 2012 08:22:49 +0200

> From: Eric Dumazet <edumazet@google.com>
> 
> Add missing kernel doc for sk_rx_dst
> 
> Move sk_rx_dst to avoid two 32bit holes on 64bit arches
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Applied, thanks Eric.

^ permalink raw reply

* Re: [PATCH net-next 0/2] be2net fixes
From: David Miller @ 2012-06-25 23:10 UTC (permalink / raw)
  To: somnath.kotur; +Cc: netdev
In-Reply-To: <a5b0dbf3-1d39-41a2-9723-b28abd578852@exht1.ad.emulex.com>

From: Somnath Kotur <somnath.kotur@emulex.com>
Date: Mon, 25 Jun 2012 11:08:12 +0530

> Pls apply.
> 
> Somnath Kotur (2):
>   be2net: Explicitly clear the reserved field in the Tx Descriptor
>   be2net: Regression bug wherein VFs creation broken for multiple
>     cards.

Applied, thanks.

^ permalink raw reply

* Re: [PATCH 1/4] netdev/phy: Handle IEEE802.3 clause 45 Ethernet PHYs
From: David Daney @ 2012-06-25 23:11 UTC (permalink / raw)
  To: David Miller
  Cc: grant.likely, rob.herring, devicetree-discuss, netdev,
	linux-kernel, linux-mips, afleming, david.daney
In-Reply-To: <20120625.153440.17010814246237639.davem@davemloft.net>

On 06/25/2012 03:34 PM, David Miller wrote:
> From: David Daney<ddaney.cavm@gmail.com>
> Date: Fri, 22 Jun 2012 17:24:13 -0700
>
>> From: David Daney<david.daney@cavium.com>
>>
>> The IEEE802.3 clause 45 MDIO bus protocol allows for directly
>> addressing PHY registers using a 21 bit address, and is used by many
>> 10G Ethernet PHYS.  Already existing is the ability of MDIO bus
>> drivers to use clause 45, with the MII_ADDR_C45 flag.  Here we add
>> struct phy_c45_device_ids to hold the device identifier registers
>> present in clause 45. struct phy_device gets a couple of new fields:
>> c45_ids to hold the identifiers and is_c45 to signal that it is clause
>> 45.
>>
>> Normally the MII_ADDR_C45 flag is ORed with the register address to
>> indicate a clause 45 transaction.  Here we also use this flag in the
>> *device* address passed to get_phy_device() to indicate that probing
>> should be done with clause 45 transactions.
>>
>> EXPORT phy_device_create() so that the follow-on patch to of_mdio.c
>> can use it to create phy devices for PHYs, that have non-standard
>> device identifier registers, based on the device tree bindings.
>>
>> Signed-off-by: David Daney<david.daney@cavium.com>
>
> I see no value in having two ways to say that clause-45 transactions
> should be used.
>
> Either make it a PHY device attribute, or specify it in the address
> in the register accesses, but not both.
>

Do you realize that at the time get_phy_device() is called, there is no 
PHY device?  So there can be no attribute, nor are we passing a register 
address.  Neither of these suggestions apply to this situation.

We need to know a priori if it is c22 or c45.  So we need to communicate 
the type somehow to get_phy_device().  I chose an unused bit in the addr 
parameter to do this, another option would be to add a separate 
parameter to get_phy_device() specifying the type.



> Also your patch is full of coding style errors, I simply couldn't
> stomache applying this even if I agreed with the substance of the
> changes:
>
>> +	     i<  ARRAY_SIZE(c45_ids->device_ids)&&
>> +		     c45_ids->devices_in_package == 0;
>
> c45_ids on the second line should line up with the initial 'i'
> on the first line.
>
>> +		c45_ids->devices_in_package = (phy_reg&  0xffff)<<  16;
>> +
>> +
>> +		reg_addr = MII_ADDR_C45 | i<<  16 | 5;
>
> There is not reason in the world to have two empty lines there, it
> looks awful.

OK, I will fix those...

>
>> +		/*
>> +		 * If mostly Fs, there is no device there,
>> +		 * let's get out of here.
>> +		 */
>
> Format comments:
>
> 	/* Like
> 	 * this.
> 	 */
>
> Not.
>
> 	/*
> 	 * Like
> 	 * this.
> 	 */

... and this one too I guess.  Really you and Linus should come to a 
consensus on this one.

[...]
>
>> +/*
>> + * phy_c45_device_ids: 802.3-c45 Device Identifiers
>> + *
>> + * devices_in_package: Bit vector of devices present.
>> + * device_ids: The device identifer for each present device.
>> + */
>
> If you're going to list the struct members use the correct kerneldoc
> format to do so.

OK.

David Daney

^ permalink raw reply

* Re: pull request: batman-adv 2012-06-25
From: David Miller @ 2012-06-25 23:19 UTC (permalink / raw)
  To: ordex-GaUfNO9RBHfsrOwW+9ziJQ
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r
In-Reply-To: <1340607284-29950-1-git-send-email-ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>

From: Antonio Quartulli <ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>
Date: Mon, 25 Jun 2012 08:54:24 +0200

> this is another set of changes intended for net-next/linux-3.6.
> 
> This patchset is entirely composed by "namespace renaming" patches.
> 
> Please, let me know if there is any problem.

Pulled, but you really, _REALLY_, should have let me pull 'net'
into 'net-next' to resolve the conflicts in translation-table.c
before sending this work to me.

I did that merge before getting to this pull request and did my
best merging things together.

But I know I made mistakes, so please send me whatever fixups
are necessary.

Thanks.

^ permalink raw reply

* Re: [PATCH 1/1] ipheth: add support for iPad
From: David Miller @ 2012-06-25 23:21 UTC (permalink / raw)
  To: rainbow; +Cc: gregkh, linux-usb, netdev, linux-kernel
In-Reply-To: <1340607887-28648-1-git-send-email-rainbow@irh.it>

From: Davide Gerhard <rainbow@irh.it>
Date: Mon, 25 Jun 2012 09:04:47 +0200

> This adds support for the iPad to the ipheth driver.
> (product id = 0x129a)
> 
> Signed-off-by: Davide Gerhard <rainbow@irh.it>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH] net/ipv6/route.c: packets originating on device match lo
From: David Miller @ 2012-06-25 23:28 UTC (permalink / raw)
  To: david_mccullough; +Cc: netdev
In-Reply-To: <20120625065030.GA28914@mcafee.com>

From: David McCullough <david_mccullough@mcafee.com>
Date: Mon, 25 Jun 2012 16:50:30 +1000

> @@ -931,6 +931,9 @@ struct dst_entry * ip6_route_output(stru
>  {
>  	int flags = 0;
>  
> +	if (fl6->flowi6_iif == 0)
> +		fl6->flowi6_iif = net->loopback_dev->ifindex;
> +		

Like ipv4, you should make this assignment unconditionally.

Thanks.

^ permalink raw reply

* Re: [PATCH net V1 0/3] net/mlx4: Bug fixes for the mlx4_en driver
From: David Miller @ 2012-06-25 23:30 UTC (permalink / raw)
  To: yevgenyp; +Cc: netdev
In-Reply-To: <1340619853-29804-1-git-send-email-yevgenyp@mellanox.co.il>

From: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
Date: Mon, 25 Jun 2012 13:24:10 +0300

> This is a set of 3 bug fixes generated agains net tree:
> 
> ---
> Diff from V1:
> Removed atomic counter patch for rework.
> 
> Yevgeny Petrilin (3):
> 	net/mlx4_en: Set correct port parameters during device initialization
> 	net/mlx4: Use single completion vector after NOP failure
> 	net/mlx4_en: Release QP range in free_resources

All applied, thanks.

^ permalink raw reply

* Re: [PATCH] net: l2tp_eth: fix l2tp_eth_dev_xmit race
From: David Miller @ 2012-06-25 23:31 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, jchapman
In-Reply-To: <1340621114.10893.29.camel@edumazet-glaptop>

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

> From: Eric Dumazet <edumazet@google.com>
> 
> Its illegal to dereference skb after giving it to l2tp_xmit_skb()
> as it might be already freed/reused.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: James Chapman <jchapman@katalix.com>

Applied, thanks Eric.

^ permalink raw reply

* Re: [PATCH 1/4] netdev/phy: Handle IEEE802.3 clause 45 Ethernet PHYs
From: David Miller @ 2012-06-25 23:33 UTC (permalink / raw)
  To: ddaney.cavm
  Cc: grant.likely, rob.herring, devicetree-discuss, netdev,
	linux-kernel, linux-mips, afleming, david.daney
In-Reply-To: <4FE8F01B.2020207@gmail.com>

From: David Daney <ddaney.cavm@gmail.com>
Date: Mon, 25 Jun 2012 16:11:23 -0700

> Do you realize that at the time get_phy_device() is called, there is
> no PHY device?  So there can be no attribute, nor are we passing a
> register address.  Neither of these suggestions apply to this
> situation.
> 
> We need to know a priori if it is c22 or c45.  So we need to
> communicate the type somehow to get_phy_device().  I chose an unused
> bit in the addr parameter to do this, another option would be to add a
> separate parameter to get_phy_device() specifying the type.

Then pass it in to the get() routine and store the attribute there
in the device we end up with.

There are many parameters that go into a PHY register access, so
we'll probably some day end up with a descriptor struct that the
caller prepares on-stack to pass into the actual read/write ops
via reference.

> ... and this one too I guess.  Really you and Linus should come to a
> consensus on this one.

We did come up with a consensus, which is that subsystem maintainers
such as myself are at liberty to enforce localized coding style for
the bodies of code they maintain.

^ permalink raw reply

* Re: [PATCH fix] mac802154: add missed braces
From: David Miller @ 2012-06-25 23:35 UTC (permalink / raw)
  To: alex.bluesman.smirnov; +Cc: netdev
In-Reply-To: <1340631013-27556-1-git-send-email-alex.bluesman.smirnov@gmail.com>

From: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
Date: Mon, 25 Jun 2012 17:30:13 +0400

> Add missed braces after 'if' operator.
> 
> Signed-off-by: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH 1/7] mac802154: add wpan device-class support
From: David Miller @ 2012-06-25 23:37 UTC (permalink / raw)
  To: alex.bluesman.smirnov; +Cc: netdev, dbaryshkov
In-Reply-To: <1340631197-27691-2-git-send-email-alex.bluesman.smirnov@gmail.com>

From: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
Date: Mon, 25 Jun 2012 17:33:11 +0400

> +	list_for_each_entry_rcu(sdata, &priv->slaves, list)
> +	{
> +		if (sdata->type != IEEE802154_DEV_WPAN)
> +			continue;
> +
> +		sskb = skb_clone(skb, GFP_ATOMIC);
> +		if (sskb)
> +			mac802154_subif_frame(sdata, sskb);
> +	}

This is not the correct way to place braces.  It should be:

	x() {
	...
	}

not:

	x()
	{
	}

^ permalink raw reply

* Re: [PATCH 0/7] mac802154: basic wpan class-device support
From: David Miller @ 2012-06-25 23:39 UTC (permalink / raw)
  To: alex.bluesman.smirnov; +Cc: netdev, dbaryshkov
In-Reply-To: <1340631197-27691-1-git-send-email-alex.bluesman.smirnov@gmail.com>


Please fix the coding style problems in patch #1 and resubmit this
series.

Thanks.

^ permalink raw reply

* Re: [net-next 00/11] caif patch-set for net-next
From: David Miller @ 2012-06-25 23:44 UTC (permalink / raw)
  To: sjur.brandeland; +Cc: netdev, sjurbren
In-Reply-To: <1340646583-21059-1-git-send-email-sjur.brandeland@stericsson.com>

From: sjur.brandeland@stericsson.com
Date: Mon, 25 Jun 2012 19:49:32 +0200

> From: Sjur Brændeland <sjur.brandeland@stericsson.com>
> 
> The first 8 patches are fixes,
> there are a couple of fixes for issues found by static code analysis (coverity),
> and some other misc cleanups/fixes.
> 
> The three last patches introduces rtnl for managing
> the HSI interface and removes the use of module parameters.

All applied, thanks.

^ permalink raw reply

* Re: [PATCH 0/3 v3 resend] 6lowpan: minor fixes
From: David Miller @ 2012-06-25 23:45 UTC (permalink / raw)
  To: alex.bluesman.smirnov; +Cc: netdev, dbaryshkov
In-Reply-To: <1340632143-27794-1-git-send-email-alex.bluesman.smirnov@gmail.com>

From: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
Date: Mon, 25 Jun 2012 17:49:00 +0400

> I sent this set several weeks ago and seems that it was missed
> (or please let me know if there was a reason).
> 
> this is the 3-rd version of the patches.
> Changes since v2:
>  - Removed WARN_ON() and BUG() from skb fetch methods. That wasn't a good idea
>    to crash kernel by such an unsignificant issue.
>  - Added new patch (I've decided to add it here just to keep all the 6lowpan
>    related code together)

All applied, thanks.

^ permalink raw reply

* Re: [PATCH 1/4] netdev/phy: Handle IEEE802.3 clause 45 Ethernet PHYs
From: David Daney @ 2012-06-25 23:48 UTC (permalink / raw)
  To: David Miller
  Cc: ddaney.cavm, grant.likely, rob.herring, devicetree-discuss,
	netdev, linux-kernel, linux-mips, afleming, david.daney
In-Reply-To: <20120625.163355.2058784474741116830.davem@davemloft.net>

On 06/25/2012 04:33 PM, David Miller wrote:
> From: David Daney<ddaney.cavm@gmail.com>
> Date: Mon, 25 Jun 2012 16:11:23 -0700
>
>> Do you realize that at the time get_phy_device() is called, there is
>> no PHY device?  So there can be no attribute, nor are we passing a
>> register address.  Neither of these suggestions apply to this
>> situation.
>>
>> We need to know a priori if it is c22 or c45.  So we need to
>> communicate the type somehow to get_phy_device().  I chose an unused
>> bit in the addr parameter to do this, another option would be to add a
>> separate parameter to get_phy_device() specifying the type.
>
> Then pass it in to the get() routine and store the attribute there
> in the device we end up with.

OK.

addr has only 5 significant bits, and the patch *does* pass the 
information (c22 vs. c45) in one of the high order bits.  So it is 
essentially as you say, but you don't like the idea of multiplexing the 
arguments into a single int.

Therefore, I am going to propose that we add a 'flags' parameter to 
get_phy_device() and change the (two) callers.

Does that seem better (or at least acceptable)?

Or do you really want to pass the address of a (one bit) structure instead?

David Daney

>
> There are many parameters that go into a PHY register access, so
> we'll probably some day end up with a descriptor struct that the
> caller prepares on-stack to pass into the actual read/write ops
> via reference.
>

^ permalink raw reply

* Re: [PATCH 1/4] netdev/phy: Handle IEEE802.3 clause 45 Ethernet PHYs
From: David Miller @ 2012-06-25 23:50 UTC (permalink / raw)
  To: ddaney.cavm
  Cc: grant.likely, rob.herring, devicetree-discuss, netdev,
	linux-kernel, linux-mips, afleming, david.daney
In-Reply-To: <4FE8F8D8.1050009@gmail.com>

From: David Daney <ddaney.cavm@gmail.com>
Date: Mon, 25 Jun 2012 16:48:40 -0700

> Therefore, I am going to propose that we add a 'flags' parameter to
> get_phy_device() and change the (two) callers.

Since there is only one flag, make it simply a bool for now.

^ permalink raw reply

* Re: [PATCH] net/ipv6/route.c: packets originating on device match lo
From: David McCullough @ 2012-06-26  1:38 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20120625.162832.804773711822642700.davem@davemloft.net>


Jivin David Miller lays it down ...
> From: David McCullough <david_mccullough@mcafee.com>
> Date: Mon, 25 Jun 2012 16:50:30 +1000
> 
> > @@ -931,6 +931,9 @@ struct dst_entry * ip6_route_output(stru
> >  {
> >  	int flags = 0;
> >  
> > +	if (fl6->flowi6_iif == 0)
> > +		fl6->flowi6_iif = net->loopback_dev->ifindex;
> > +		
> 
> Like ipv4, you should make this assignment unconditionally.

No problems, will resend,  I wasn't so sure that I could do that safely
with the flowi getting passed into IPv6 rather than created as it is in
IPv4.  Did some extra testing,  looks good so patch to follow,

Thanks,
Davidm

-- 
David McCullough,      david_mccullough@mcafee.com,  Ph:+61 734352815
McAfee - SnapGear      http://www.mcafee.com         http://www.uCdot.org

^ permalink raw reply

* [PATCH v2] net/ipv6/route.c: packets originating on device match lo
From: David McCullough @ 2012-06-26  1:42 UTC (permalink / raw)
  To: netdev; +Cc: David Miller


Hi all,

Fix to allow IPv6 packets originating locally to match rules with the "iff"
set to "lo".  This allows IPv6 rule matching work the same as it does for
IPv4.  From the iproute2 man page:

   iif NAME
		  select  the incoming device to match.  If the interface is loop‐
		  back, the rule only matches packets originating from this  host.
		  This  means that you may create separate routing tables for for‐
		  warded and local packets and, hence, completely segregate them.

Cheers,
Davidm

Signed-off-by: David McCullough <david_mccullough@mcafee.com>

diff -u -p -r1.1.1.59 route.c
--- linux-3.4/net/ipv6/route.c	21 May 2012 23:15:01 -0000	1.1.1.59
+++ linux-3.4/net/ipv6/route.c	26 Jun 2012 01:41:15 -0000
@@ -931,6 +931,8 @@ struct dst_entry * ip6_route_output(stru
 {
 	int flags = 0;
 
+	fl6->flowi6_iif = net->loopback_dev->ifindex;
+
 	if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr))
 		flags |= RT6_LOOKUP_F_IFACE;
 
 
-- 
David McCullough,      david_mccullough@mcafee.com,  Ph:+61 734352815
McAfee - SnapGear      http://www.mcafee.com         http://www.uCdot.org

^ permalink raw reply

* linux-next: manual merge of the net-next tree with the net tree
From: Stephen Rothwell @ 2012-06-26  3:15 UTC (permalink / raw)
  To: David Miller, netdev
  Cc: linux-next, linux-kernel, Per Ellefsen,
	"Sjur Brændeland", Kim Lilliestierna

[-- Attachment #1: Type: text/plain, Size: 988 bytes --]

Hi all,

Today's linux-next merge of the net-next tree got a conflict in
drivers/net/caif/caif_hsi.c between commits 3935600a7f34 ("caif-hsi:
Bugfix - Piggyback'ed embedded CAIF frame lost") and 1fdc7630b2cb
("caif-hsi: Add missing return in error path") from the net tree and
commits 4e7bb59d49fb ("caif-hsi: Removed dead code") and c41254006377
("caif-hsi: Add rtnl support") from the net-next tree.

I fixed them up (see below) and can carry the fix as necessary.
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --cc drivers/net/caif/caif_hsi.c
index 4a27adb,1c2bd01..0000000
--- a/drivers/net/caif/caif_hsi.c
+++ b/drivers/net/caif/caif_hsi.c
@@@ -693,8 -678,8 +678,6 @@@ static void cfhsi_rx_done(struct cfhsi 
  			 */
  			memcpy(rx_buf, (u8 *)piggy_desc,
  					CFHSI_DESC_SHORT_SZ);
- 			if (desc_pld_len == -EPROTO)
- 				goto out_of_sync;
 -			/* Mark no embedded frame here */
 -			piggy_desc->offset = 0;
  		}
  	}
  

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH v2] net/sh-eth: Add support selecting MII function for SH7734 and R8A7740
From: Nobuhiro Iwamatsu @ 2012-06-26  3:32 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20120612.002954.1384327664115800772.davem@davemloft.net>

David Miller さんは書きました:
> From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
> Date: Tue, 12 Jun 2012 16:29:02 +0900
> 
>> @@ -492,6 +513,7 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
>>  	.no_trimd	= 1,
>>  	.no_ade		= 1,
>>  	.tsu		= 1,
>> +	.select_mii = 1,
>>  };
>>  
> 
> Indent this new line consistently with those around it.
> 
Thank you. I will fix and resend.

Best regards,
   Nobuhiro

^ permalink raw reply

* [PATCH v3] net/sh-eth: Add support selecting MII function for SH7734 and R8A7740
From: Nobuhiro Iwamatsu @ 2012-06-26  3:34 UTC (permalink / raw)
  To: netdev; +Cc: Nobuhiro Iwamatsu

Ethernet IP of SH7734 and R8A7740 has selecting MII register.
The user needs to change a value according to MII to be used.
This adds the function to change the value of this register.

Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
---
 V2: Fix indent.
 V2: Fix the check by select_mii.
 drivers/net/ethernet/renesas/sh_eth.c |  108 ++++++++++++++++++++-------------
 drivers/net/ethernet/renesas/sh_eth.h |    1 +
 2 files changed, 66 insertions(+), 43 deletions(-)

diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 79bf09b..8d696e0 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -49,6 +49,34 @@
 		NETIF_MSG_RX_ERR| \
 		NETIF_MSG_TX_ERR)
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7734) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7763) || \
+	defined(CONFIG_ARCH_R8A7740)
+static void sh_eth_select_mii(struct net_device *ndev)
+{
+	u32 value = 0x0;
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
+	switch (mdp->phy_interface) {
+	case PHY_INTERFACE_MODE_GMII:
+		value = 0x2;
+		break;
+	case PHY_INTERFACE_MODE_MII:
+		value = 0x1;
+		break;
+	case PHY_INTERFACE_MODE_RMII:
+		value = 0x0;
+		break;
+	default:
+		pr_warn("PHY interface mode was not setup. Set to MII.\n");
+		value = 0x1;
+		break;
+	}
+
+	sh_eth_write(ndev, value, RMII_MII);
+}
+#endif
+
 /* There is CPU dependent code */
 #if defined(CONFIG_CPU_SUBTYPE_SH7724)
 #define SH_ETH_RESET_DEFAULT	1
@@ -283,6 +311,7 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
 #define SH_ETH_HAS_TSU	1
 static void sh_eth_reset_hw_crc(struct net_device *ndev);
+
 static void sh_eth_chip_reset(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
@@ -292,35 +321,6 @@ static void sh_eth_chip_reset(struct net_device *ndev)
 	mdelay(1);
 }
 
-static void sh_eth_reset(struct net_device *ndev)
-{
-	int cnt = 100;
-
-	sh_eth_write(ndev, EDSR_ENALL, EDSR);
-	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
-	while (cnt > 0) {
-		if (!(sh_eth_read(ndev, EDMR) & 0x3))
-			break;
-		mdelay(1);
-		cnt--;
-	}
-	if (cnt == 0)
-		printk(KERN_ERR "Device reset fail\n");
-
-	/* Table Init */
-	sh_eth_write(ndev, 0x0, TDLAR);
-	sh_eth_write(ndev, 0x0, TDFAR);
-	sh_eth_write(ndev, 0x0, TDFXR);
-	sh_eth_write(ndev, 0x0, TDFFR);
-	sh_eth_write(ndev, 0x0, RDLAR);
-	sh_eth_write(ndev, 0x0, RDFAR);
-	sh_eth_write(ndev, 0x0, RDFXR);
-	sh_eth_write(ndev, 0x0, RDFFR);
-
-	/* Reset HW CRC register */
-	sh_eth_reset_hw_crc(ndev);
-}
-
 static void sh_eth_set_duplex(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
@@ -377,9 +377,43 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
 	.tsu		= 1,
 #if defined(CONFIG_CPU_SUBTYPE_SH7734)
 	.hw_crc     = 1,
+	.select_mii = 1,
 #endif
 };
 
+static void sh_eth_reset(struct net_device *ndev)
+{
+	int cnt = 100;
+
+	sh_eth_write(ndev, EDSR_ENALL, EDSR);
+	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
+	while (cnt > 0) {
+		if (!(sh_eth_read(ndev, EDMR) & 0x3))
+			break;
+		mdelay(1);
+		cnt--;
+	}
+	if (cnt == 0)
+		printk(KERN_ERR "Device reset fail\n");
+
+	/* Table Init */
+	sh_eth_write(ndev, 0x0, TDLAR);
+	sh_eth_write(ndev, 0x0, TDFAR);
+	sh_eth_write(ndev, 0x0, TDFXR);
+	sh_eth_write(ndev, 0x0, TDFFR);
+	sh_eth_write(ndev, 0x0, RDLAR);
+	sh_eth_write(ndev, 0x0, RDFAR);
+	sh_eth_write(ndev, 0x0, RDFXR);
+	sh_eth_write(ndev, 0x0, RDFFR);
+
+	/* Reset HW CRC register */
+	sh_eth_reset_hw_crc(ndev);
+
+	/* Select MII mode */
+	if (sh_eth_my_cpu_data.select_mii)
+		sh_eth_select_mii(ndev);
+}
+
 static void sh_eth_reset_hw_crc(struct net_device *ndev)
 {
 	if (sh_eth_my_cpu_data.hw_crc)
@@ -391,25 +425,12 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev)
 static void sh_eth_chip_reset(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	unsigned long mii;
 
 	/* reset device */
 	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
 	mdelay(1);
 
-	switch (mdp->phy_interface) {
-	case PHY_INTERFACE_MODE_GMII:
-		mii = 2;
-		break;
-	case PHY_INTERFACE_MODE_MII:
-		mii = 1;
-		break;
-	case PHY_INTERFACE_MODE_RMII:
-	default:
-		mii = 0;
-		break;
-	}
-	sh_eth_write(ndev, mii, RMII_MII);
+	sh_eth_select_mii(ndev);
 }
 
 static void sh_eth_reset(struct net_device *ndev)
@@ -492,6 +513,7 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
 	.no_trimd	= 1,
 	.no_ade		= 1,
 	.tsu		= 1,
+	.select_mii	= 1,
 };
 
 #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index 57b8e1f..d6763b1392 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -757,6 +757,7 @@ struct sh_eth_cpu_data {
 	unsigned no_trimd:1;		/* E-DMAC DO NOT have TRIMD */
 	unsigned no_ade:1;	/* E-DMAC DO NOT have ADE bit in EESR */
 	unsigned hw_crc:1;	/* E-DMAC have CSMR */
+	unsigned select_mii:1;	/* EtherC have RMII_MII (MII select register) */
 };
 
 struct sh_eth_private {
-- 
1.7.10

^ permalink raw reply related

* [PATCH] net/sh-eth: Check return value of sh_eth_reset when chip reset fail
From: Nobuhiro Iwamatsu @ 2012-06-26  3:35 UTC (permalink / raw)
  To: netdev; +Cc: florian, Nobuhiro Iwamatsu

The sh_eth_reset function resets chip, but this performs nothing when failed.
This changes sh_eth_reset return an error, when this failed in reset.

Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
---
 drivers/net/ethernet/renesas/sh_eth.c |   88 +++++++++++++++++++++------------
 1 file changed, 56 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 8d696e0..326cb91 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -130,6 +130,8 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
 #elif defined(CONFIG_CPU_SUBTYPE_SH7757)
 #define SH_ETH_HAS_BOTH_MODULES	1
 #define SH_ETH_HAS_TSU	1
+static int sh_eth_check_reset(struct net_device *ndev);
+
 static void sh_eth_set_duplex(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
@@ -204,23 +206,19 @@ static void sh_eth_chip_reset_giga(struct net_device *ndev)
 }
 
 static int sh_eth_is_gether(struct sh_eth_private *mdp);
-static void sh_eth_reset(struct net_device *ndev)
+static int sh_eth_reset(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	int cnt = 100;
+	int ret = 0;
 
 	if (sh_eth_is_gether(mdp)) {
 		sh_eth_write(ndev, 0x03, EDSR);
 		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER,
 				EDMR);
-		while (cnt > 0) {
-			if (!(sh_eth_read(ndev, EDMR) & 0x3))
-				break;
-			mdelay(1);
-			cnt--;
-		}
-		if (cnt < 0)
-			printk(KERN_ERR "Device reset fail\n");
+
+		ret = sh_eth_check_reset(ndev);
+		if (ret)
+			goto out;
 
 		/* Table Init */
 		sh_eth_write(ndev, 0x0, TDLAR);
@@ -238,6 +236,9 @@ static void sh_eth_reset(struct net_device *ndev)
 		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER,
 				EDMR);
 	}
+
+out:
+	return ret;
 }
 
 static void sh_eth_set_duplex_giga(struct net_device *ndev)
@@ -310,6 +311,7 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
 
 #elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
 #define SH_ETH_HAS_TSU	1
+static int sh_eth_check_reset(struct net_device *ndev);
 static void sh_eth_reset_hw_crc(struct net_device *ndev);
 
 static void sh_eth_chip_reset(struct net_device *ndev)
@@ -381,20 +383,16 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
 #endif
 };
 
-static void sh_eth_reset(struct net_device *ndev)
+static int sh_eth_reset(struct net_device *ndev)
 {
-	int cnt = 100;
+	int ret = 0;
 
 	sh_eth_write(ndev, EDSR_ENALL, EDSR);
 	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
-	while (cnt > 0) {
-		if (!(sh_eth_read(ndev, EDMR) & 0x3))
-			break;
-		mdelay(1);
-		cnt--;
-	}
-	if (cnt == 0)
-		printk(KERN_ERR "Device reset fail\n");
+
+	ret = sh_eth_check_reset(ndev);
+	if (ret)
+		goto out;
 
 	/* Table Init */
 	sh_eth_write(ndev, 0x0, TDLAR);
@@ -412,6 +410,8 @@ static void sh_eth_reset(struct net_device *ndev)
 	/* Select MII mode */
 	if (sh_eth_my_cpu_data.select_mii)
 		sh_eth_select_mii(ndev);
+out:
+	return ret;
 }
 
 static void sh_eth_reset_hw_crc(struct net_device *ndev)
@@ -422,6 +422,8 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev)
 
 #elif defined(CONFIG_ARCH_R8A7740)
 #define SH_ETH_HAS_TSU	1
+static int sh_eth_check_reset(struct net_device *ndev);
+
 static void sh_eth_chip_reset(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
@@ -433,20 +435,16 @@ static void sh_eth_chip_reset(struct net_device *ndev)
 	sh_eth_select_mii(ndev);
 }
 
-static void sh_eth_reset(struct net_device *ndev)
+static int sh_eth_reset(struct net_device *ndev)
 {
-	int cnt = 100;
+	int ret = 0;
 
 	sh_eth_write(ndev, EDSR_ENALL, EDSR);
 	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
-	while (cnt > 0) {
-		if (!(sh_eth_read(ndev, EDMR) & 0x3))
-			break;
-		mdelay(1);
-		cnt--;
-	}
-	if (cnt == 0)
-		printk(KERN_ERR "Device reset fail\n");
+
+	ret = sh_eth_check_reset(ndev);
+	if (ret)
+		goto out;
 
 	/* Table Init */
 	sh_eth_write(ndev, 0x0, TDLAR);
@@ -457,6 +455,9 @@ static void sh_eth_reset(struct net_device *ndev)
 	sh_eth_write(ndev, 0x0, RDFAR);
 	sh_eth_write(ndev, 0x0, RDFXR);
 	sh_eth_write(ndev, 0x0, RDFFR);
+
+out:
+	return ret;
 }
 
 static void sh_eth_set_duplex(struct net_device *ndev)
@@ -565,11 +566,31 @@ static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd)
 
 #if defined(SH_ETH_RESET_DEFAULT)
 /* Chip Reset */
-static void sh_eth_reset(struct net_device *ndev)
+static int  sh_eth_reset(struct net_device *ndev)
 {
 	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, EDMR);
 	mdelay(3);
 	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, EDMR);
+
+	return 0;
+}
+#else
+static int sh_eth_check_reset(struct net_device *ndev)
+{
+	int ret = 0;
+	int cnt = 100;
+
+	while (cnt > 0) {
+		if (!(sh_eth_read(ndev, EDMR) & 0x3))
+			break;
+		mdelay(1);
+		cnt--;
+	}
+	if (cnt < 0) {
+		printk(KERN_ERR "Device reset fail\n");
+		ret = -ETIMEDOUT;
+	}
+	return ret;
 }
 #endif
 
@@ -924,7 +945,9 @@ static int sh_eth_dev_init(struct net_device *ndev)
 	u32 val;
 
 	/* Soft Reset */
-	sh_eth_reset(ndev);
+	ret = sh_eth_reset(ndev);
+	if (ret)
+		goto out;
 
 	/* Descriptor format */
 	sh_eth_ring_format(ndev);
@@ -998,6 +1021,7 @@ static int sh_eth_dev_init(struct net_device *ndev)
 
 	netif_start_queue(ndev);
 
+out:
 	return ret;
 }
 
-- 
1.7.10

^ permalink raw reply related

* Re: [PATCH v2] net/sh-eth: Add support selecting MII function for SH7734 and R8A7740
From: Nobuhiro Iwamatsu @ 2012-06-26  3:35 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: netdev
In-Reply-To: <2360907.koU5zCUYMQ@flexo>

Hi,

Thank you for your review.

Florian Fainelli さんは書きました:
> On Tuesday 12 June 2012 16:29:02 Nobuhiro Iwamatsu wrote:
>> Ethernet IP of SH7734 and R8A7740 has selecting MII register.
>> The user needs to change a value according to MII to be used.
>> This adds the function to change the value of this register.
>>
>> Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
>> ---
>>  V2: Fix the check by select_mii.
>>  drivers/net/ethernet/renesas/sh_eth.c |  106 
> ++++++++++++++++++++-------------
>>  drivers/net/ethernet/renesas/sh_eth.h |    1 +
>>  2 files changed, 65 insertions(+), 42 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/renesas/sh_eth.c 
> b/drivers/net/ethernet/renesas/sh_eth.c
>> index be3c221..5358804 100644
>> --- a/drivers/net/ethernet/renesas/sh_eth.c
>> +++ b/drivers/net/ethernet/renesas/sh_eth.c
>> @@ -49,6 +49,33 @@
>>  		NETIF_MSG_RX_ERR| \
>>  		NETIF_MSG_TX_ERR)
>>  
>> +#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) 
> || \
>> +	defined(CONFIG_ARCH_R8A7740)
>> +static void sh_eth_select_mii(struct net_device *ndev)
>> +{
>> +	u32 value = 0x0;
>> +	struct sh_eth_private *mdp = netdev_priv(ndev);
>> +
>> +	switch (mdp->phy_interface) {
>> +	case PHY_INTERFACE_MODE_GMII:
>> +		value = 0x2;
>> +		break;
>> +	case PHY_INTERFACE_MODE_MII:
>> +		value = 0x1;
>> +		break;
>> +	case PHY_INTERFACE_MODE_RMII:
>> +		value = 0x0;
>> +		break;
>> +	default:
>> +		pr_warn("PHY interface mode was not setup. Set to MII.\n");
>> +		value = 0x1;
>> +		break;
>> +	}
>> +
>> +	sh_eth_write(ndev, value, RMII_MII);
>> +}
>> +#endif
>> +
>>  /* There is CPU dependent code */
>>  #if defined(CONFIG_CPU_SUBTYPE_SH7724)
>>  #define SH_ETH_RESET_DEFAULT	1
>> @@ -283,6 +310,7 @@ static struct sh_eth_cpu_data 
> *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
>>  #elif defined(CONFIG_CPU_SUBTYPE_SH7734) || 
> defined(CONFIG_CPU_SUBTYPE_SH7763)
>>  #define SH_ETH_HAS_TSU	1
>>  static void sh_eth_reset_hw_crc(struct net_device *ndev);
>> +
>>  static void sh_eth_chip_reset(struct net_device *ndev)
>>  {
>>  	struct sh_eth_private *mdp = netdev_priv(ndev);
>> @@ -292,35 +320,6 @@ static void sh_eth_chip_reset(struct net_device *ndev)
>>  	mdelay(1);
>>  }
>>  
>> -static void sh_eth_reset(struct net_device *ndev)
>> -{
>> -	int cnt = 100;
>> -
>> -	sh_eth_write(ndev, EDSR_ENALL, EDSR);
>> -	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
>> -	while (cnt > 0) {
>> -		if (!(sh_eth_read(ndev, EDMR) & 0x3))
>> -			break;
>> -		mdelay(1);
>> -		cnt--;
>> -	}
>> -	if (cnt == 0)
>> -		printk(KERN_ERR "Device reset fail\n");
>> -
>> -	/* Table Init */
>> -	sh_eth_write(ndev, 0x0, TDLAR);
>> -	sh_eth_write(ndev, 0x0, TDFAR);
>> -	sh_eth_write(ndev, 0x0, TDFXR);
>> -	sh_eth_write(ndev, 0x0, TDFFR);
>> -	sh_eth_write(ndev, 0x0, RDLAR);
>> -	sh_eth_write(ndev, 0x0, RDFAR);
>> -	sh_eth_write(ndev, 0x0, RDFXR);
>> -	sh_eth_write(ndev, 0x0, RDFFR);
>> -
>> -	/* Reset HW CRC register */
>> -	sh_eth_reset_hw_crc(ndev);
>> -}
>> -
>>  static void sh_eth_set_duplex(struct net_device *ndev)
>>  {
>>  	struct sh_eth_private *mdp = netdev_priv(ndev);
>> @@ -377,9 +376,43 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
>>  	.tsu		= 1,
>>  #if defined(CONFIG_CPU_SUBTYPE_SH7734)
>>  	.hw_crc     = 1,
>> +	.select_mii = 1,
>>  #endif
>>  };
>>  
>> +static void sh_eth_reset(struct net_device *ndev)
>> +{
>> +	int cnt = 100;
>> +
>> +	sh_eth_write(ndev, EDSR_ENALL, EDSR);
>> +	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
>> +	while (cnt > 0) {
>> +		if (!(sh_eth_read(ndev, EDMR) & 0x3))
>> +			break;
>> +		mdelay(1);
>> +		cnt--;
>> +	}
>> +	if (cnt == 0)
>> +		printk(KERN_ERR "Device reset fail\n");
> 
> It looks like this would need a subsequent fix. Failing to reset the adapter 
> and just erroring out and not returning an error looks obviously wrong. Since 
> sh_eth_reset() is called in sh_eth_dev_init() which does return an int, 
> propagate the error back to the caller.

Yes, you are right. I will fix your point and send a patch.

Best regards,
   Nobuhiro

^ permalink raw reply

* Re: [PATCH] Allow receiving packets on the fallback tunnel if they pass sanity checks
From: Phil Dibowitz @ 2012-06-26  3:37 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, phild
In-Reply-To: <20120620.210405.2231549940491911080.davem@davemloft.net>

[-- Attachment #1: Type: text/plain, Size: 2435 bytes --]

On 06/20/2012 09:04 PM, David Miller wrote:
> From: Phil Dibowitz <phil@ipom.com>
> Date: Tue, 5 Jun 2012 08:40:58 -0700
> 
>> From b413062771afbba064ae9bc49b5daed7abb1243d Mon Sep 17 00:00:00 2001
>> From: Ville Nuorvala <ville.nuorvala@gmail.com>
>> Subject: [PATCH] Allow receiving packets on the fallback tunnel if they pass sanity checks
>>
>> The same IPv6 address checks are performed as with any normal tunnel,
>> but as the fallback tunnel endpoint addresses are unspecified, the checks
>> must be performed on a per-packet basis, rather than at tunnel
>> configuration time.
>>
>> Signed-off-by: Ville Nuorvala <ville.nuorvala@gmail.com>
>> Tested-by: Phil Dibowitz <phil@ipom.com>
> 
> I've reviewed this change but I still have no idea why it's
> necessary.
> 
> You need to compose a more lengthy and detailed commit log message
> explaining everything before I'm going to consider applying this
> patch.
> 
> You can't just say "we have some problem at Facebook, this patch fixes
> it", and then merely describe word by word the content of the patch
> without explaining the "why".  That simply doesn't cut it.

Sure. Sorry, I just kept Ville's patch description.

We do Layer-3 DSR via IP-in-IP tunneling. Our load balancers wrap an extra IP
header on incoming packets so they can be routed to the backend. In the v4
tunnel driver, when these packets fall on the default tunl0 device, the
behavior is to decapsulate them and drop them back on the stack. So our setup
is that tunl0 has the VIP and eth0 has (obviously) the backend's real address.

In IPv6 we do the same thing, but the v6 tunnel driver didn't have this same
behavior - if you didn't have an explicit tunnel setup, it would drop the packet.

This patch brings that v4 feature to the v6 driver.

I think that's the level of detail you're looking for, but I'm happy to expand
on anything in particular. I also break this down in tons of detail here:

https://www.facebook.com/notes/facebook-engineering/under-the-hood-network-implementation-for-world-ipv6-launch/10150873176303920

-- 
Phil Dibowitz                             phil@ipom.com
Open Source software and tech docs        Insanity Palace of Metallica
http://www.phildev.net/                   http://www.ipom.com/

"Be who you are and say what you feel, because those who mind don't matter
 and those who matter don't mind."
 - Dr. Seuss



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply

* Re: [net-next RFC V3 PATCH 4/6] tuntap: multiqueue support
From: Jason Wang @ 2012-06-26  3:42 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: habanero, netdev, linux-kernel, krkumar2, tahm, akong, davem,
	shemminger, mashirle
In-Reply-To: <20120625082553.GC18229@redhat.com>

On 06/25/2012 04:25 PM, Michael S. Tsirkin wrote:
> On Mon, Jun 25, 2012 at 02:10:18PM +0800, Jason Wang wrote:
>> This patch adds multiqueue support for tap device. This is done by abstracting
>> each queue as a file/socket and allowing multiple sockets to be attached to the
>> tuntap device (an array of tun_file were stored in the tun_struct). Userspace
>> could write and read from those files to do the parallel packet
>> sending/receiving.
>>
>> Unlike the previous single queue implementation, the socket and device were
>> loosely coupled, each of them were allowed to go away first. In order to let the
>> tx path lockless, netif_tx_loch_bh() is replaced by RCU/NETIF_F_LLTX to
>> synchronize between data path and system call.
> Don't use LLTX/RCU. It's not worth it.
> Use something like netif_set_real_num_tx_queues.
>
>> The tx queue selecting is first based on the recorded rxq index of an skb, it
>> there's no such one, then choosing based on rx hashing (skb_get_rxhash()).
>>
>> Signed-off-by: Jason Wang<jasowang@redhat.com>
> Interestingly macvtap switched to hashing first:
> ef0002b577b52941fb147128f30bd1ecfdd3ff6d
> (the commit log is corrupted but see what it
> does in the patch).
> Any idea why?

Yes, so tap should be changed to behave same as macvtap. I remember the 
reason we do that is to make sure the packet of a single flow to be 
queued to a fixed socket/virtqueues. As 10g cards like ixgbe choose the 
rx queue for a flow based on the last tx queue where the packets of that 
flow comes. So if we are using recored rx queue in macvtap, the queue 
index of a flow would change as vhost thread moves amongs processors.

But during test tun/tap, one interesting thing I find is that even ixgbe 
has recorded the queue index during rx, it seems be lost when tap tries 
to transmit skbs to userspace.

>> ---
>>   drivers/net/tun.c |  371 +++++++++++++++++++++++++++++++++--------------------
>>   1 files changed, 232 insertions(+), 139 deletions(-)
>>
>> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
>> index 8233b0a..5c26757 100644
>> --- a/drivers/net/tun.c
>> +++ b/drivers/net/tun.c
>> @@ -107,6 +107,8 @@ struct tap_filter {
>>   	unsigned char	addr[FLT_EXACT_COUNT][ETH_ALEN];
>>   };
>>
>> +#define MAX_TAP_QUEUES (NR_CPUS<  16 ? NR_CPUS : 16)
> Why the limit? I am guessing you copied this from macvtap?
> This is problematic for a number of reasons:
> 	- will not play well with migration
> 	- will not work well for a large guest
>
> Yes, macvtap needs to be fixed too.
>
> I am guessing what it is trying to prevent is queueing
> up a huge number of packets?
> So just divide the default tx queue limit by the # of queues.
>
> And by the way, for MQ applications maybe we can finally
> ignore tx queue altogether and limit the total number
> of bytes queued?
> To avoid regressions we can make it large like 64M/# queues.
> Could be a separate patch I think, and for a single queue
> might need a compatible mode though I am not sure.
>
>> +
>>   struct tun_file {
>>   	struct sock sk;
>>   	struct socket socket;
>> @@ -114,16 +116,18 @@ struct tun_file {
>>   	int vnet_hdr_sz;
>>   	struct tap_filter txflt;
>>   	atomic_t count;
>> -	struct tun_struct *tun;
>> +	struct tun_struct __rcu *tun;
>>   	struct net *net;
>>   	struct fasync_struct *fasync;
>>   	unsigned int flags;
>> +	u16 queue_index;
>>   };
>>
>>   struct tun_sock;
>>
>>   struct tun_struct {
>> -	struct tun_file		*tfile;
>> +	struct tun_file		*tfiles[MAX_TAP_QUEUES];
>> +	unsigned int            numqueues;
>>   	unsigned int 		flags;
>>   	uid_t			owner;
>>   	gid_t			group;
>> @@ -138,80 +142,159 @@ struct tun_struct {
>>   #endif
>>   };
>>
>> -static int tun_attach(struct tun_struct *tun, struct file *file)
>> +static DEFINE_SPINLOCK(tun_lock);
>> +
>> +/*
>> + * tun_get_queue(): calculate the queue index
>> + *     - if skbs comes from mq nics, we can just borrow
>> + *     - if not, calculate from the hash
>> + */
>> +static struct tun_file *tun_get_queue(struct net_device *dev,
>> +				      struct sk_buff *skb)
>>   {
>> -	struct tun_file *tfile = file->private_data;
>> -	int err;
>> +	struct tun_struct *tun = netdev_priv(dev);
>> +	struct tun_file *tfile = NULL;
>> +	int numqueues = tun->numqueues;
>> +	__u32 rxq;
>>
>> -	ASSERT_RTNL();
>> +	BUG_ON(!rcu_read_lock_held());
>>
>> -	netif_tx_lock_bh(tun->dev);
>> +	if (!numqueues)
>> +		goto out;
>>
>> -	err = -EINVAL;
>> -	if (tfile->tun)
>> +	if (numqueues == 1) {
>> +		tfile = rcu_dereference(tun->tfiles[0]);
> Instead of hacks like this, you can ask for an MQ
> flag to be set in SETIFF. Then you won't need to
> handle attach/detach at random times.
> And most of the scary num_queues checks can go away.
> You can then also ask userspace about the max # of queues
> to expect if you want to save some memory.
>
>
>>   		goto out;
>> +	}
>>
>> -	err = -EBUSY;
>> -	if (tun->tfile)
>> +	if (likely(skb_rx_queue_recorded(skb))) {
>> +		rxq = skb_get_rx_queue(skb);
>> +
>> +		while (unlikely(rxq>= numqueues))
>> +			rxq -= numqueues;
>> +
>> +		tfile = rcu_dereference(tun->tfiles[rxq]);
>>   		goto out;
>> +	}
>>
>> -	err = 0;
>> -	tfile->tun = tun;
>> -	tun->tfile = tfile;
>> -	netif_carrier_on(tun->dev);
>> -	dev_hold(tun->dev);
>> -	sock_hold(&tfile->sk);
>> -	atomic_inc(&tfile->count);
>> +	/* Check if we can use flow to select a queue */
>> +	rxq = skb_get_rxhash(skb);
>> +	if (rxq) {
>> +		u32 idx = ((u64)rxq * numqueues)>>  32;
> This completely confuses me. What's the logic here?
> How do we even know it's in range?
>
>> +		tfile = rcu_dereference(tun->tfiles[idx]);
>> +		goto out;
>> +	}
>>
>> +	tfile = rcu_dereference(tun->tfiles[0]);
>>   out:
>> -	netif_tx_unlock_bh(tun->dev);
>> -	return err;
>> +	return tfile;
>>   }
>>
>> -static void __tun_detach(struct tun_struct *tun)
>> +static int tun_detach(struct tun_file *tfile, bool clean)
>>   {
>> -	struct tun_file *tfile = tun->tfile;
>> -	/* Detach from net device */
>> -	netif_tx_lock_bh(tun->dev);
>> -	netif_carrier_off(tun->dev);
>> -	tun->tfile = NULL;
>> -	netif_tx_unlock_bh(tun->dev);
>> -
>> -	/* Drop read queue */
>> -	skb_queue_purge(&tfile->socket.sk->sk_receive_queue);
>> -
>> -	/* Drop the extra count on the net device */
>> -	dev_put(tun->dev);
>> -}
>> +	struct tun_struct *tun;
>> +	struct net_device *dev = NULL;
>> +	bool destroy = false;
>>
>> -static void tun_detach(struct tun_struct *tun)
>> -{
>> -	rtnl_lock();
>> -	__tun_detach(tun);
>> -	rtnl_unlock();
>> -}
>> +	spin_lock(&tun_lock);
>>
>> -static struct tun_struct *__tun_get(struct tun_file *tfile)
>> -{
>> -	struct tun_struct *tun = NULL;
>> +	tun = rcu_dereference_protected(tfile->tun,
>> +					lockdep_is_held(&tun_lock));
>> +	if (tun) {
>> +		u16 index = tfile->queue_index;
>> +		BUG_ON(index>= tun->numqueues);
>> +		dev = tun->dev;
>> +
>> +		rcu_assign_pointer(tun->tfiles[index],
>> +				   tun->tfiles[tun->numqueues - 1]);
>> +		tun->tfiles[index]->queue_index = index;
>> +		rcu_assign_pointer(tfile->tun, NULL);
>> +		--tun->numqueues;
>> +		sock_put(&tfile->sk);
>>
>> -	if (atomic_inc_not_zero(&tfile->count))
>> -		tun = tfile->tun;
>> +		if (tun->numqueues == 0&&  !(tun->flags&  TUN_PERSIST))
>> +			destroy = true;
> Please don't use flags like that. Use dedicated labels and goto there on error.
>
>
>> +	}
>>
>> -	return tun;
>> +	spin_unlock(&tun_lock);
>> +
>> +	synchronize_rcu();
>> +	if (clean)
>> +		sock_put(&tfile->sk);
>> +
>> +	if (destroy) {
>> +		rtnl_lock();
>> +		if (dev->reg_state == NETREG_REGISTERED)
>> +			unregister_netdevice(dev);
>> +		rtnl_unlock();
>> +	}
>> +
>> +	return 0;
>>   }
>>
>> -static struct tun_struct *tun_get(struct file *file)
>> +static void tun_detach_all(struct net_device *dev)
>>   {
>> -	return __tun_get(file->private_data);
>> +	struct tun_struct *tun = netdev_priv(dev);
>> +	struct tun_file *tfile, *tfile_list[MAX_TAP_QUEUES];
>> +	int i, j = 0;
>> +
>> +	spin_lock(&tun_lock);
>> +
>> +	for (i = 0; i<  MAX_TAP_QUEUES&&  tun->numqueues; i++) {
>> +		tfile = rcu_dereference_protected(tun->tfiles[i],
>> +						lockdep_is_held(&tun_lock));
>> +		BUG_ON(!tfile);
>> +		wake_up_all(&tfile->wq.wait);
>> +		tfile_list[j++] = tfile;
>> +		rcu_assign_pointer(tfile->tun, NULL);
>> +		--tun->numqueues;
>> +	}
>> +	BUG_ON(tun->numqueues != 0);
>> +	/* guarantee that any future tun_attach will fail */
>> +	tun->numqueues = MAX_TAP_QUEUES;
>> +	spin_unlock(&tun_lock);
>> +
>> +	synchronize_rcu();
>> +	for (--j; j>= 0; j--)
>> +		sock_put(&tfile_list[j]->sk);
>>   }
>>
>> -static void tun_put(struct tun_struct *tun)
>> +static int tun_attach(struct tun_struct *tun, struct file *file)
>>   {
>> -	struct tun_file *tfile = tun->tfile;
>> +	struct tun_file *tfile = file->private_data;
>> +	int err;
>> +
>> +	ASSERT_RTNL();
>> +
>> +	spin_lock(&tun_lock);
>>
>> -	if (atomic_dec_and_test(&tfile->count))
>> -		tun_detach(tfile->tun);
>> +	err = -EINVAL;
>> +	if (rcu_dereference_protected(tfile->tun, lockdep_is_held(&tun_lock)))
>> +		goto out;
>> +
>> +	err = -EBUSY;
>> +	if (!(tun->flags&  TUN_TAP_MQ)&&  tun->numqueues == 1)
>> +		goto out;
>> +
>> +	if (tun->numqueues == MAX_TAP_QUEUES)
>> +		goto out;
>> +
>> +	err = 0;
>> +	tfile->queue_index = tun->numqueues;
>> +	rcu_assign_pointer(tfile->tun, tun);
>> +	rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
>> +	sock_hold(&tfile->sk);
>> +	tun->numqueues++;
>> +
>> +	if (tun->numqueues == 1)
>> +		netif_carrier_on(tun->dev);
>> +
>> +	/* device is allowed to go away first, so no need to hold extra
>> +	 * refcnt. */
>> +
>> +out:
>> +	spin_unlock(&tun_lock);
>> +	return err;
>>   }
>>
>>   /* TAP filtering */
>> @@ -331,16 +414,7 @@ static const struct ethtool_ops tun_ethtool_ops;
>>   /* Net device detach from fd. */
>>   static void tun_net_uninit(struct net_device *dev)
>>   {
>> -	struct tun_struct *tun = netdev_priv(dev);
>> -	struct tun_file *tfile = tun->tfile;
>> -
>> -	/* Inform the methods they need to stop using the dev.
>> -	 */
>> -	if (tfile) {
>> -		wake_up_all(&tfile->wq.wait);
>> -		if (atomic_dec_and_test(&tfile->count))
>> -			__tun_detach(tun);
>> -	}
>> +	tun_detach_all(dev);
>>   }
>>
>>   /* Net device open. */
>> @@ -360,10 +434,10 @@ static int tun_net_close(struct net_device *dev)
>>   /* Net device start xmit */
>>   static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
>>   {
>> -	struct tun_struct *tun = netdev_priv(dev);
>> -	struct tun_file *tfile = tun->tfile;
>> +	struct tun_file *tfile = NULL;
>>
>> -	tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len);
>> +	rcu_read_lock();
>> +	tfile = tun_get_queue(dev, skb);
>>
>>   	/* Drop packet if interface is not attached */
>>   	if (!tfile)
>> @@ -381,7 +455,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
>>
>>   	if (skb_queue_len(&tfile->socket.sk->sk_receive_queue)
>>   	>= dev->tx_queue_len) {
>> -		if (!(tun->flags&  TUN_ONE_QUEUE)) {
>> +		if (!(tfile->flags&  TUN_ONE_QUEUE)&&
> Which patch moved flags from tun to tfile?
>
>> +		    !(tfile->flags&  TUN_TAP_MQ)) {
>>   			/* Normal queueing mode. */
>>   			/* Packet scheduler handles dropping of further packets. */
>>   			netif_stop_queue(dev);
>> @@ -390,7 +465,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
>>   			 * error is more appropriate. */
>>   			dev->stats.tx_fifo_errors++;
>>   		} else {
>> -			/* Single queue mode.
>> +			/* Single queue mode or multi queue mode.
>>   			 * Driver handles dropping of all packets itself. */
> Please don't do this. Stop the queue on overrun as appropriate.
> ONE_QUEUE is a legacy hack.
>
> BTW we really should stop queue before we start dropping packets,
> but that can be a separate patch.
>
>>   			goto drop;
>>   		}
>> @@ -408,9 +483,11 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
>>   		kill_fasync(&tfile->fasync, SIGIO, POLL_IN);
>>   	wake_up_interruptible_poll(&tfile->wq.wait, POLLIN |
>>   				   POLLRDNORM | POLLRDBAND);
>> +	rcu_read_unlock();
>>   	return NETDEV_TX_OK;
>>
>>   drop:
>> +	rcu_read_unlock();
>>   	dev->stats.tx_dropped++;
>>   	kfree_skb(skb);
>>   	return NETDEV_TX_OK;
>> @@ -527,16 +604,22 @@ static void tun_net_init(struct net_device *dev)
>>   static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
>>   {
>>   	struct tun_file *tfile = file->private_data;
>> -	struct tun_struct *tun = __tun_get(tfile);
>> +	struct tun_struct *tun = NULL;
>>   	struct sock *sk;
>>   	unsigned int mask = 0;
>>
>> -	if (!tun)
>> +	if (!tfile)
>>   		return POLLERR;
>>
>> -	sk = tfile->socket.sk;
>> +	rcu_read_lock();
>> +	tun = rcu_dereference(tfile->tun);
>> +	if (!tun) {
>> +		rcu_read_unlock();
>> +		return POLLERR;
>> +	}
>> +	rcu_read_unlock();
>>
>> -	tun_debug(KERN_INFO, tun, "tun_chr_poll\n");
>> +	sk =&tfile->sk;
>>
>>   	poll_wait(file,&tfile->wq.wait, wait);
>>
>> @@ -548,10 +631,12 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
>>   	     sock_writeable(sk)))
>>   		mask |= POLLOUT | POLLWRNORM;
>>
>> -	if (tun->dev->reg_state != NETREG_REGISTERED)
>> +	rcu_read_lock();
>> +	tun = rcu_dereference(tfile->tun);
>> +	if (!tun || tun->dev->reg_state != NETREG_REGISTERED)
>>   		mask = POLLERR;
>> +	rcu_read_unlock();
>>
>> -	tun_put(tun);
>>   	return mask;
>>   }
>>
>> @@ -708,9 +793,12 @@ static ssize_t tun_get_user(struct tun_file *tfile,
>>   		skb_shinfo(skb)->gso_segs = 0;
>>   	}
>>
>> -	tun = __tun_get(tfile);
>> -	if (!tun)
>> +	rcu_read_lock();
>> +	tun = rcu_dereference(tfile->tun);
>> +	if (!tun) {
>> +		rcu_read_unlock();
>>   		return -EBADFD;
>> +	}
>>
>>   	switch (tfile->flags&  TUN_TYPE_MASK) {
>>   	case TUN_TUN_DEV:
>> @@ -720,26 +808,30 @@ static ssize_t tun_get_user(struct tun_file *tfile,
>>   		skb->protocol = eth_type_trans(skb, tun->dev);
>>   		break;
>>   	}
>> -
>> -	netif_rx_ni(skb);
>>   	tun->dev->stats.rx_packets++;
>>   	tun->dev->stats.rx_bytes += len;
>> -	tun_put(tun);
>> +	rcu_read_unlock();
>> +
>> +	netif_rx_ni(skb);
>> +
>>   	return count;
>>
>>   err_free:
>>   	count = -EINVAL;
>>   	kfree_skb(skb);
>>   err:
>> -	tun = __tun_get(tfile);
>> -	if (!tun)
>> +	rcu_read_lock();
>> +	tun = rcu_dereference(tfile->tun);
>> +	if (!tun) {
>> +		rcu_read_unlock();
>>   		return -EBADFD;
>> +	}
>>
>>   	if (drop)
>>   		tun->dev->stats.rx_dropped++;
>>   	if (error)
>>   		tun->dev->stats.rx_frame_errors++;
>> -	tun_put(tun);
>> +	rcu_read_unlock();
>>   	return count;
>>   }
>>
>> @@ -833,12 +925,13 @@ static ssize_t tun_put_user(struct tun_file *tfile,
>>   	skb_copy_datagram_const_iovec(skb, 0, iv, total, len);
>>   	total += skb->len;
>>
>> -	tun = __tun_get(tfile);
>> +	rcu_read_lock();
>> +	tun = rcu_dereference(tfile->tun);
>>   	if (tun) {
>>   		tun->dev->stats.tx_packets++;
>>   		tun->dev->stats.tx_bytes += len;
>> -		tun_put(tun);
>>   	}
>> +	rcu_read_unlock();
>>
>>   	return total;
>>   }
>> @@ -869,28 +962,31 @@ static ssize_t tun_do_read(struct tun_file *tfile,
>>   				break;
>>   			}
>>
>> -			tun = __tun_get(tfile);
>> +			rcu_read_lock();
>> +			tun = rcu_dereference(tfile->tun);
>>   			if (!tun) {
>> -				ret = -EIO;
>> +				ret = -EBADFD;
> BADFD is for when you get passed something like -1 fd.
> Here fd is OK, it's just in a bad state so you can not do IO.
>
>
>> +				rcu_read_unlock();
>>   				break;
>>   			}
>>   			if (tun->dev->reg_state != NETREG_REGISTERED) {
>>   				ret = -EIO;
>> -				tun_put(tun);
>> +				rcu_read_unlock();
>>   				break;
>>   			}
>> -			tun_put(tun);
>> +			rcu_read_unlock();
>>
>>   			/* Nothing to read, let's sleep */
>>   			schedule();
>>   			continue;
>>   		}
>>
>> -		tun = __tun_get(tfile);
>> +		rcu_read_lock();
>> +		tun = rcu_dereference(tfile->tun);
>>   		if (tun) {
>>   			netif_wake_queue(tun->dev);
>> -			tun_put(tun);
>>   		}
>> +		rcu_read_unlock();
>>
>>   		ret = tun_put_user(tfile, skb, iv, len);
>>   		kfree_skb(skb);
>> @@ -1038,6 +1134,9 @@ static int tun_flags(struct tun_struct *tun)
>>   	if (tun->flags&  TUN_VNET_HDR)
>>   		flags |= IFF_VNET_HDR;
>>
>> +	if (tun->flags&  TUN_TAP_MQ)
>> +		flags |= IFF_MULTI_QUEUE;
>> +
>>   	return flags;
>>   }
>>
>> @@ -1097,8 +1196,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
>>   		err = tun_attach(tun, file);
>>   		if (err<  0)
>>   			return err;
>> -	}
>> -	else {
>> +	} else {
>>   		char *name;
>>   		unsigned long flags = 0;
>>
>> @@ -1142,6 +1240,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
>>   		dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
>>   			TUN_USER_FEATURES;
>>   		dev->features = dev->hw_features;
>> +		if (ifr->ifr_flags&  IFF_MULTI_QUEUE)
>> +			dev->features |= NETIF_F_LLTX;
>>
>>   		err = register_netdevice(tun->dev);
>>   		if (err<  0)
>> @@ -1154,7 +1254,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
>>
>>   		err = tun_attach(tun, file);
>>   		if (err<  0)
>> -			goto failed;
>> +			goto err_free_dev;
>>   	}
>>
>>   	tun_debug(KERN_INFO, tun, "tun_set_iff\n");
>> @@ -1174,6 +1274,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
>>   	else
>>   		tun->flags&= ~TUN_VNET_HDR;
>>
>> +	if (ifr->ifr_flags&  IFF_MULTI_QUEUE)
>> +		tun->flags |= TUN_TAP_MQ;
>> +	else
>> +		tun->flags&= ~TUN_TAP_MQ;
>> +
>>   	/* Cache flags from tun device */
>>   	tfile->flags = tun->flags;
>>   	/* Make sure persistent devices do not get stuck in
>> @@ -1187,7 +1292,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
>>
>>   err_free_dev:
>>   	free_netdev(dev);
>> -failed:
>>   	return err;
>>   }
>>
>> @@ -1264,38 +1368,40 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
>>   				(unsigned int __user*)argp);
>>   	}
>>
>> -	rtnl_lock();
>> -
>> -	tun = __tun_get(tfile);
>> -	if (cmd == TUNSETIFF&&  !tun) {
>> +	ret = 0;
>> +	if (cmd == TUNSETIFF) {
>> +		rtnl_lock();
>>   		ifr.ifr_name[IFNAMSIZ-1] = '\0';
>> -
>>   		ret = tun_set_iff(tfile->net, file,&ifr);
>> -
>> +		rtnl_unlock();
>>   		if (ret)
>> -			goto unlock;
>> -
>> +			return ret;
>>   		if (copy_to_user(argp,&ifr, ifreq_len))
>> -			ret = -EFAULT;
>> -		goto unlock;
>> +			return -EFAULT;
>> +		return ret;
>>   	}
>>
>> +	rtnl_lock();
>> +
>> +	rcu_read_lock();
>> +
>>   	ret = -EBADFD;
>> +	tun = rcu_dereference(tfile->tun);
>>   	if (!tun)
>>   		goto unlock;
>> +	else
>> +		ret = 0;
>>
>> -	tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %d\n", cmd);
>> -
>> -	ret = 0;
>>   	switch (cmd) {
>>   	case TUNGETIFF:
>>   		ret = tun_get_iff(current->nsproxy->net_ns, tun,&ifr);
>> +		rcu_read_unlock();
>>   		if (ret)
>> -			break;
>> +			goto out;
>>
>>   		if (copy_to_user(argp,&ifr, ifreq_len))
>>   			ret = -EFAULT;
>> -		break;
>> +		goto out;
>>
>>   	case TUNSETNOCSUM:
>>   		/* Disable/Enable checksum */
>> @@ -1357,9 +1463,10 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
>>   		/* Get hw address */
>>   		memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN);
>>   		ifr.ifr_hwaddr.sa_family = tun->dev->type;
>> +		rcu_read_unlock();
>>   		if (copy_to_user(argp,&ifr, ifreq_len))
>>   			ret = -EFAULT;
>> -		break;
>> +		goto out;
>>
>>   	case SIOCSIFHWADDR:
>>   		/* Set hw address */
>> @@ -1375,9 +1482,9 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
>>   	}
>>
>>   unlock:
>> +	rcu_read_unlock();
>> +out:
>>   	rtnl_unlock();
>> -	if (tun)
>> -		tun_put(tun);
>>   	return ret;
>>   }
>>
>> @@ -1517,6 +1624,11 @@ out:
>>   	return ret;
>>   }
>>
>> +static void tun_sock_destruct(struct sock *sk)
>> +{
>> +	skb_queue_purge(&sk->sk_receive_queue);
>> +}
>> +
>>   static int tun_chr_open(struct inode *inode, struct file * file)
>>   {
>>   	struct net *net = current->nsproxy->net_ns;
>> @@ -1540,6 +1652,7 @@ static int tun_chr_open(struct inode *inode, struct file * file)
>>   	sock_init_data(&tfile->socket,&tfile->sk);
>>
>>   	tfile->sk.sk_write_space = tun_sock_write_space;
>> +	tfile->sk.sk_destruct = tun_sock_destruct;
>>   	tfile->sk.sk_sndbuf = INT_MAX;
>>   	file->private_data = tfile;
>>
>> @@ -1549,31 +1662,8 @@ static int tun_chr_open(struct inode *inode, struct file * file)
>>   static int tun_chr_close(struct inode *inode, struct file *file)
>>   {
>>   	struct tun_file *tfile = file->private_data;
>> -	struct tun_struct *tun;
>> -
>> -	tun = __tun_get(tfile);
>> -	if (tun) {
>> -		struct net_device *dev = tun->dev;
>> -
>> -		tun_debug(KERN_INFO, tun, "tun_chr_close\n");
>> -
>> -		__tun_detach(tun);
>> -
>> -		/* If desirable, unregister the netdevice. */
>> -		if (!(tun->flags&  TUN_PERSIST)) {
>> -			rtnl_lock();
>> -			if (dev->reg_state == NETREG_REGISTERED)
>> -				unregister_netdevice(dev);
>> -			rtnl_unlock();
>> -		}
>>
>> -		/* drop the reference that netdevice holds */
>> -		sock_put(&tfile->sk);
>> -
>> -	}
>> -
>> -	/* drop the reference that file holds */
>> -	sock_put(&tfile->sk);
>> +	tun_detach(tfile, true);
>>
>>   	return 0;
>>   }
>> @@ -1700,14 +1790,17 @@ static void tun_cleanup(void)
>>    * holding a reference to the file for as long as the socket is in use. */
>>   struct socket *tun_get_socket(struct file *file)
>>   {
>> -	struct tun_struct *tun;
>> +	struct tun_struct *tun = NULL;
>>   	struct tun_file *tfile = file->private_data;
>>   	if (file->f_op !=&tun_fops)
>>   		return ERR_PTR(-EINVAL);
>> -	tun = tun_get(file);
>> -	if (!tun)
>> +	rcu_read_lock();
>> +	tun = rcu_dereference(tfile->tun);
>> +	if (!tun) {
>> +		rcu_read_unlock();
>>   		return ERR_PTR(-EBADFD);
>> -	tun_put(tun);
>> +	}
>> +	rcu_read_unlock();
>>   	return&tfile->socket;
>>   }
>>   EXPORT_SYMBOL_GPL(tun_get_socket);

^ permalink raw reply


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