Netdev List
 help / color / mirror / Atom feed
* RE: [PATCH v2 1/1] ip-link: in human readable output use dynamic precision length
From: David Laight @ 2014-11-05  9:30 UTC (permalink / raw)
  To: 'Christian Hesse'; +Cc: Stephen Hemminger, netdev@vger.kernel.org
In-Reply-To: <20141104221038.440fd9d7@leda.localdomain>

From: Christian Hesse
...
> 
> I do not like this at all... snprintf() would be nice for a catch-all, but we
> have to take care of negative values. So let's try something different.
> I will think about it and send a new patch.
> 
> > > +		precision = 0;
> > > +
> > > +	snprintf(buf, sizeof(buf), "%.*f%c%s", precision,
> > > +		(double) count / powi, *prefix, use_iec ? "i" : "");
> > >
> > >  	fprintf(fp, "%-*s ", width, buf);
> > >  }
> >
> > The above will go wrong in all sorts of horrid ways....
> > For instance you are doing a truncating integer divide, but the FP
> > value will get rounded for display.
> >
> > It would be safer to use integers throughout.
> 
> My implementation used integers, but Stephen changes this to floating point
> with his cleanups.
> 
> IMHO the rounding is ok. This is for *human* readability. ;)
> Whoever wants correct values should not ask ip to print human readable values
> but rely on pure numbers.

Rounding the value is fine, the difference between 1000 and 1024
is not that great either.
The problem is that the two calculations get rounded differently.
If the FP value ends up being 9.999999 it will be printed as 10.0
but your field width calculation will only have allowed for
a single digit.

> > Oh, and a 2Mbit E1 link is actually 2048000 :-)
> 
> Sorry? Did not get the point.
That was really in reference to a much earlier comment about comms
always using 1000.

	David

^ permalink raw reply

* Re: [PATCH] stmmac: fix sparse warnings
From: Giuseppe CAVALLARO @ 2014-11-05  9:27 UTC (permalink / raw)
  To: Andy Shevchenko; +Cc: netdev, Kweh Hock Leong, David S . Miller, Vince Bridgers
In-Reply-To: <1415178226.472.9.camel@linux.intel.com>

On 11/5/2014 10:03 AM, Andy Shevchenko wrote:
> On Tue, 2014-11-04 at 17:35 +0100, Giuseppe CAVALLARO wrote:
>> On 11/3/2014 6:28 PM, Andy Shevchenko wrote:
>>> This patch fixes the following sparse warnings.
>>>
>>> drivers/net/ethernet/stmicro/stmmac/enh_desc.c:381:30: warning: symbol 'enh_desc_ops' was not declared. Should it be static?
>>> drivers/net/ethernet/stmicro/stmmac/norm_desc.c:253:30: warning: symbol 'ndesc_ops' was not declared. Should it be static?
>>> drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c:141:33: warning: symbol 'stmmac_ptp' was not declared. Should it be static?
>>>
>>> There is no functional change.
>>
>> Hello Andy
>>
>> I have never seen this kind of warnings. I prefer to not include the
>> stmmac.h in enh_desc.c and norm_desc.c but eventually to move the
>> following from stmmac.h to common.h:
>>     extern const struct stmmac_desc_ops enh_desc_ops;
>>     extern const struct stmmac_desc_ops ndesc_ops;
>> what do you think?
>
> If it would work I do this way certainly. Thanks for the tip.

yes Andy just verified with sparse, pls also fix:

extern const struct stmmac_hwtimestamp stmmac_ptp;

in the same way.

>
> Will check soon and resubmit new version.

sure and you can add my Acked-by:

peppe

