Patch "net: cdc_ncm: avoid changing RX/TX buffers on MTU changes" has been added to the 4.1-stable tree
Subsystems (5)
This is a note to let you know that I've just added the patch titled
net: cdc_ncm: avoid changing RX/TX buffers on MTU changes
to the 4.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
net-cdc_ncm-avoid-changing-rx-tx-buffers-on-mtu-changes.patch
and it can be found in the queue-4.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Tue Jan 26 21:37:04 PST 2016
From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <[email protected]>
Date: Wed, 23 Dec 2015 13:42:43 +0100
Subject: net: cdc_ncm: avoid changing RX/TX buffers on MTU changes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <[email protected]>
[ Upstream commit 1dfddff5fcd869fcab0c52fafae099dfa435a935 ]
NCM buffer sizes are negotiated with the device independently of the network device MTU. The RX buffers are allocated by the usbnet framework based on the rx_urb_size value set by cdc_ncm. A single RX buffer can hold a number of MTU sized packets.
The default usbnet change_mtu ndo only modifies rx_urb_size if it is equal to hard_mtu. And the cdc_ncm driver will set rx_urb_size and hard_mtu independently of each other, based on dwNtbInMaxSize and dwNtbOutMaxSize respectively. It was therefore assumed that usbnet_change_mtu() would never touch rx_urb_size. This failed to consider the case where dwNtbInMaxSize and dwNtbOutMaxSize happens to be equal.
Fix by implementing an NCM specific change_mtu ndo, modifying the netdev MTU without touching the buffer size settings.
--- drivers/net/usb/cdc_mbim.c | 2 +- drivers/net/usb/cdc_ncm.c | 31 +++++++++++++++++++++++++++++++ include/linux/usb/cdc_ncm.h | 1 + 3 files changed, 33 insertions(+), 1 deletion(-)
drivers/net/usb/cdc_mbim.c +1 -1
@@ -100,7 +100,7 @@ static const struct net_device_ops cdc_m .ndo_stop = usbnet_stop, .ndo_start_xmit = usbnet_start_xmit, .ndo_tx_timeout = usbnet_tx_timeout, - .ndo_change_mtu = usbnet_change_mtu, + .ndo_change_mtu = cdc_ncm_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, .ndo_vlan_rx_add_vid = cdc_mbim_rx_add_vid,
drivers/net/usb/cdc_ncm.c +31 -0
@@ -41,6 +41,7 @@#include <linux/module.h> #include <linux/netdevice.h> #include <linux/ctype.h> +#include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/workqueue.h> #include <linux/mii.h>
@@ -687,6 +688,33 @@ static void cdc_ncm_free(struct cdc_ncm_kfree (ctx); } +/* we need to override the usbnet change_mtu ndo for two reasons: +* - respect the negotiated maximum datagram size +* - avoid unwanted changes to rx and tx buffers +*/ +int cdc_ncm_change_mtu (struct net_device *net,int new_mtu) +{ +struct usbnet *dev =netdev_priv (net); +struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0 ]; +int maxmtu = ctx->max_datagram_size -cdc_ncm_eth_hlen (dev); + +if (new_mtu <=0 || new_mtu > maxmtu) +return -EINVAL ; + net->mtu = new_mtu; +return 0 ; +} +EXPORT_SYMBOL_GPL (cdc_ncm_change_mtu); + +static const struct net_device_ops cdc_ncm_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = cdc_ncm_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; +int cdc_ncm_bind_common (struct usbnet *dev,struct usb_interface *intf,u8 data_altsetting) {const struct usb_cdc_union_desc *union_desc =NULL ;
@@ -861,6 +889,9 @@ advance:/* add our sysfs attrs */ dev->net->sysfs_groups[0 ] = &cdc_ncm_sysfs_attr_group; +/* must handle MTU changes */ + dev->net->netdev_ops = &cdc_ncm_netdev_ops; +return 0 ; error2:
include/linux/usb/cdc_ncm.h +1 -0
@@ -133,6 +133,7 @@ struct cdc_ncm_ctx { };u8 cdc_ncm_select_altsetting (struct usb_interface *intf); +int cdc_ncm_change_mtu (struct net_device *net,int new_mtu);int cdc_ncm_bind_common (struct usbnet *dev,struct usb_interface *intf,u8 data_altsetting);void cdc_ncm_unbind (struct usbnet *dev,struct usb_interface *intf);struct sk_buff *cdc_ncm_fill_tx_frame (struct usbnet *dev,struct sk_buff *skb,__le32 sign);
Patches currently in stable-queue which might be from [email protected] are
queue-4.1/net-cdc_ncm-avoid-changing-rx-tx-buffers-on-mtu-changes.patch