>
>>
>> peppe
>>
>>
>>>
>>> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>>> ---
>>>    drivers/net/ethernet/stmicro/stmmac/enh_desc.c        | 2 ++
>>>    drivers/net/ethernet/stmicro/stmmac/norm_desc.c       | 2 ++
>>>    drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 2 ++
>>>    3 files changed, 6 insertions(+)
>>>
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
>>> index 1e2bcf5..ddd4272 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
>>> @@ -23,8 +23,10 @@
>>>    *******************************************************************************/
>>>
>>>    #include <linux/stmmac.h>
>>> +
>>>    #include "common.h"
>>>    #include "descs_com.h"
>>> +#include "stmmac.h"
>>>
>>>    static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
>>>    				  struct dma_desc *p, void __iomem *ioaddr)
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
>>> index 35ad4f4..46b882c 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
>>> @@ -23,8 +23,10 @@
>>>    *******************************************************************************/
>>>
>>>    #include <linux/stmmac.h>
>>> +
>>>    #include "common.h"
>>>    #include "descs_com.h"
>>> +#include "stmmac.h"
>>>
>>>    static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
>>>    			       struct dma_desc *p, void __iomem *ioaddr)
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
>>> index 76ad214..88e0da3 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
>>> @@ -25,8 +25,10 @@
>>>
>>>    #include <linux/io.h>
>>>    #include <linux/delay.h>
>>> +
>>>    #include "common.h"
>>>    #include "stmmac_ptp.h"
>>> +#include "stmmac.h"
>>>
>>>    static void stmmac_config_hw_tstamping(void __iomem *ioaddr, u32 data)
>>>    {
>>>
>>
>
>

^ permalink raw reply

* Re: [PATCH] ipvs: Keep skb->sk when allocating headroom on tunnel xmit
From: Julian Anastasov @ 2014-11-05  9:21 UTC (permalink / raw)
  To: Calvin Owens
  Cc: Simon Horman, Wensong Zhang, lvs-devel, linux-kernel, netdev,
	agartrell, kernel-team
In-Reply-To: <1415147860-11389-1-git-send-email-calvinowens@fb.com>


	Hello,

On Tue, 4 Nov 2014, Calvin Owens wrote:

> ip_vs_prepare_tunneled_skb() ignores ->sk when allocating a new
> skb, either unconditionally setting ->sk to NULL or allowing
> the uninitialized ->sk from a newly allocated skb to leak through
> to the caller.
> 
> This patch properly copies ->sk and increments its reference count.
> 
> Signed-off-by: Calvin Owens <calvinowens@fb.com>

	Good catch. Please, extend your patch to
fix also the second place that has such error,
ip_vs_tunnel_xmit_v6. This call is missing from long time,
it was not needed. But commits that allow skb->sk (local
clients) already need it, eg.

- f2428ed5e7bc89c7 ("ipvs: load balance ipv6 connections from a local
process"), 2.6.28
- 4856c84c1358b798 ("ipvs: load balance IPv4 connections from a local 
process"), 2.6.28

> ---
>  net/netfilter/ipvs/ip_vs_xmit.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
> index 437a366..bd90bf8 100644
> --- a/net/netfilter/ipvs/ip_vs_xmit.c
> +++ b/net/netfilter/ipvs/ip_vs_xmit.c
> @@ -846,6 +846,8 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af,
>  		new_skb = skb_realloc_headroom(skb, max_headroom);
>  		if (!new_skb)
>  			goto error;
> +		if (skb->sk)
> +			skb_set_owner_w(new_skb, skb->sk);
>  		consume_skb(skb);
>  		skb = new_skb;
>  	}

Regards

--
Julian Anastasov <ja@ssi.bg>

^ permalink raw reply

* Re: [PATCH V1 net-next 5/5] net/mlx4_core: Add retrieval of CONFIG_DEV parameters
From: Or Gerlitz @ 2014-11-05  9:19 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David S. Miller, netdev, Matan Barak, Amir Vadai, Saeed Mahameed,
	Shani Michaeli, Ido Shamay
In-Reply-To: <1415119714.1005.3.camel@edumazet-glaptop2.roam.corp.google.com>

On 11/4/2014 6:48 PM, Eric Dumazet wrote:

> This added following warnings :
>
>    CC      drivers/net/ethernet/mellanox/mlx4/fw.o
> drivers/net/ethernet/mellanox/mlx4/fw.c: In function 'mlx4_config_dev_retrieval':
> drivers/net/ethernet/mellanox/mlx4/fw.c:1944:12: warning: 'config_dev.rx_checksum_val' may be used uninitialized in this function [-Wmaybe-uninitialized]
> In file included from include/linux/swab.h:4:0,
>                   from include/uapi/linux/byteorder/little_endian.h:12,
>                   from include/linux/byteorder/little_endian.h:4,
>                   from ./arch/x86/include/uapi/asm/byteorder.h:4,
>                   from include/asm-generic/bitops/le.h:5,
>                   from ./arch/x86/include/asm/bitops.h:504,
>                   from include/linux/bitops.h:33,
>                   from include/linux/kernel.h:10,
>                   from include/linux/skbuff.h:17,
>                   from include/linux/if_ether.h:23,
>                   from include/linux/etherdevice.h:25,
>                   from drivers/net/ethernet/mellanox/mlx4/fw.c:35:
> include/uapi/linux/swab.h:53:93: warning: 'config_dev.vxlan_udp_dport' may be used uninitialized in this function [-Wmaybe-uninitialized]
> drivers/net/ethernet/mellanox/mlx4/fw.c:1922:25: note: 'config_dev.vxlan_udp_dport' was declared here
>
>

Oh, missed that since we build with CONFIG_CC_OPTIMIZE_FOR_SIZE which 
for some reason cause the kernel Makefile to mask away that warning?!

> ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
> KBUILD_CFLAGS   += -Os $(call cc-disable-warning,maybe-uninitialized,)
> else
> KBUILD_CFLAGS   += -O2
> endif

Anyway, this seems as false positive since just before using the struct 
mlx4_config_dev instance we go through mlx4_CONFIG_DEV_get() which 
either fills in values for the fields or return error and in that case, 
we don't use them... the below patch makes gcc (4.8.2) happy, but it's 
not really needed... thoughts?

diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c 
b/drivers/net/ethernet/mellanox/mlx4/fw.c
index d6dba77..9a4703f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -1929,7 +1929,7 @@ int mlx4_config_dev_retrieval(struct mlx4_dev *dev,

         if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_CONFIG_DEV))
                 return -ENOTSUPP;
-
+       memset(&config_dev, 0, sizeof(config_dev));
         err = mlx4_CONFIG_DEV_get(dev, &config_dev);
         if (err)
                 return err;

Or.

^ permalink raw reply related

* RE: [PATCH net 5/5] qlcnic: Implement ndo_gso_check()
From: Shahed Shaikh @ 2014-11-05  9:17 UTC (permalink / raw)
  To: Joe Stringer, netdev
  Cc: sathya.perla@emulex.com, jeffrey.t.kirsher@intel.com,
	linux.nics@intel.com, amirv@mellanox.com, Dept-GE Linux NIC Dev,
	Tom Herbert (Partner - google), linux-kernel
In-Reply-To: <1415138202-1197-6-git-send-email-joestringer@nicira.com>

> -----Original Message-----
> From: Joe Stringer [mailto:joestringer@nicira.com]
> Sent: Wednesday, November 05, 2014 3:27 AM
> To: netdev
> Cc: sathya.perla@emulex.com; jeffrey.t.kirsher@intel.com;
> linux.nics@intel.com; amirv@mellanox.com; Shahed Shaikh; Dept-GE Linux
> NIC Dev; Tom Herbert (Partner - google); linux-kernel
> Subject: [PATCH net 5/5] qlcnic: Implement ndo_gso_check()
> 
> ndo_gso_check() was recently introduced to allow NICs to report the
> offloading support that they have on a per-skb basis. Add an implementation
> for this driver which checks for something that looks like VXLAN.
> 
> Implementation shamelessly stolen from Tom Herbert:
> http://thread.gmane.org/gmane.linux.network/332428/focus=333111
> 
> Signed-off-by: Joe Stringer <joestringer@nicira.com>
> ---
>  drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c |   12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
> b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
> index f5e29f7..6184f47 100644
> --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
> +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
> @@ -505,6 +505,17 @@ static void qlcnic_del_vxlan_port(struct net_device
> *netdev,  }  #endif
> 
> +static bool qlcnic_gso_check(struct sk_buff *skb, struct net_device
> +*dev) {
> +	if ((skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) &&
> +	    (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
> +	     skb->inner_protocol != htons(ETH_P_TEB) ||
> +	     skb_inner_mac_header(skb) - skb_transport_header(skb) != 16))
> +		return false;
> +

Hi Joe,

Yes, qlcnic driver only supports VXLAN offload.
It would be good to put a comment about value 16 to make it more intuitive. 
e.g. 16 is the size of outer UDP header + VXLAN header.

Anyway, patch looks good to me.

Acked-by: Shahed Shaikh <shahed.shaikh@qlogic.com>

Thanks,
Shahed

^ permalink raw reply

* Re: [PATCH] rtlwifi: Add more checks for get_btc_status callback
From: Mike Galbraith @ 2014-11-05  9:16 UTC (permalink / raw)
  To: Larry Finger
  Cc: Murilo Opsfelder Araujo, linux-kernel, linux-wireless, netdev,
	Chaoming Li, John W. Linville, Thadeu Cascardo, troy_tan
In-Reply-To: <5451BED0.2060906@lwfinger.net>

On Wed, 2014-10-29 at 23:30 -0500, Larry Finger wrote: 
> On 10/29/2014 06:28 PM, Murilo Opsfelder Araujo wrote:
> > This is a complement of commit 08054200117a95afc14c3d2ed3a38bf4e345bf78
> > "rtlwifi: Add check for get_btc_status callback".
> >
> > With this patch, next-20141029 at least does not panic with rtl8192se
> > device.
> >
> 
> This patch is OK, but as noted it is not complete.
> 
> I have patches to fix all the kernel panics for rtl8192se AND rtl8192ce. There 
> are missing parts, but I would prefer submitting mine, which would conflict with 
> this one. For that reason, NACK for this one, and please apply the set I am 
> submitting now.

It's all in there now, but my RTL8191SEvB is still dead.  Squabbling
with it isn't going all that well either.

As soon as 38506ece rtlwifi: rtl_pci: Start modification for new drivers
is applied, explosions appear.  Subsequently applying...

08054200 rtlwifi: Add check for get_btc_status callback
c0386f15 rtlwifi: rtl8192ce: rtl8192de: rtl8192se: Fix handling for missing get_btc_status
50147969 rtlwifi: rtl8192se: Fix duplicate calls to ieee80211_register_hw()
30c5ccc6 rtlwifi: rtl8192se: Add missing section to read descriptor setting
75a916e1 rtlwifi: rtl8192se: Fix firmware loading

...fixes that mess up, but leaves the interface dead in the same manner
as if nothing has been reverted.  So it _seems_ the bustage lurks in
38506ece somewhere.  Too bad it's non-dinky, and written in wifi-ese :)

-Mike

Full revert series: 
patches/revert-75a916e1944fea8347d2245c62567187e4eff9dd
patches/revert-8ae3c16e41b02db8ffe4121468519d6352baedc1
patches/revert-30c5ccc6afee39754cff75ad8d775ad39a2ce989
patches/revert-501479699ff484ba8acc1d07022271f00cfc55a3
patches/revert-c0386f1584127442d0f2aea41bc948056d6b1337
patches/revert-08054200117a95afc14c3d2ed3a38bf4e345bf78
patches/revert-4f2b244c7d5b81ce4f0c6c0382f3a3b7c2dbec1c
patches/revert-cefe3dfdb9f5f498cae9871f7e52800f5e22c614
patches/revert-b2d624a5810203a1a8b7735e1ec5685109b22fc3
patches/revert-d514aefb8ce89562ef2d7dcddc530e5de6287c4b
patches/revert-598a0df07fc6c4642f9b0497cef1233e41d4c987
patches/revert-47481d977cb2987ab363202c68a79ec1bccd357c
patches/revert-1fca350b761631d182c2e8bce530896e66404bc2
patches/revert-3f08e47291879fb047d7d4464d2beaedfea4eb63
patches/revert-989377e1cc9e713822d148d2e638d6c63d8a94b1
patches/revert-574a7930d7c4d0fe4295868e52a5277bd9595b5e
patches/revert-ef09396ef622572c604d4977e76f6151ef68ed21
patches/revert-557f933113a42a48ec617b81b5ea53fd7202b1ed
patches/revert-9f087a924427c01190b205f0051be00808c99828
patches/revert-5c99f04fec93068147a3e95b439b345f203ac5b9
patches/revert-0529c6b8176135bcae1ab66bed6c1288456fbdec
patches/revert-b1a3bfc97cd95681c511515534b84843998f3ea0
patches/revert-7fe3b3abb5da3a105d87640db693c41259138294
patches/revert-34ed780a6afc4df5e3285d20fac721c591e0724e
patches/revert-21e4b0726dc671c423e2dc9a85364716219c4502
patches/revert-c151aed6aa146e9587590051aba9da68b9370f9b
patches/revert-f3a97e93814aeac3f13e857a0071726acc9bd626
patches/revert-d3feae41a3473a0f7b431d6af4e092865d586e52
patches/revert-3c67b8f9f3b5bb1207c9bb198e5ef04ff56921dd
patches/revert-9afa2e44f4d8f9d031f815c32bb8f225f0f6746b
patches/revert-f7953b2ad66cc5fc66e13d5c0a40e61b45cdfca8
patches/revert-38506ecefab911785d5e1aa5889f6eeb462e0954
patches/revert-fd09ff958777cf583d7541f180991c0fc50bd2f7
patches/revert-560e334dbd9907ecdd25318fbdb33179c5d5a3bd
patches/revert-5eef40e5687da4ad0123e231e4fe952a12655f0b
patches/revert-6b5447ce630cdc231caf4f958325f8fa925216bf
patches/revert-dbb30ebeefaf01121b32ae6b5baf29524f3a0b30
patches/revert-4f4378dead3792d21577739f07869fbd843dab23
patches/revert-ed364abffd6e19bec67b7ccda8237213b8b37640
patches/revert-c96fd200e9af8ad4c4891ef579044a75c659d8c7
patches/revert-2ec7f01c35727574953dbd884d7d45da940a25ee
patches/revert-f5b5869095819970333dc9de54eed5c552407d35
patches/revert-2187e9a2ce575ee85a1ce31fa2ecbc0f580c105f
patches/revert-e8f3fef412d4ffd8cb1bd5cd7a6e5572e21bf80a
patches/revert-e79fff28587c9437282c863722d1fa186143f62a

^ permalink raw reply

* [PATCH V1 4/4] can: m_can: allow to send std frame on CAN FD mode
From: Dong Aisheng @ 2014-11-05  7:58 UTC (permalink / raw)
  To: linux-can
  Cc: mkl, wg, varkabhadram, netdev, socketcan, b29396,
	linux-arm-kernel
In-Reply-To: <1415174326-6623-1-git-send-email-b29396@freescale.com>

The current code sends all CAN frames on CAN FD format(with BRS or not)
if CAN_CTRLMODE_FD is enabled.
However, even CAN_CTRLMODE_FD is enabled, the can tool may still
send normal frames.
e.g.
ip link set can0 up type can bitrate 1000000 dbitrate 1000000 fd on
cansend can0 123#112233

Therefore sending normal CAN frame on FD format seems not reasonable
and the CAN FD incapable device may not be able to receive it correctly.

The patch switches the M_CAN operation mode to ISO11898-1 instead of
staying on CAN FD operation mode by writing "11" to CMR bit if find
we're sending a normal can skb.

Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
 drivers/net/can/m_can/m_can.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index f47c200..219c4b7 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -1080,10 +1080,14 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
 	if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
 		cccr = m_can_read(priv, M_CAN_CCCR);
 		cccr &= ~(CCCR_CMR_MASK << CCCR_CMR_SHIFT);
-		if (cf->flags & CANFD_BRS)
-			cccr |= CCCR_CMR_CANFD_BRS << CCCR_CMR_SHIFT;
-		else
-			cccr |= CCCR_CMR_CANFD << CCCR_CMR_SHIFT;
+		if (can_is_canfd_skb(skb)) {
+			if (cf->flags & CANFD_BRS)
+				cccr |= CCCR_CMR_CANFD_BRS << CCCR_CMR_SHIFT;
+			else
+				cccr |= CCCR_CMR_CANFD << CCCR_CMR_SHIFT;
+		} else {
+			cccr |= CCCR_CMR_CAN << CCCR_CMR_SHIFT;
+		}
 		m_can_write(priv, M_CAN_CCCR, cccr);
 	}
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH V1 3/4] can: add can_is_canfd_skb() API
From: Dong Aisheng @ 2014-11-05  7:58 UTC (permalink / raw)
  To: linux-can
  Cc: mkl, wg, varkabhadram, netdev, socketcan, b29396,
	linux-arm-kernel
In-Reply-To: <1415174326-6623-1-git-send-email-b29396@freescale.com>

The CAN device drivers can use it to check if the frame to send is on
CAN FD mode or normal CAN mode.

Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
 include/linux/can/dev.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 6992afc..fe3be29 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -99,6 +99,11 @@ inval_skb:
 	return 1;
 }
 
+static inline int can_is_canfd_skb(struct sk_buff *skb)
+{
+	return skb->protocol == htons(ETH_P_CANFD);
+}
+
 /* get data length from can_dlc with sanitized can_dlc */
 u8 can_dlc2len(u8 can_dlc);
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH V2 1/4] can: m_can: update to support CAN FD features
From: Dong Aisheng @ 2014-11-05  7:58 UTC (permalink / raw)
  To: linux-can
  Cc: mkl, wg, varkabhadram, netdev, socketcan, b29396,
	linux-arm-kernel

Bosch M_CAN is CAN FD capable device. This patch implements the CAN
FD features include up to 64 bytes payload and bitrate switch function.
1) Change the Rx FIFO and Tx Buffer to 64 bytes for support CAN FD
   up to 64 bytes payload. It's backward compatible with old 8 bytes
   normal CAN frame.
2) Allocate can frame or canfd frame based on EDL bit
3) Bitrate Switch function is disabled by default and will be enabled
   according to CANFD_BRS bit in cf->flags.

Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
Changes Since V1:
 * Allocate can frame or canfd frame based on EDL bit
 * Only check and set RTR bit for normal frame (no EDL bit set)
---
 drivers/net/can/m_can/m_can.c | 172 +++++++++++++++++++++++++++++++-----------
 1 file changed, 129 insertions(+), 43 deletions(-)

diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 6160b9c..664fe30 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -105,14 +105,36 @@ enum m_can_mram_cfg {
 	MRAM_CFG_NUM,
 };
 
+/* Fast Bit Timing & Prescaler Register (FBTP) */
+#define FBTR_FBRP_MASK		0x1f
+#define FBTR_FBRP_SHIFT		16
+#define FBTR_FTSEG1_SHIFT	8
+#define FBTR_FTSEG1_MASK	(0xf << FBTR_FTSEG1_SHIFT)
+#define FBTR_FTSEG2_SHIFT	4
+#define FBTR_FTSEG2_MASK	(0x7 << FBTR_FTSEG2_SHIFT)
+#define FBTR_FSJW_SHIFT		0
+#define FBTR_FSJW_MASK		0x3
+
 /* Test Register (TEST) */
 #define TEST_LBCK	BIT(4)
 
 /* CC Control Register(CCCR) */
-#define CCCR_TEST	BIT(7)
-#define CCCR_MON	BIT(5)
-#define CCCR_CCE	BIT(1)
-#define CCCR_INIT	BIT(0)
+#define CCCR_TEST		BIT(7)
+#define CCCR_CMR_MASK		0x3
+#define CCCR_CMR_SHIFT		10
+#define CCCR_CMR_CANFD		0x1
+#define CCCR_CMR_CANFD_BRS	0x2
+#define CCCR_CMR_CAN		0x3
+#define CCCR_CME_MASK		0x3
+#define CCCR_CME_SHIFT		8
+#define CCCR_CME_CAN		0
+#define CCCR_CME_CANFD		0x1
+#define CCCR_CME_CANFD_BRS	0x2
+#define CCCR_TEST		BIT(7)
+#define CCCR_MON		BIT(5)
+#define CCCR_CCE		BIT(1)
+#define CCCR_INIT		BIT(0)
+#define CCCR_CANFD		0x10
 
 /* Bit Timing & Prescaler Register (BTP) */
 #define BTR_BRP_MASK		0x3ff
@@ -204,6 +226,7 @@ enum m_can_mram_cfg {
 
 /* Rx Buffer / FIFO Element Size Configuration (RXESC) */
 #define M_CAN_RXESC_8BYTES	0x0
+#define M_CAN_RXESC_64BYTES	0x777
 
 /* Tx Buffer Configuration(TXBC) */
 #define TXBC_NDTB_OFF		16
@@ -211,6 +234,7 @@ enum m_can_mram_cfg {
 
 /* Tx Buffer Element Size Configuration(TXESC) */
 #define TXESC_TBDS_8BYTES	0x0
+#define TXESC_TBDS_64BYTES	0x7
 
 /* Tx Event FIFO Con.guration (TXEFC) */
 #define TXEFC_EFS_OFF		16
@@ -219,11 +243,11 @@ enum m_can_mram_cfg {
 /* Message RAM Configuration (in bytes) */
 #define SIDF_ELEMENT_SIZE	4
 #define XIDF_ELEMENT_SIZE	8
-#define RXF0_ELEMENT_SIZE	16
-#define RXF1_ELEMENT_SIZE	16
+#define RXF0_ELEMENT_SIZE	72
+#define RXF1_ELEMENT_SIZE	72
 #define RXB_ELEMENT_SIZE	16
 #define TXE_ELEMENT_SIZE	8
-#define TXB_ELEMENT_SIZE	16
+#define TXB_ELEMENT_SIZE	72
 
 /* Message RAM Elements */
 #define M_CAN_FIFO_ID		0x0
@@ -231,11 +255,17 @@ enum m_can_mram_cfg {
 #define M_CAN_FIFO_DATA(n)	(0x8 + ((n) << 2))
 
 /* Rx Buffer Element */
+/* R0 */
 #define RX_BUF_ESI		BIT(31)
 #define RX_BUF_XTD		BIT(30)
 #define RX_BUF_RTR		BIT(29)
+/* R1 */
+#define RX_BUF_ANMF		BIT(31)
+#define RX_BUF_EDL		BIT(21)
+#define RX_BUF_BRS		BIT(20)
 
 /* Tx Buffer Element */
+/* R0 */
 #define TX_BUF_XTD		BIT(30)
 #define TX_BUF_RTR		BIT(29)
 
@@ -327,41 +357,65 @@ static inline void m_can_disable_all_interrupts(const struct m_can_priv *priv)
 	m_can_write(priv, M_CAN_ILE, 0x0);
 }
 
-static void m_can_read_fifo(const struct net_device *dev, struct can_frame *cf,
-			    u32 rxfs)
+static void m_can_read_fifo(struct net_device *dev, u32 rxfs)
 {
+	struct net_device_stats *stats = &dev->stats;
 	struct m_can_priv *priv = netdev_priv(dev);
-	u32 id, fgi;
+	struct canfd_frame *cf;
+	struct sk_buff *skb;
+	u32 id, fgi, dlc;
+	int i;
 
 	/* calculate the fifo get index for where to read data */
 	fgi = (rxfs & RXFS_FGI_MASK) >> RXFS_FGI_OFF;
+	dlc = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC);
+	if (dlc & RX_BUF_EDL)
+		skb = alloc_canfd_skb(dev, &cf);
+	else
+		skb = alloc_can_skb(dev, (struct can_frame **)&cf);
+	if (!skb) {
+		stats->rx_dropped++;
+		return;
+	}
+
 	id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_ID);
 	if (id & RX_BUF_XTD)
 		cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG;
 	else
 		cf->can_id = (id >> 18) & CAN_SFF_MASK;
 
-	if (id & RX_BUF_RTR) {
+	if (id & RX_BUF_ESI) {
+		cf->flags |= CANFD_ESI;
+		netdev_dbg(dev, "ESI Error\n");
+	}
+
+	if (!(dlc & RX_BUF_EDL) && (id & RX_BUF_RTR)) {
 		cf->can_id |= CAN_RTR_FLAG;
 	} else {
 		id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC);
-		cf->can_dlc = get_can_dlc((id >> 16) & 0x0F);
-		*(u32 *)(cf->data + 0) = m_can_fifo_read(priv, fgi,
-							 M_CAN_FIFO_DATA(0));
-		*(u32 *)(cf->data + 4) = m_can_fifo_read(priv, fgi,
-							 M_CAN_FIFO_DATA(1));
+		cf->len = can_dlc2len(get_canfd_dlc((id >> 16) & 0x0F));
+
+		if (id & RX_BUF_BRS)
+			cf->flags |= CANFD_BRS;
+
+		for (i = 0; i < cf->len; i += 4)
+			*(u32 *)(cf->data + i) =
+				m_can_fifo_read(priv, fgi,
+						M_CAN_FIFO_DATA(i / 4));
 	}
 
 	/* acknowledge rx fifo 0 */
 	m_can_write(priv, M_CAN_RXF0A, fgi);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->len;
+
+	netif_receive_skb(skb);
 }
 
 static int m_can_do_rx_poll(struct net_device *dev, int quota)
 {
 	struct m_can_priv *priv = netdev_priv(dev);
-	struct net_device_stats *stats = &dev->stats;
-	struct sk_buff *skb;
-	struct can_frame *frame;
 	u32 pkts = 0;
 	u32 rxfs;
 
@@ -375,18 +429,7 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota)
 		if (rxfs & RXFS_RFL)
 			netdev_warn(dev, "Rx FIFO 0 Message Lost\n");
 
-		skb = alloc_can_skb(dev, &frame);
-		if (!skb) {
-			stats->rx_dropped++;
-			return pkts;
-		}
-
-		m_can_read_fifo(dev, frame, rxfs);
-
-		stats->rx_packets++;
-		stats->rx_bytes += frame->can_dlc;
-
-		netif_receive_skb(skb);
+		m_can_read_fifo(dev, rxfs);
 
 		quota--;
 		pkts++;
@@ -744,10 +787,23 @@ static const struct can_bittiming_const m_can_bittiming_const = {
 	.brp_inc = 1,
 };
 
+static const struct can_bittiming_const m_can_data_bittiming_const = {
+	.name = KBUILD_MODNAME,
+	.tseg1_min = 2,		/* Time segment 1 = prop_seg + phase_seg1 */
+	.tseg1_max = 16,
+	.tseg2_min = 1,		/* Time segment 2 = phase_seg2 */
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 32,
+	.brp_inc = 1,
+};
+
 static int m_can_set_bittiming(struct net_device *dev)
 {
 	struct m_can_priv *priv = netdev_priv(dev);
 	const struct can_bittiming *bt = &priv->can.bittiming;
+	const struct can_bittiming *dbt = &priv->can.data_bittiming;
 	u16 brp, sjw, tseg1, tseg2;
 	u32 reg_btp;
 
@@ -758,7 +814,17 @@ static int m_can_set_bittiming(struct net_device *dev)
 	reg_btp = (brp << BTR_BRP_SHIFT) | (sjw << BTR_SJW_SHIFT) |
 			(tseg1 << BTR_TSEG1_SHIFT) | (tseg2 << BTR_TSEG2_SHIFT);
 	m_can_write(priv, M_CAN_BTP, reg_btp);
-	netdev_dbg(dev, "setting BTP 0x%x\n", reg_btp);
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
+		brp = dbt->brp - 1;
+		sjw = dbt->sjw - 1;
+		tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1;
+		tseg2 = dbt->phase_seg2 - 1;
+		reg_btp = (brp << FBTR_FBRP_SHIFT) | (sjw << FBTR_FSJW_SHIFT) |
+				(tseg1 << FBTR_FTSEG1_SHIFT) |
+				(tseg2 << FBTR_FTSEG2_SHIFT);
+		m_can_write(priv, M_CAN_FBTP, reg_btp);
+	}
 
 	return 0;
 }
@@ -778,8 +844,8 @@ static void m_can_chip_config(struct net_device *dev)
 
 	m_can_config_endisable(priv, true);
 
-	/* RX Buffer/FIFO Element Size 8 bytes data field */
-	m_can_write(priv, M_CAN_RXESC, M_CAN_RXESC_8BYTES);
+	/* RX Buffer/FIFO Element Size 64 bytes data field */
+	m_can_write(priv, M_CAN_RXESC, M_CAN_RXESC_64BYTES);
 
 	/* Accept Non-matching Frames Into FIFO 0 */
 	m_can_write(priv, M_CAN_GFC, 0x0);
@@ -788,8 +854,8 @@ static void m_can_chip_config(struct net_device *dev)
 	m_can_write(priv, M_CAN_TXBC, (1 << TXBC_NDTB_OFF) |
 		    priv->mcfg[MRAM_TXB].off);
 
-	/* only support 8 bytes firstly */
-	m_can_write(priv, M_CAN_TXESC, TXESC_TBDS_8BYTES);
+	/* support 64 bytes payload */
+	m_can_write(priv, M_CAN_TXESC, TXESC_TBDS_64BYTES);
 
 	m_can_write(priv, M_CAN_TXEFC, (1 << TXEFC_EFS_OFF) |
 		    priv->mcfg[MRAM_TXE].off);
@@ -804,7 +870,8 @@ static void m_can_chip_config(struct net_device *dev)
 		    RXFC_FWM_1 | priv->mcfg[MRAM_RXF1].off);
 
 	cccr = m_can_read(priv, M_CAN_CCCR);
-	cccr &= ~(CCCR_TEST | CCCR_MON);
+	cccr &= ~(CCCR_TEST | CCCR_MON | (CCCR_CMR_MASK << CCCR_CMR_SHIFT) |
+		(CCCR_CME_MASK << CCCR_CME_SHIFT));
 	test = m_can_read(priv, M_CAN_TEST);
 	test &= ~TEST_LBCK;
 
@@ -816,6 +883,9 @@ static void m_can_chip_config(struct net_device *dev)
 		test |= TEST_LBCK;
 	}
 
+	if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
+		cccr |= CCCR_CME_CANFD_BRS << CCCR_CME_SHIFT;
+
 	m_can_write(priv, M_CAN_CCCR, cccr);
 	m_can_write(priv, M_CAN_TEST, test);
 
@@ -880,11 +950,13 @@ static struct net_device *alloc_m_can_dev(void)
 
 	priv->dev = dev;
 	priv->can.bittiming_const = &m_can_bittiming_const;
+	priv->can.data_bittiming_const = &m_can_data_bittiming_const;
 	priv->can.do_set_mode = m_can_set_mode;
 	priv->can.do_get_berr_counter = m_can_get_berr_counter;
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
 					CAN_CTRLMODE_LISTENONLY |
-					CAN_CTRLMODE_BERR_REPORTING;
+					CAN_CTRLMODE_BERR_REPORTING |
+					CAN_CTRLMODE_FD;
 
 	return dev;
 }
@@ -967,8 +1039,9 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
 				    struct net_device *dev)
 {
 	struct m_can_priv *priv = netdev_priv(dev);
-	struct can_frame *cf = (struct can_frame *)skb->data;
-	u32 id;
+	struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+	u32 id, cccr;
+	int i;
 
 	if (can_dropped_invalid_skb(dev, skb))
 		return NETDEV_TX_OK;
@@ -987,11 +1060,24 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
 
 	/* message ram configuration */
 	m_can_fifo_write(priv, 0, M_CAN_FIFO_ID, id);
-	m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, cf->can_dlc << 16);
-	m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0), *(u32 *)(cf->data + 0));
-	m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1), *(u32 *)(cf->data + 4));
+	m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, can_len2dlc(cf->len) << 16);
+
+	for (i = 0; i < cf->len; i += 4)
+		m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(i / 4),
+				 *(u32 *)(cf->data + i));
+
 	can_put_echo_skb(skb, dev, 0);
 
+	if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
+		cccr = m_can_read(priv, M_CAN_CCCR);
+		cccr &= ~(CCCR_CMR_MASK << CCCR_CMR_SHIFT);
+		if (cf->flags & CANFD_BRS)
+			cccr |= CCCR_CMR_CANFD_BRS << CCCR_CMR_SHIFT;
+		else
+			cccr |= CCCR_CMR_CANFD << CCCR_CMR_SHIFT;
+		m_can_write(priv, M_CAN_CCCR, cccr);
+	}
+
 	/* enable first TX buffer to start transfer  */
 	m_can_write(priv, M_CAN_TXBTIE, 0x1);
 	m_can_write(priv, M_CAN_TXBAR, 0x1);
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH] stmmac: fix sparse warnings
From: Andy Shevchenko @ 2014-11-05  9:03 UTC (permalink / raw)
  To: Giuseppe CAVALLARO
  Cc: netdev, Kweh Hock Leong, David S . Miller, Vince Bridgers
In-Reply-To: <54590045.3050305@st.com>

On Tue, 2014-11-04 at 17:35 +0100, Giuseppe CAVALLARO wrote:
> On 11/3/2014 6:28 PM, Andy Shevchenko wrote:
> > This patch fixes the following sparse warnings.
> >
> > drivers/net/ethernet/stmicro/stmmac/enh_desc.c:381:30: warning: symbol 'enh_desc_ops' was not declared. Should it be static?
> > drivers/net/ethernet/stmicro/stmmac/norm_desc.c:253:30: warning: symbol 'ndesc_ops' was not declared. Should it be static?
> > drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c:141:33: warning: symbol 'stmmac_ptp' was not declared. Should it be static?
> >
> > There is no functional change.
> 
> Hello Andy
> 
> I have never seen this kind of warnings. I prefer to not include the
> stmmac.h in enh_desc.c and norm_desc.c but eventually to move the
> following from stmmac.h to common.h:
>    extern const struct stmmac_desc_ops enh_desc_ops;
>    extern const struct stmmac_desc_ops ndesc_ops;
> what do you think?

If it would work I do this way certainly. Thanks for the tip.

Will check soon and resubmit new version.

> 
> peppe
> 
> 
> >
> > Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > ---
> >   drivers/net/ethernet/stmicro/stmmac/enh_desc.c        | 2 ++
> >   drivers/net/ethernet/stmicro/stmmac/norm_desc.c       | 2 ++
> >   drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 2 ++
> >   3 files changed, 6 insertions(+)
> >
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
> > index 1e2bcf5..ddd4272 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
> > @@ -23,8 +23,10 @@
> >   *******************************************************************************/
> >
> >   #include <linux/stmmac.h>
> > +
> >   #include "common.h"
> >   #include "descs_com.h"
> > +#include "stmmac.h"
> >
> >   static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
> >   				  struct dma_desc *p, void __iomem *ioaddr)
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
> > index 35ad4f4..46b882c 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
> > @@ -23,8 +23,10 @@
> >   *******************************************************************************/
> >
> >   #include <linux/stmmac.h>
> > +
> >   #include "common.h"
> >   #include "descs_com.h"
> > +#include "stmmac.h"
> >
> >   static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
> >   			       struct dma_desc *p, void __iomem *ioaddr)
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
> > index 76ad214..88e0da3 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
> > @@ -25,8 +25,10 @@
> >
> >   #include <linux/io.h>
> >   #include <linux/delay.h>
> > +
> >   #include "common.h"
> >   #include "stmmac_ptp.h"
> > +#include "stmmac.h"
> >
> >   static void stmmac_config_hw_tstamping(void __iomem *ioaddr, u32 data)
> >   {
> >
> 


-- 
Andy Shevchenko <andriy.shevchenko@intel.com>
Intel Finland Oy

^ permalink raw reply

* Bug#764162: [PATCH 0/1] mv643xx_eth: Disable TSO by default
From: Ian Campbell @ 2014-11-05  8:39 UTC (permalink / raw)
  To: Karl Beldan
  Cc: Ezequiel Garcia, netdev, David Miller, Thomas Petazzoni,
	Gregory Clement, Tawfik Bayouk, Lior Amsalem, Nadav Haklai,
	764162
In-Reply-To: <20141104142020.GA6728@magnum.frso.rivierawaves.com>

On Tue, 2014-11-04 at 15:20 +0100, Karl Beldan wrote:
> On Sat, Nov 01, 2014 at 12:30:19PM -0300, Ezequiel Garcia wrote:
> > Several users ([1], [2]) have been reporting data corruption with TSO on
> > Kirkwood platforms (i.e. using the mv643xx_eth driver).
> > 
> > Until we manage to find what's causing this, this simple patch will make
> > the TSO path disabled by default. This patch should be queued for stable,
> > fixing the TSO feature introduced in v3.16.
> > 
> > The corruption itself is very easy to reproduce: checking md5sum on a mounted
> > NFS directory gives a different result each time. Same tests using the mvneta
> > driver (Armada 370/38x/XP SoC) pass with no issues.
> > 
> > Frankly, I'm a bit puzzled about this, and so any ideas or debugging hints
> > are well received.
> > 
> 
> Hi,
> 
> Can you try this :

It fixes things for me, thanks!

Tested-by: Ian Campbell <ijc@hellion.org.uk>

> @@ -1067,7 +1082,8 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
>  		txq->tx_desc_count--;
>  
>  		skb = NULL;
> -		if (cmd_sts & TX_LAST_DESC)
> +		if ((cmd_sts & (TX_LAST_DESC | TX_ENABLE_INTERRUPT)) ==
> +			       (TX_LAST_DESC | TX_ENABLE_INTERRUPT))
>  			skb = __skb_dequeue(&txq->tx_skb);
>  
>  		if (cmd_sts & ERROR_SUMMARY) {
> 

^ permalink raw reply

* [PATCH RFC net] ip_tunnel: Respect the IP_DF bit of the inner packet.
From: Steffen Klassert @ 2014-11-05  8:09 UTC (permalink / raw)
  To: netdev

The pmtu calculation depends on the IP_DF bit in tnl_update_pmtu().
If the IP_DF bit is set, the pmtu calculation is based on the outer
packet size. Otherwise it is based on the inner packet size.
If xfrm is used after tunneling through an ipip device, the mtu of
the outer device can be lower than the mtu of the ipip device.
Reporting the mtu of the ipip device is wrong in this case. So
respect the IP_DF bit of the inner packet on ipv4 to report the
calculated mtu of the outer device.

Fixes: fd58156e456d ("IPIP: Use ip-tunneling code.")
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---

I marked this as RFC because it affects the mtu calculation of
gre tunnels too. I think it should be ok, but I have no testcase
to confirm the correctness for gre tunnels. So would be good if
someone with gre knowlegde could look at this.

If it turns out that we can't do that for gre, we need to
split this code back into a gre and an ipip version.

 net/ipv4/ip_tunnel.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 0bb8e14..f6f2d10 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -738,7 +738,11 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 		goto tx_error;
 	}
 
-	if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off)) {
+	df = tnl_params->frag_off;
+	if (skb->protocol == htons(ETH_P_IP))
+		df |= (inner_iph->frag_off&htons(IP_DF));
+
+	if (tnl_update_pmtu(dev, skb, rt, df)) {
 		ip_rt_put(rt);
 		goto tx_error;
 	}
@@ -767,10 +771,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 			ttl = ip4_dst_hoplimit(&rt->dst);
 	}
 
-	df = tnl_params->frag_off;
-	if (skb->protocol == htons(ETH_P_IP))
-		df |= (inner_iph->frag_off&htons(IP_DF));
-
 	max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
 			+ rt->dst.header_len + ip_encap_hlen(&tunnel->encap);
 	if (max_headroom > dev->needed_headroom)
-- 
1.9.1

^ permalink raw reply related

* [PATCH V2 2/4] can: m_can: workaround for transmit data less than 4 bytes
From: Dong Aisheng @ 2014-11-05  7:58 UTC (permalink / raw)
  To: linux-can
  Cc: mkl, wg, varkabhadram, netdev, socketcan, b29396,
	linux-arm-kernel
In-Reply-To: <1415174326-6623-1-git-send-email-b29396@freescale.com>

At least on the i.MX6SX with M_CAN IP version 3.0.x, an issue with
the Message RAM was discovered. Sending CAN frames with dlc less
than 4 bytes will lead to bit errors, when the first 8 bytes of
the Message RAM have not been initialized (i.e. written to).
To work around this issue, the first 8 bytes are initialized in open()
function.

Without the workaround, we can easily see the following errors:
root@imx6qdlsolo:~# ip link set can0 up type can bitrate 1000000
[   66.882520] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
root@imx6qdlsolo:~# cansend can0 123#112233
[   66.935640] m_can 20e8000.can can0: Bit Error Uncorrected

Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
ChangeLog since v1:
 * initialize the first 8 bytes of Tx Buffer of Message RAM in open()
   to workaround the issue
---
 drivers/net/can/m_can/m_can.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 664fe30..f47c200 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -902,6 +902,15 @@ static void m_can_chip_config(struct net_device *dev)
 	/* set bittiming params */
 	m_can_set_bittiming(dev);
 
+	/* At least on the i.MX6SX with M_CAN IP version 3.0.x, an issue with
+	 * the Message RAM was discovered. Sending CAN frames with dlc less
+	 * than 4 bytes will lead to bit errors, when the first 8 bytes of
+	 * the Message RAM have not been initialized (i.e. written to).
+	 * To work around this issue, the first 8 bytes are initialized here.
+	 */
+	m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0), 0x0);
+	m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1), 0x0);
+
 	m_can_config_endisable(priv, false);
 }
 
-- 
1.9.1


^ permalink raw reply related

* Re: [PATCH] net: eth: realtek: atp: checkpatch errors and warnings corrected
From: Roberto Medina @ 2014-11-05  7:44 UTC (permalink / raw)
  To: David Laight, Joe Perches
  Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6D1C9E71E4@AcuExch.aculab.com>

On 11/04/2014 11:19 AM, David Laight wrote:
>
> That code (and all the ones below) are gibberish, neither the old or new
> sequences make any sense.
>

Thank you for your feedback I did it again and objdiff doesn't show any 
changes (if I'm not mistaken).

> Almost as though you used the wrong instruction set!
>
> 	David

diff -Nurd 
/home/vov/Git/linux-next/.tmp_objdiff/a641d0e/drivers/net/ethernet/realtek/atp.dis 
/home/vov/Git/linux-next/.tmp_objdiff/5f19b70/drivers/net/ethernet/realtek/atp.dis
--- 
/home/vov/Git/linux-next/.tmp_objdiff/a641d0e/drivers/net/ethernet/realtek/atp.dis 
2014-11-05 08:38:49.244100507 +0100
+++ 
/home/vov/Git/linux-next/.tmp_objdiff/5f19b70/drivers/net/ethernet/realtek/atp.dis 
2014-11-05 08:39:14.654101606 +0100
@@ -1357,7 +1357,7 @@

  Disassembly of section .bss:

-00000000 <num_tx_since_rx.36127>:
+00000000 <num_tx_since_rx.36172>:
  :	00 00                	add    %al,(%eax)
  	...

Thanks,

Roberto

^ permalink raw reply

* Re: [PATCH] drivers: net: ethernet: xilinx: xilinx_emaclite: revert the original commit "1db3ddff1602edf2390b7667dcbaa0f71512e3ea"
From: Michal Simek @ 2014-11-05  7:19 UTC (permalink / raw)
  To: Chen Gang, michal.simek, soren.brinkmann, davem, sthokal,
	manuel.schoelling, f.fainelli, paul.gortmaker, ebiederm
  Cc: netdev, linux-kernel@vger.kernel.org
In-Reply-To: <5458E605.6070801@gmail.com>

On 11/04/2014 03:43 PM, Chen Gang wrote:
> Microblaze is a fpga soft core, it can be customized easily, which may
> cause many various hardware version strings.
> 
> So the original fix patch based on hard-coded compatible version strings
> is not a good idea (although it is correct for current issue). For it,
> there will be a new solving way soon (which based on the device tree).
> 
> The original issue is related with qemu, so can only change the hardware
> version string in qemu for it, then keep the original driver no touch (
> qemu is for virtualization which has much easier life than real world).
> 
> 
> Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
> ---
>  drivers/net/ethernet/xilinx/xilinx_emaclite.c | 1 -
>  1 file changed, 1 deletion(-)

Acked-by: Michal Simek <michal.simek@xilinx.com>

Thanks,
Michal

^ permalink raw reply

* [PATCH net-next 2/2] ip6_tunnel: Add support for wildcard tunnel endpoints.
From: Steffen Klassert @ 2014-11-05  7:03 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20141105070248.GC6390@secunet.com>

This patch adds support for tunnels with local or
remote wildcard endpoints. With this we get a
NBMA tunnel mode like we have it for ipv4 and
sit tunnels.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv6/ip6_tunnel.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index a8f94ff..4550d08 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -183,6 +183,7 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_
 	unsigned int hash = HASH(remote, local);
 	struct ip6_tnl *t;
 	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+	struct in6_addr any;
 
 	for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
 		if (ipv6_addr_equal(local, &t->parms.laddr) &&
@@ -190,6 +191,22 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_
 		    (t->dev->flags & IFF_UP))
 			return t;
 	}
+
+	memset(&any, 0, sizeof(any));
+	hash = HASH(&any, local);
+	for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
+		if (ipv6_addr_equal(local, &t->parms.laddr) &&
+		    (t->dev->flags & IFF_UP))
+			return t;
+	}
+
+	hash = HASH(remote, &any);
+	for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
+		if (ipv6_addr_equal(remote, &t->parms.raddr) &&
+		    (t->dev->flags & IFF_UP))
+			return t;
+	}
+
 	t = rcu_dereference(ip6n->tnls_wc[0]);
 	if (t && (t->dev->flags & IFF_UP))
 		return t;
@@ -979,7 +996,29 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
 	u8 proto;
 	int err = -1;
 
-	if (!fl6->flowi6_mark)
+	/* NBMA tunnel */
+	if (ipv6_addr_any(&t->parms.raddr)) {
+		struct in6_addr *addr6;
+		struct neighbour *neigh;
+		int addr_type;
+
+		if (!skb_dst(skb))
+			goto tx_err_link_failure;
+
+		neigh = dst_neigh_lookup(skb_dst(skb),
+					 &ipv6_hdr(skb)->daddr);
+		if (!neigh)
+			goto tx_err_link_failure;
+
+		addr6 = (struct in6_addr *)&neigh->primary_key;
+		addr_type = ipv6_addr_type(addr6);
+
+		if (addr_type == IPV6_ADDR_ANY)
+			addr6 = &ipv6_hdr(skb)->daddr;
+
+		memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
+		neigh_release(neigh);
+	} else if (!fl6->flowi6_mark)
 		dst = ip6_tnl_dst_check(t);
 
 	if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr))
-- 
1.9.1

^ permalink raw reply related

* [PATCH net-next 1/2] ipv6: Allow sending packets through tunnels with wildcard endpoints
From: Steffen Klassert @ 2014-11-05  7:02 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

Currently we need the IP6_TNL_F_CAP_XMIT capabiltiy to transmit
packets through an ipv6 tunnel. This capability is set when the
tunnel gets configured, based on the tunnel endpoint addresses.

On tunnels with wildcard tunnel endpoints, we need to do the
capabiltiy checking on a per packet basis like it is done in
the receive path.

This patch extends ip6_tnl_xmit_ctl() to take local and remote
addresses as parameters to allow for per packet capabiltiy
checking.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 include/net/ip6_tunnel.h |  3 ++-
 net/ipv6/ip6_gre.c       |  2 +-
 net/ipv6/ip6_tunnel.c    | 23 +++++++++++++++--------
 net/ipv6/ip6_vti.c       | 10 ++++++++--
 4 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index a5593da..9326c41 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -65,7 +65,8 @@ void ip6_tnl_dst_reset(struct ip6_tnl *t);
 void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst);
 int ip6_tnl_rcv_ctl(struct ip6_tnl *t, const struct in6_addr *laddr,
 		const struct in6_addr *raddr);
-int ip6_tnl_xmit_ctl(struct ip6_tnl *t);
+int ip6_tnl_xmit_ctl(struct ip6_tnl *t, const struct in6_addr *laddr,
+		     const struct in6_addr *raddr);
 __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw);
 __u32 ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr,
 			     const struct in6_addr *raddr);
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 12c3c8e..1fcf62e 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -902,7 +902,7 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
 	struct net_device_stats *stats = &t->dev->stats;
 	int ret;
 
-	if (!ip6_tnl_xmit_ctl(t))
+	if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr))
 		goto tx_err;
 
 	switch (skb->protocol) {
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 8c97cd1..a8f94ff 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -909,24 +909,28 @@ ip6_tnl_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr)
 	return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr);
 }
 
-int ip6_tnl_xmit_ctl(struct ip6_tnl *t)
+int ip6_tnl_xmit_ctl(struct ip6_tnl *t,
+		     const struct in6_addr *laddr,
+		     const struct in6_addr *raddr)
 {
 	struct __ip6_tnl_parm *p = &t->parms;
 	int ret = 0;
 	struct net *net = t->net;
 
-	if (p->flags & IP6_TNL_F_CAP_XMIT) {
+	if ((p->flags & IP6_TNL_F_CAP_XMIT) ||
+	    ((p->flags & IP6_TNL_F_CAP_PER_PACKET) &&
+	     (ip6_tnl_get_cap(t, laddr, raddr) & IP6_TNL_F_CAP_XMIT))) {
 		struct net_device *ldev = NULL;
 
 		rcu_read_lock();
 		if (p->link)
 			ldev = dev_get_by_index_rcu(net, p->link);
 
-		if (unlikely(!ipv6_chk_addr(net, &p->laddr, ldev, 0)))
+		if (unlikely(!ipv6_chk_addr(net, laddr, ldev, 0)))
 			pr_warn("%s xmit: Local address not yet configured!\n",
 				p->name);
-		else if (!ipv6_addr_is_multicast(&p->raddr) &&
-			 unlikely(ipv6_chk_addr(net, &p->raddr, NULL, 0)))
+		else if (!ipv6_addr_is_multicast(raddr) &&
+			 unlikely(ipv6_chk_addr(net, raddr, NULL, 0)))
 			pr_warn("%s xmit: Routing loop! Remote address found on this node!\n",
 				p->name);
 		else
@@ -977,6 +981,10 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
 
 	if (!fl6->flowi6_mark)
 		dst = ip6_tnl_dst_check(t);
+
+	if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr))
+		goto tx_err_link_failure;
+
 	if (!dst) {
 		ndst = ip6_route_output(net, NULL, fl6);
 
@@ -1086,8 +1094,7 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	int err;
 
 	tproto = ACCESS_ONCE(t->parms.proto);
-	if ((tproto != IPPROTO_IPIP && tproto != 0) ||
-	    !ip6_tnl_xmit_ctl(t))
+	if (tproto != IPPROTO_IPIP && tproto != 0)
 		return -1;
 
 	if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
@@ -1131,7 +1138,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	tproto = ACCESS_ONCE(t->parms.proto);
 	if ((tproto != IPPROTO_IPV6 && tproto != 0) ||
-	    !ip6_tnl_xmit_ctl(t) || ip6_tnl_addr_conflict(t, ipv6h))
+	    ip6_tnl_addr_conflict(t, ipv6h))
 		return -1;
 
 	offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index d440bb5..0e8e97e 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -416,6 +416,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
 	struct net_device_stats *stats = &t->dev->stats;
 	struct dst_entry *dst = skb_dst(skb);
 	struct net_device *tdev;
+	struct xfrm_state *x;
 	int err = -1;
 
 	if (!dst)
@@ -429,7 +430,12 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
 		goto tx_err_link_failure;
 	}
 
-	if (!vti6_state_check(dst->xfrm, &t->parms.raddr, &t->parms.laddr))
+	x = dst->xfrm;
+	if (!vti6_state_check(x, &t->parms.raddr, &t->parms.laddr))
+		goto tx_err_link_failure;
+
+	if (!ip6_tnl_xmit_ctl(t, (const struct in6_addr *)&x->props.saddr,
+			      (const struct in6_addr *)&x->id.daddr))
 		goto tx_err_link_failure;
 
 	tdev = dst->dev;
@@ -484,7 +490,7 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 		ipv6h = ipv6_hdr(skb);
 
 		if ((t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) ||
-		    !ip6_tnl_xmit_ctl(t) || vti6_addr_conflict(t, ipv6h))
+		    vti6_addr_conflict(t, ipv6h))
 			goto tx_err;
 
 		xfrm_decode_session(skb, &fl, AF_INET6);
-- 
1.9.1

^ permalink raw reply related

* How to make stack send broadcast ARP request when entry is STALE?
From: Ulf samuelsson @ 2014-11-05  6:48 UTC (permalink / raw)
  To: Netdev

Have a problem with an HP router at a certain location, which
is configured to only answer to broadcast ARP requests.
That cannot be changed.

The first ARP request the kernel sends out, is a broadcast request,
which is fine, but after the reply, the kernel sends unicast requests,
which will not get any replies.

The ARP entry will after some time enter STALE state,
and if nothing is done it will time out, and be removed.
This process takes to long, and I have been told that it is
difficult to makes changes that will eventually remove it.

Have tried to change the state from STALE to INCOMPLETE, which failed,
and then tried to change the state to PROBE which also failed.

The stack is only sending out unicasts, and never broadcast.
Is there any way to get the stack to send out a broadcast ARP
without having to wait for the entry to be removed?

I think the recommended behaviour in IPv6 is to send out 3 unicasts
and if all fails, to send out broadcasts.

Anyone know any good literature on how the ARP + neigh state machine works
in the kernel.

I read in Herberts book about the Linux TCP/IP stack and it only discuss how to reply to 
ARP requests and not anything on how to generate ARP requests.

Best Regards
Ulf Samuelsson

^ permalink raw reply

* Re: net: fec: fix regression on i.MX28 introduced by rx_copybreak support
From: Lothar Waßmann @ 2014-11-05  5:21 UTC (permalink / raw)
  To: David Miller
  Cc: fabio.estevam, Frank.Li, netdev, linux-kernel, rmk+kernel,
	linux-arm-kernel
In-Reply-To: <20141104.112858.356827532569349127.davem@davemloft.net>

Hi,

David Miller wrote:
> From: Lothar Waßmann <LW@KARO-electronics.de>
> Date: Tue, 4 Nov 2014 11:29:12 +0100
> 
> > Hi David,
> > 
> > Lothar Waßmann wrote:
> >> David Miller wrote:
> >> > From: Lothar Waßmann <LW@KARO-electronics.de>
> >> > Date: Thu, 30 Oct 2014 07:51:04 +0100
> >> > 
> >> > >> Also, I don't thnk your DIV_ROUND_UP() eliminate for the loop
> >> > >> in swap_buffer() is valid.  The whole point is that the current
> >> > >> code handles buffers which have a length which is not a multiple
> >> > >> of 4 properly, after your change it will no longer do so.
> >> > >>
> >> > > Do you really think so?
> >> > 
> >> > Yes, because you're rounding down so you'll miss the final
> >> > partial word (if any).
> >> >
> >> Nope. DIV_ROUND_UP() would give '1' as upper bound for lengths from 1 to
> >> 4, '2' for lengths from 5 to 8 and so on.
> >> 
> >> The loop with increment 4 and i < len does exactly the same.
> >> Try it for yourself, if you don't believe it.
> >> 
> >> 
> > Do you still think, the loop without DIV_ROUND_UP() is incorrect,
> > or can this patch be applied?
> 
> I haven't had the time to fully re-look into the details, I'm busy
> with many other things at the moment.
> 
> But looking at DIV_ROUND_UP() macro it rounds up.  It gives an
> upper bound of 4 for any value 1 to 4.  Unlike what you claim.
> 
You're missing the 'DIV' part of DIV_ROUND_UP().

> Because it goes "(n + (d - 1)) / d"
> 
> Which for 'd' of 4 gives:
> 
> 1 --> 4
> 2 --> 4
> 3 --> 4
> 4 --> 4
>
'1', not '4'.
The loop has to be done once for each (probably partial) WORD of input
data, not for each BYTE.

Without dividing and incrementing by four the loop
counter will be 0 for the first word which is less than any length > 0.
Thus the loop will be run once for any number of bytes from 1 thru 4.
If incremented by 4 after the first loop, it will be run again for any
length > 5 and so forth.


Lothar Waßmann
-- 
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Geschäftsführer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info@karo-electronics.de
___________________________________________________________

^ permalink raw reply

* Re: [PATCH 1/4] inet: Add skb_copy_datagram_iter
From: Al Viro @ 2014-11-05  4:12 UTC (permalink / raw)
  To: David Miller; +Cc: herbert, netdev, linux-kernel, bcrl
In-Reply-To: <20141105035536.GO7996@ZenIV.linux.org.uk>

On Wed, Nov 05, 2014 at 03:55:36AM +0000, Al Viro wrote:
> What do you think of the trick with user_msghdr, BTW?

	PS: where do you prefer the branches to be based off?
git://git.kernel.org/pub/scm/linux/kernel/git/davem/net#master, mainline,
something else?  I can certainly do that as patches over email, the
question is what's best used as base...  FWIW, the analysis I've posted
was in 3.18-rc3 and it looks like it ought to be valid in net#master
as well.

^ permalink raw reply

* Re: [PATCH 1/4] inet: Add skb_copy_datagram_iter
From: Al Viro @ 2014-11-05  3:55 UTC (permalink / raw)
  To: David Miller; +Cc: herbert, netdev, linux-kernel, bcrl
In-Reply-To: <20141104.222727.275422581392488793.davem@davemloft.net>

On Tue, Nov 04, 2014 at 10:27:27PM -0500, David Miller wrote:

> Al, is this the helper you are talking about?

Mostly, except that I kept it 4-argument (and used skb_copy_datagram_msg()
for name).  Matter of taste - the ones you've missed because of that are

net/appletalk/ddp.c:1761:	err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied);
net/ipv4/tcp.c:1836:			err = skb_copy_datagram_iovec(skb, offset,
net/ipv4/udp.c:1284:		err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
net/ipv6/udp.c:427:			err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
net/ipx/af_ipx.c:1808:	rc = skb_copy_datagram_iovec(skb, sizeof(struct ipxhdr), msg->msg_iov,
net/iucv/af_iucv.c:1358:	if (skb_copy_datagram_iovec(cskb, offset, msg->msg_iov, copied)) {
net/llc/af_llc.c:822:			int rc = skb_copy_datagram_iovec(skb, offset,
net/rxrpc/ar-recvmsg.c:183:		ret = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copy);
net/tipc/socket.c:1375:		res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg),
net/tipc/socket.c:1476:		res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg) + offset,
net/unix/af_unix.c:1828:	err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size);
net/unix/af_unix.c:2033:		if (skb_copy_datagram_iovec(skb, UNIXCB(skb).consumed + skip,
net/vmw_vsock/vmci_transport.c:1776:	err = skb_copy_datagram_iovec(skb, sizeof(*dg), msg->msg_iov,

and back then I decided that 13 more converted instances might be worth keeping
it in 4-argument form...

What do you think of the trick with user_msghdr, BTW?

^ permalink raw reply

* Re: [PATCH 02/13] net_sched: introduce qdisc_peek() helper function
From: Herbert Xu @ 2014-11-05  3:49 UTC (permalink / raw)
  To: Cong Wang; +Cc: stephen, netdev
In-Reply-To: <CAM_iQpXj6Pk3moYVKzj8YhmPz74fBgvVt4RxRMgW=+-p5MKnEg@mail.gmail.com>

Cong Wang <xiyou.wangcong@gmail.com> wrote:
> On Tue, Nov 4, 2014 at 10:45 AM, Stephen Hemminger
> <stephen@networkplumber.org> wrote:
>> On Tue,  4 Nov 2014 09:56:25 -0800
>> Cong Wang <xiyou.wangcong@gmail.com> wrote:
>>
>>> +static inline void qdisc_warn_nonwc(void *func, struct Qdisc *qdisc)
>>> +{
>>> +     if (!(qdisc->flags & TCQ_F_WARN_NONWC)) {
>>> +             pr_warn("%pf: %s qdisc %X: is non-work-conserving?\n",
>>> +                     func, qdisc->ops->id, qdisc->handle >> 16);
>>> +             qdisc->flags |= TCQ_F_WARN_NONWC;
>>> +     }
>>> +}
>>> +
>>
>> Inilining this and creating N copies of same message is not a step forward.
> 
> Hmm, I think gcc merges same string literals when building Linux kernel?
> But I never verify this.

In general you should try to avoid inlining code that's not in
the fast path as that leads to binary code size bloat.  As errors
shouldn't be in the fast path this function should be inlined.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [PATCH 2/4] tun: Use iovec iterators
From: Herbert Xu @ 2014-11-05  3:41 UTC (permalink / raw)
  To: YOSHIFUJI Hideaki
  Cc: viro, davem, netdev, linux-kernel, bcrl, hideaki.yoshifuji
In-Reply-To: <5459902C.1010102@miraclelinux.com>

YOSHIFUJI Hideaki <hideaki.yoshifuji@miraclelinux.com> wrote:
>>
>> -             if (len < skb->len + vlan_hlen + vnet_hdr_sz) {
>> +             if (iov_iter_count(iter) < total) {
> 
> I guess this should be: sizeof(pi) + total

Good catch! Here is a third update:

tun: Use iovec iterators

This patch removes the use of skb_copy_datagram_const_iovec in
favour of the iovec iterator-based skb_copy_datagram_iter.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 9dd3746..b4ac4d5 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -71,6 +71,7 @@
 #include <net/rtnetlink.h>
 #include <net/sock.h>
 #include <linux/seq_file.h>
+#include <linux/uio.h>
 
 #include <asm/uaccess.h>
 
@@ -1230,11 +1231,11 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
 static ssize_t tun_put_user(struct tun_struct *tun,
 			    struct tun_file *tfile,
 			    struct sk_buff *skb,
-			    const struct iovec *iv, int len)
+			    struct iov_iter *iter)
 {
 	struct tun_pi pi = { 0, skb->protocol };
-	ssize_t total = 0;
-	int vlan_offset = 0, copied;
+	ssize_t total;
+	int vlan_offset;
 	int vlan_hlen = 0;
 	int vnet_hdr_sz = 0;
 
@@ -1244,23 +1245,25 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 	if (tun->flags & TUN_VNET_HDR)
 		vnet_hdr_sz = tun->vnet_hdr_sz;
 
+	total = skb->len + vlan_hlen + vnet_hdr_sz;
+
 	if (!(tun->flags & TUN_NO_PI)) {
-		if ((len -= sizeof(pi)) < 0)
+		if (iov_iter_count(iter) < sizeof(pi))
 			return -EINVAL;
 
-		if (len < skb->len + vlan_hlen + vnet_hdr_sz) {
+		total += sizeof(pi);
+		if (iov_iter_count(iter) < total) {
 			/* Packet will be striped */
 			pi.flags |= TUN_PKT_STRIP;
 		}
 
-		if (memcpy_toiovecend(iv, (void *) &pi, 0, sizeof(pi)))
+		if (copy_to_iter(&pi, sizeof(pi), iter))
 			return -EFAULT;
-		total += sizeof(pi);
 	}
 
 	if (vnet_hdr_sz) {
 		struct virtio_net_hdr gso = { 0 }; /* no info leak */
-		if ((len -= vnet_hdr_sz) < 0)
+		if (iov_iter_count(iter) < vnet_hdr_sz)
 			return -EINVAL;
 
 		if (skb_is_gso(skb)) {
@@ -1299,17 +1302,12 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 			gso.flags = VIRTIO_NET_HDR_F_DATA_VALID;
 		} /* else everything is zero */
 
-		if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total,
-					       sizeof(gso))))
+		if (copy_to_iter(&gso, sizeof(gso), iter))
 			return -EFAULT;
-		total += vnet_hdr_sz;
 	}
 
-	copied = total;
-	len = min_t(int, skb->len + vlan_hlen, len);
-	total += skb->len + vlan_hlen;
 	if (vlan_hlen) {
-		int copy, ret;
+		int ret;
 		struct {
 			__be16 h_vlan_proto;
 			__be16 h_vlan_TCI;
@@ -1320,36 +1318,32 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 
 		vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
 
-		copy = min_t(int, vlan_offset, len);
-		ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
-		len -= copy;
-		copied += copy;
-		if (ret || !len)
+		ret = skb_copy_datagram_iter(skb, 0, iter, vlan_offset);
+		if (ret || !iov_iter_count(iter))
 			goto done;
 
-		copy = min_t(int, sizeof(veth), len);
-		ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy);
-		len -= copy;
-		copied += copy;
-		if (ret || !len)
+		ret = copy_to_iter(&veth, sizeof(veth), iter);
+		if (ret || !iov_iter_count(iter))
 			goto done;
 	}
 
-	skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
+	skb_copy_datagram_iter(skb, vlan_offset, iter, skb->len - vlan_offset);
 
 done:
 	tun->dev->stats.tx_packets++;
-	tun->dev->stats.tx_bytes += len;
+	tun->dev->stats.tx_bytes += skb->len + vlan_hlen;
 
 	return total;
 }
 
 static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
-			   const struct iovec *iv, ssize_t len, int noblock)
+			   const struct iovec *iv, unsigned long segs,
+			   ssize_t len, int noblock)
 {
 	struct sk_buff *skb;
 	ssize_t ret = 0;
 	int peeked, err, off = 0;
+	struct iov_iter iter;
 
 	tun_debug(KERN_INFO, tun, "tun_do_read\n");
 
@@ -1362,11 +1356,12 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
 	/* Read frames from queue */
 	skb = __skb_recv_datagram(tfile->socket.sk, noblock ? MSG_DONTWAIT : 0,
 				  &peeked, &off, &err);
-	if (skb) {
-		ret = tun_put_user(tun, tfile, skb, iv, len);
-		kfree_skb(skb);
-	} else
-		ret = err;
+	if (!skb)
+		return ret;
+
+	iov_iter_init(&iter, READ, iv, segs, len);
+	ret = tun_put_user(tun, tfile, skb, &iter);
+	kfree_skb(skb);
 
 	return ret;
 }
@@ -1387,7 +1382,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
 		goto out;
 	}
 
-	ret = tun_do_read(tun, tfile, iv, len,
+	ret = tun_do_read(tun, tfile, iv, count, len,
 			  file->f_flags & O_NONBLOCK);
 	ret = min_t(ssize_t, ret, len);
 	if (ret > 0)
@@ -1488,7 +1483,7 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
 					 SOL_PACKET, TUN_TX_TIMESTAMP);
 		goto out;
 	}
-	ret = tun_do_read(tun, tfile, m->msg_iov, total_len,
+	ret = tun_do_read(tun, tfile, m->msg_iov, m->msg_iovlen, total_len,
 			  flags & MSG_DONTWAIT);
 	if (ret > total_len) {
 		m->msg_flags |= MSG_TRUNC;

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply related

* Re: [PATCH 1/4] inet: Add skb_copy_datagram_iter
From: David Miller @ 2014-11-05  3:27 UTC (permalink / raw)
  To: herbert; +Cc: viro, netdev, linux-kernel, bcrl
In-Reply-To: <20141105022251.GA19136@gondor.apana.org.au>

From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Wed, 5 Nov 2014 10:22:51 +0800

> On Tue, Nov 04, 2014 at 03:13:55PM +0000, Al Viro wrote:
>> 
>> Think of it that way: every sendmsg/recvmsg path leading to memcpy_fromiovec
>> and its friends (including the open-coded ones) would need to be changed
>> at some point.  Assuming we do not end up passing struct iov_iter * as
>> an extra argument through a fairly large part of net/* (and that would
>> be prohibitively hard and messy, not to mention the effects on the stack
>> footprint, etc.), the most obvious strategy is to have that thing passed
>> where msg_iov/msg_iovlen are - in struct msghdr.  *IF* we go that way,
>> it makes a whole lot of sense to start with a bunch of cleanups that
>> will make sense on their own (most of callers of skb_copy_datagram_iovec
>> do look like skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); might
>> as well give it an inlined helper) and will reduce the amount of places
>> where ->msg_iov is used.  With such cleanups standing on their own and
>> being splittable from the rest of the queue.  And leaving us with fewer
>> places in code that deal with ->msg_iov and need to be dealt with.
> 
> I think your solution is great.  However, I don't see how my four
> patches impede in anyway the work that you're doing.  I presume
> your first patch will make skb_copy_datagram_msg just a wrapper
> around skb_copy_datagram_iovec.
> 
> Since I'm not removing skb_copy_datagram_iovec (it can't be removed
> until all users are gone) you can still do that and when you're
> ready to switch over to iov_iter you can just move the wrapper over
> to skb_copy_datagram_iter.  No?

Agreed, I think both efforts can proceed in parallel.

Al, is this the helper you are talking about?

diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index 1be8228..a08057d 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -163,7 +163,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 	memcpy(skb_push(skb, MISDN_HEADER_LEN), mISDN_HEAD_P(skb),
 	       MISDN_HEADER_LEN);
 
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 
 	mISDN_sock_cmsg(sk, msg, skb);
 
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index 6c9c16d..25234d9 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -981,7 +981,7 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
 
 	if (skb) {
 		total_len = min_t(size_t, total_len, skb->len);
-		error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);
+		error = skb_copy_datagram_msghdr(skb, m, total_len);
 		if (error == 0) {
 			consume_skb(skb);
 			return total_len;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 5ad9675..19fe8cc 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/kmemcheck.h>
 #include <linux/compiler.h>
+#include <linux/socket.h>
 #include <linux/time.h>
 #include <linux/bug.h>
 #include <linux/cache.h>
@@ -2637,6 +2638,11 @@ unsigned int datagram_poll(struct file *file, struct socket *sock,
 			   struct poll_table_struct *wait);
 int skb_copy_datagram_iovec(const struct sk_buff *from, int offset,
 			    struct iovec *to, int size);
+static inline int skb_copy_datagram_msghdr(const struct sk_buff *from,
+					   struct msghdr *msg, int size)
+{
+	return skb_copy_datagram_iovec(from, 0, msg->msg_iov, size);
+}
 int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen,
 				     struct iovec *iov);
 int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset,
diff --git a/net/atm/common.c b/net/atm/common.c
index 6a76515..7e42bbe 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -554,7 +554,7 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
 		msg->msg_flags |= MSG_TRUNC;
 	}
 
-	error = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	error = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (error)
 		return error;
 	sock_recv_ts_and_drops(msg, sk, skb);
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index c35c3f4..a91075c 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1634,7 +1634,7 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
 		msg->msg_flags |= MSG_TRUNC;
 	}
 
-	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	skb_copy_datagram_msghdr(skb, msg, copied);
 
 	if (msg->msg_name) {
 		ax25_digi digi;
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 339c74a..a68dd75 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -237,7 +237,7 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 	}
 
 	skb_reset_transport_header(skb);
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err == 0) {
 		sock_recv_ts_and_drops(msg, sk, skb);
 
@@ -328,7 +328,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 		}
 
 		chunk = min_t(unsigned int, skb->len, size);
-		if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, chunk)) {
+		if (skb_copy_datagram_msghdr(skb, msg, chunk)) {
 			skb_queue_head(&sk->sk_receive_queue, skb);
 			if (!copied)
 				copied = -EFAULT;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 115f149..45d4fba 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -878,7 +878,7 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 	}
 
 	skb_reset_transport_header(skb);
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 
 	switch (hci_pi(sk)->channel) {
 	case HCI_CHANNEL_RAW:
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 43f750e..67e63b6 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -293,7 +293,7 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
 		copylen = len;
 	}
 
-	ret = skb_copy_datagram_iovec(skb, 0, m->msg_iov, copylen);
+	ret = skb_copy_datagram_msghdr(skb, m, copylen);
 	if (ret)
 		goto out_free;
 
diff --git a/net/core/sock.c b/net/core/sock.c
index 15e0c67..220c791 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2457,7 +2457,7 @@ int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
 		msg->msg_flags |= MSG_TRUNC;
 		copied = len;
 	}
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err)
 		goto out_free_skb;
 
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 5ab6627..7ccf58f 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -896,7 +896,7 @@ verify_sock_status:
 		else if (len < skb->len)
 			msg->msg_flags |= MSG_TRUNC;
 
-		if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len)) {
+		if (skb_copy_datagram_msghdr(skb, msg, len)) {
 			/* Exception. Bailout! */
 			len = -EFAULT;
 			break;
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
index ef2ad8a..7017055 100644
--- a/net/ieee802154/dgram.c
+++ b/net/ieee802154/dgram.c
@@ -324,7 +324,7 @@ static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk,
 	}
 
 	/* FIXME: skip headers if necessary ?! */
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err)
 		goto done;
 
diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c
index 9d1f648..5dd893a 100644
--- a/net/ieee802154/raw.c
+++ b/net/ieee802154/raw.c
@@ -195,7 +195,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		copied = len;
 	}
 
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err)
 		goto done;
 
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index c373a9a..d643882 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -424,7 +424,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 		msg->msg_flags |= MSG_TRUNC;
 		copied = len;
 	}
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err)
 		goto out_free_skb;
 
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 57f7c98..a6e0197 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -875,7 +875,7 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 	}
 
 	/* Don't bother checking the checksum */
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err)
 		goto done;
 
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 739db31..2f4bb30 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -718,7 +718,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		copied = len;
 	}
 
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err)
 		goto done;
 
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 39ec0c3..3638679 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1377,7 +1377,7 @@ static int tcp_peek_sndq(struct sock *sk, struct msghdr *msg, int len)
 	/* XXX -- need to support SO_PEEK_OFF */
 
 	skb_queue_walk(&sk->sk_write_queue, skb) {
-		err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, skb->len);
+		err = skb_copy_datagram_msghdr(skb, msg, skb->len);
 		if (err)
 			break;
 
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 2cdc383..4bd84fd 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -351,7 +351,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 		msg->msg_flags |= MSG_TRUNC;
 		copied = len;
 	}
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err)
 		goto out_free_skb;
 
@@ -445,7 +445,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
 		msg->msg_flags |= MSG_TRUNC;
 		copied = len;
 	}
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err)
 		goto out_free_skb;
 
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 075a0fb..5d37aa1 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -486,11 +486,11 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
 	}
 
 	if (skb_csum_unnecessary(skb)) {
-		err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+		err = skb_copy_datagram_msghdr(skb, msg, copied);
 	} else if (msg->msg_flags&MSG_TRUNC) {
 		if (__skb_checksum_complete(skb))
 			goto csum_copy_err;
-		err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+		err = skb_copy_datagram_msghdr(skb, msg, copied);
 	} else {
 		err = skb_copy_and_csum_datagram_iovec(skb, 0, msg->msg_iov);
 		if (err == -EINVAL)
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 92fafd4..54db6dc 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -1396,7 +1396,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
 		copied = size;
 		msg->msg_flags |= MSG_TRUNC;
 	}
-	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	skb_copy_datagram_msghdr(skb, msg, copied);
 
 	skb_free_datagram(sk, skb);
 
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 1847ec4..f09a848 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -3654,7 +3654,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
 	}
 
 	skb_reset_transport_header(skb);
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err)
 		goto out_free;
 
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 369a982..2913198 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -528,7 +528,7 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
 		copied = len;
 	}
 
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err)
 		goto done;
 
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index 0edb263..8613881 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -672,7 +672,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,
 		copied = len;
 	}
 
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err)
 		goto done;
 
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index b704a93..5f3c0f5 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -208,7 +208,7 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock,
 	else if (len < skb->len)
 		msg->msg_flags |= MSG_TRUNC;
 
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len);
+	err = skb_copy_datagram_msghdr(skb, msg, len);
 	if (likely(err == 0))
 		err = len;
 
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index f1de72d..123cffd 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2401,7 +2401,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
 	}
 
 	skb_reset_transport_header(data_skb);
-	err = skb_copy_datagram_iovec(data_skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(data_skb, msg, copied);
 
 	if (msg->msg_name) {
 		DECLARE_SOCKADDR(struct sockaddr_nl *, addr, msg->msg_name);
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 1b06a1f..6bc3556 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1167,7 +1167,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
 		msg->msg_flags |= MSG_TRUNC;
 	}
 
-	er = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	er = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (er < 0) {
 		skb_free_datagram(sk, skb);
 		release_sock(sk);
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
index 51f077a..e962c07 100644
--- a/net/nfc/llcp_sock.c
+++ b/net/nfc/llcp_sock.c
@@ -832,7 +832,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 	copied = min_t(unsigned int, rlen, len);
 
 	cskb = skb;
-	if (skb_copy_datagram_iovec(cskb, 0, msg->msg_iov, copied)) {
+	if (skb_copy_datagram_msghdr(cskb, msg, copied)) {
 		if (!(flags & MSG_PEEK))
 			skb_queue_head(&sk->sk_receive_queue, skb);
 		return -EFAULT;
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
index 11c3544..4467b2c 100644
--- a/net/nfc/rawsock.c
+++ b/net/nfc/rawsock.c
@@ -269,7 +269,7 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock,
 		copied = len;
 	}
 
-	rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	rc = skb_copy_datagram_msghdr(skb, msg, copied);
 
 	skb_free_datagram(sk, skb);
 
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 87d20f4..390b776 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2953,7 +2953,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
 		msg->msg_flags |= MSG_TRUNC;
 	}
 
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (err)
 		goto out_free;
 
diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c
index 290352c..b4835bc 100644
--- a/net/phonet/datagram.c
+++ b/net/phonet/datagram.c
@@ -150,7 +150,7 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk,
 		copylen = len;
 	}
 
-	rval = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copylen);
+	rval = skb_copy_datagram_msghdr(skb, msg, copylen);
 	if (rval) {
 		rval = -EFAULT;
 		goto out;
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index 70a547e..f544658 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -1296,7 +1296,7 @@ copy:
 	else
 		len = skb->len;
 
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len);
+	err = skb_copy_datagram_msghdr(skb, msg, len);
 	if (!err)
 		err = (flags & MSG_TRUNC) ? skb->len : len;
 
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index a85c1a0..b660504 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1249,7 +1249,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
 		msg->msg_flags |= MSG_TRUNC;
 	}
 
-	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	skb_copy_datagram_msghdr(skb, msg, copied);
 
 	if (msg->msg_name) {
 		struct sockaddr_rose *srose;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 634a2ab..0fca34c 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2095,7 +2095,7 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
 	if (copied > len)
 		copied = len;
 
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	err = skb_copy_datagram_msghdr(skb, msg, copied);
 
 	event = sctp_skb2event(skb);
 
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 5ad4418..fad0702 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -1335,7 +1335,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
 	/* Currently, each datagram always contains a complete record */
 	msg->msg_flags |= MSG_EOR;
 
-	rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	rc = skb_copy_datagram_msghdr(skb, msg, copied);
 	if (rc)
 		goto out_free_dgram;
 

^ permalink raw reply related

* Re: [PATCH 2/4] tun: Use iovec iterators
From: YOSHIFUJI Hideaki @ 2014-11-05  2:49 UTC (permalink / raw)
  To: Herbert Xu, Al Viro, David S. Miller, netdev,
	Linux Kernel Mailing List, Benjamin LaHaise
  Cc: hideaki.yoshifuji
In-Reply-To: <20141104083721.GA12691@gondor.apana.org.au>

Hi,

Herbert Xu wrote:
> Oops, this patch had a left-over skb_pull which made it broken.
> Here is a fixed version.
>
> tun: Use iovec iterators
>
> This patch removes the use of skb_copy_datagram_const_iovec in
> favour of the iovec iterator-based skb_copy_datagram_iter.
>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
>
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index 9dd3746..ff955cdb 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
:
> @@ -1244,23 +1245,25 @@ static ssize_t tun_put_user(struct tun_struct *tun,
>   	if (tun->flags & TUN_VNET_HDR)
>   		vnet_hdr_sz = tun->vnet_hdr_sz;
>
> +	total = skb->len + vlan_hlen + vnet_hdr_sz;
> +
>   	if (!(tun->flags & TUN_NO_PI)) {
> -		if ((len -= sizeof(pi)) < 0)
> +		if (iov_iter_count(iter) < sizeof(pi))
>   			return -EINVAL;
>
> -		if (len < skb->len + vlan_hlen + vnet_hdr_sz) {
> +		if (iov_iter_count(iter) < total) {

I guess this should be: sizeof(pi) + total

-- 
Hideaki Yoshifuji <hideaki.yoshifuji@miraclelinux.com>
Technical Division, MIRACLE LINUX CORPORATION

^ 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