summaryrefslogtreecommitdiffstats
path: root/drivers/net/usb
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-06-17 18:55:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-06-17 18:55:34 -0400
commitda0f382029868806e88c046eb2560fdee7a9457c (patch)
treefe8c8248c5d2023430e2a129fe7dc0c424365aea /drivers/net/usb
parenteb7c825bf74755a9ea975b7a463c6d13ffa7f447 (diff)
parent4fddbf8a99ee5a65bdd31b3ebbf5a84b9395d496 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: "Lots of bug fixes here: 1) Out of bounds access in __bpf_skc_lookup, from Lorenz Bauer. 2) Fix rate reporting in cfg80211_calculate_bitrate_he(), from John Crispin. 3) Use after free in psock backlog workqueue, from John Fastabend. 4) Fix source port matching in fdb peer flow rule of mlx5, from Raed Salem. 5) Use atomic_inc_not_zero() in fl6_sock_lookup(), from Eric Dumazet. 6) Network header needs to be set for packet redirect in nfp, from John Hurley. 7) Fix udp zerocopy refcnt, from Willem de Bruijn. 8) Don't assume linear buffers in vxlan and geneve error handlers, from Stefano Brivio. 9) Fix TOS matching in mlxsw, from Jiri Pirko. 10) More SCTP cookie memory leak fixes, from Neil Horman. 11) Fix VLAN filtering in rtl8366, from Linus Walluij. 12) Various TCP SACK payload size and fragmentation memory limit fixes from Eric Dumazet. 13) Use after free in pneigh_get_next(), also from Eric Dumazet. 14) LAPB control block leak fix from Jeremy Sowden" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (145 commits) lapb: fixed leak of control-blocks. tipc: purge deferredq list for each grp member in tipc_group_delete ax25: fix inconsistent lock state in ax25_destroy_timer neigh: fix use-after-free read in pneigh_get_next tcp: fix compile error if !CONFIG_SYSCTL hv_sock: Suppress bogus "may be used uninitialized" warnings be2net: Fix number of Rx queues used for flow hashing net: handle 802.1P vlan 0 packets properly tcp: enforce tcp_min_snd_mss in tcp_mtu_probing() tcp: add tcp_min_snd_mss sysctl tcp: tcp_fragment() should apply sane memory limits tcp: limit payload size of sacked skbs Revert "net: phylink: set the autoneg state in phylink_phy_change" bpf: fix nested bpf tracepoints with per-cpu data bpf: Fix out of bounds memory access in bpf_sk_storage vsock/virtio: set SOCK_DONE on peer shutdown net: dsa: rtl8366: Fix up VLAN filtering net: phylink: set the autoneg state in phylink_phy_change net: add high_order_alloc_disable sysctl/static key tcp: add tcp_tx_skb_cache sysctl ...
Diffstat (limited to 'drivers/net/usb')
-rw-r--r--drivers/net/usb/qmi_wwan.c103
1 files changed, 89 insertions, 14 deletions
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index d9a6699abe59..780c10ee359b 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -22,6 +22,7 @@
22#include <linux/usb/cdc.h> 22#include <linux/usb/cdc.h>
23#include <linux/usb/usbnet.h> 23#include <linux/usb/usbnet.h>
24#include <linux/usb/cdc-wdm.h> 24#include <linux/usb/cdc-wdm.h>
25#include <linux/u64_stats_sync.h>
25 26
26/* This driver supports wwan (3G/LTE/?) devices using a vendor 27/* This driver supports wwan (3G/LTE/?) devices using a vendor
27 * specific management protocol called Qualcomm MSM Interface (QMI) - 28 * specific management protocol called Qualcomm MSM Interface (QMI) -
@@ -75,6 +76,7 @@ struct qmimux_hdr {
75struct qmimux_priv { 76struct qmimux_priv {
76 struct net_device *real_dev; 77 struct net_device *real_dev;
77 u8 mux_id; 78 u8 mux_id;
79 struct pcpu_sw_netstats __percpu *stats64;
78}; 80};
79 81
80static int qmimux_open(struct net_device *dev) 82static int qmimux_open(struct net_device *dev)
@@ -101,19 +103,65 @@ static netdev_tx_t qmimux_start_xmit(struct sk_buff *skb, struct net_device *dev
101 struct qmimux_priv *priv = netdev_priv(dev); 103 struct qmimux_priv *priv = netdev_priv(dev);
102 unsigned int len = skb->len; 104 unsigned int len = skb->len;
103 struct qmimux_hdr *hdr; 105 struct qmimux_hdr *hdr;
106 netdev_tx_t ret;
104 107
105 hdr = skb_push(skb, sizeof(struct qmimux_hdr)); 108 hdr = skb_push(skb, sizeof(struct qmimux_hdr));
106 hdr->pad = 0; 109 hdr->pad = 0;
107 hdr->mux_id = priv->mux_id; 110 hdr->mux_id = priv->mux_id;
108 hdr->pkt_len = cpu_to_be16(len); 111 hdr->pkt_len = cpu_to_be16(len);
109 skb->dev = priv->real_dev; 112 skb->dev = priv->real_dev;
110 return dev_queue_xmit(skb); 113 ret = dev_queue_xmit(skb);
114
115 if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
116 struct pcpu_sw_netstats *stats64 = this_cpu_ptr(priv->stats64);
117
118 u64_stats_update_begin(&stats64->syncp);
119 stats64->tx_packets++;
120 stats64->tx_bytes += len;
121 u64_stats_update_end(&stats64->syncp);
122 } else {
123 dev->stats.tx_dropped++;
124 }
125
126 return ret;
127}
128
129static void qmimux_get_stats64(struct net_device *net,
130 struct rtnl_link_stats64 *stats)
131{
132 struct qmimux_priv *priv = netdev_priv(net);
133 unsigned int start;
134 int cpu;
135
136 netdev_stats_to_stats64(stats, &net->stats);
137
138 for_each_possible_cpu(cpu) {
139 struct pcpu_sw_netstats *stats64;
140 u64 rx_packets, rx_bytes;
141 u64 tx_packets, tx_bytes;
142
143 stats64 = per_cpu_ptr(priv->stats64, cpu);
144
145 do {
146 start = u64_stats_fetch_begin_irq(&stats64->syncp);
147 rx_packets = stats64->rx_packets;
148 rx_bytes = stats64->rx_bytes;
149 tx_packets = stats64->tx_packets;
150 tx_bytes = stats64->tx_bytes;
151 } while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
152
153 stats->rx_packets += rx_packets;
154 stats->rx_bytes += rx_bytes;
155 stats->tx_packets += tx_packets;
156 stats->tx_bytes += tx_bytes;
157 }
111} 158}
112 159
113static const struct net_device_ops qmimux_netdev_ops = { 160static const struct net_device_ops qmimux_netdev_ops = {
114 .ndo_open = qmimux_open, 161 .ndo_open = qmimux_open,
115 .ndo_stop = qmimux_stop, 162 .ndo_stop = qmimux_stop,
116 .ndo_start_xmit = qmimux_start_xmit, 163 .ndo_start_xmit = qmimux_start_xmit,
164 .ndo_get_stats64 = qmimux_get_stats64,
117}; 165};
118 166
119static void qmimux_setup(struct net_device *dev) 167static void qmimux_setup(struct net_device *dev)
@@ -153,7 +201,7 @@ static bool qmimux_has_slaves(struct usbnet *dev)
153 201
154static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb) 202static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
155{ 203{
156 unsigned int len, offset = 0; 204 unsigned int len, offset = 0, pad_len, pkt_len;
157 struct qmimux_hdr *hdr; 205 struct qmimux_hdr *hdr;
158 struct net_device *net; 206 struct net_device *net;
159 struct sk_buff *skbn; 207 struct sk_buff *skbn;
@@ -171,10 +219,16 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
171 if (hdr->pad & 0x80) 219 if (hdr->pad & 0x80)
172 goto skip; 220 goto skip;
173 221
222 /* extract padding length and check for valid length info */
223 pad_len = hdr->pad & 0x3f;
224 if (len == 0 || pad_len >= len)
225 goto skip;
226 pkt_len = len - pad_len;
227
174 net = qmimux_find_dev(dev, hdr->mux_id); 228 net = qmimux_find_dev(dev, hdr->mux_id);
175 if (!net) 229 if (!net)
176 goto skip; 230 goto skip;
177 skbn = netdev_alloc_skb(net, len); 231 skbn = netdev_alloc_skb(net, pkt_len);
178 if (!skbn) 232 if (!skbn)
179 return 0; 233 return 0;
180 skbn->dev = net; 234 skbn->dev = net;
@@ -191,9 +245,20 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
191 goto skip; 245 goto skip;
192 } 246 }
193 247
194 skb_put_data(skbn, skb->data + offset + qmimux_hdr_sz, len); 248 skb_put_data(skbn, skb->data + offset + qmimux_hdr_sz, pkt_len);
195 if (netif_rx(skbn) != NET_RX_SUCCESS) 249 if (netif_rx(skbn) != NET_RX_SUCCESS) {
250 net->stats.rx_errors++;
196 return 0; 251 return 0;
252 } else {
253 struct pcpu_sw_netstats *stats64;
254 struct qmimux_priv *priv = netdev_priv(net);
255
256 stats64 = this_cpu_ptr(priv->stats64);
257 u64_stats_update_begin(&stats64->syncp);
258 stats64->rx_packets++;
259 stats64->rx_bytes += pkt_len;
260 u64_stats_update_end(&stats64->syncp);
261 }
197 262
198skip: 263skip:
199 offset += len + qmimux_hdr_sz; 264 offset += len + qmimux_hdr_sz;
@@ -217,6 +282,12 @@ static int qmimux_register_device(struct net_device *real_dev, u8 mux_id)
217 priv->mux_id = mux_id; 282 priv->mux_id = mux_id;
218 priv->real_dev = real_dev; 283 priv->real_dev = real_dev;
219 284
285 priv->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
286 if (!priv->stats64) {
287 err = -ENOBUFS;
288 goto out_free_newdev;
289 }
290
220 err = register_netdevice(new_dev); 291 err = register_netdevice(new_dev);
221 if (err < 0) 292 if (err < 0)
222 goto out_free_newdev; 293 goto out_free_newdev;
@@ -241,13 +312,15 @@ out_free_newdev:
241 return err; 312 return err;
242} 313}
243 314
244static void qmimux_unregister_device(struct net_device *dev) 315static void qmimux_unregister_device(struct net_device *dev,
316 struct list_head *head)
245{ 317{
246 struct qmimux_priv *priv = netdev_priv(dev); 318 struct qmimux_priv *priv = netdev_priv(dev);
247 struct net_device *real_dev = priv->real_dev; 319 struct net_device *real_dev = priv->real_dev;
248 320
321 free_percpu(priv->stats64);
249 netdev_upper_dev_unlink(real_dev, dev); 322 netdev_upper_dev_unlink(real_dev, dev);
250 unregister_netdevice(dev); 323 unregister_netdevice_queue(dev, head);
251 324
252 /* Get rid of the reference to real_dev */ 325 /* Get rid of the reference to real_dev */
253 dev_put(real_dev); 326 dev_put(real_dev);
@@ -356,8 +429,8 @@ static ssize_t add_mux_store(struct device *d, struct device_attribute *attr, c
356 if (kstrtou8(buf, 0, &mux_id)) 429 if (kstrtou8(buf, 0, &mux_id))
357 return -EINVAL; 430 return -EINVAL;
358 431
359 /* mux_id [1 - 0x7f] range empirically found */ 432 /* mux_id [1 - 254] for compatibility with ip(8) and the rmnet driver */
360 if (mux_id < 1 || mux_id > 0x7f) 433 if (mux_id < 1 || mux_id > 254)
361 return -EINVAL; 434 return -EINVAL;
362 435
363 if (!rtnl_trylock()) 436 if (!rtnl_trylock())
@@ -418,7 +491,7 @@ static ssize_t del_mux_store(struct device *d, struct device_attribute *attr, c
418 ret = -EINVAL; 491 ret = -EINVAL;
419 goto err; 492 goto err;
420 } 493 }
421 qmimux_unregister_device(del_dev); 494 qmimux_unregister_device(del_dev, NULL);
422 495
423 if (!qmimux_has_slaves(dev)) 496 if (!qmimux_has_slaves(dev))
424 info->flags &= ~QMI_WWAN_FLAG_MUX; 497 info->flags &= ~QMI_WWAN_FLAG_MUX;
@@ -1428,6 +1501,7 @@ static void qmi_wwan_disconnect(struct usb_interface *intf)
1428 struct qmi_wwan_state *info; 1501 struct qmi_wwan_state *info;
1429 struct list_head *iter; 1502 struct list_head *iter;
1430 struct net_device *ldev; 1503 struct net_device *ldev;
1504 LIST_HEAD(list);
1431 1505
1432 /* called twice if separate control and data intf */ 1506 /* called twice if separate control and data intf */
1433 if (!dev) 1507 if (!dev)
@@ -1440,8 +1514,9 @@ static void qmi_wwan_disconnect(struct usb_interface *intf)
1440 } 1514 }
1441 rcu_read_lock(); 1515 rcu_read_lock();
1442 netdev_for_each_upper_dev_rcu(dev->net, ldev, iter) 1516 netdev_for_each_upper_dev_rcu(dev->net, ldev, iter)
1443 qmimux_unregister_device(ldev); 1517 qmimux_unregister_device(ldev, &list);
1444 rcu_read_unlock(); 1518 rcu_read_unlock();
1519 unregister_netdevice_many(&list);
1445 rtnl_unlock(); 1520 rtnl_unlock();
1446 info->flags &= ~QMI_WWAN_FLAG_MUX; 1521 info->flags &= ~QMI_WWAN_FLAG_MUX;
1447 } 1522 }
x80 /* Interrupt pending */ #define TSS_SEQ_ACTIVE 0x40 /* Sequencer active */ #define TSS_XFER_CNT 0x20 /* Transfer counter zero */ #define TSS_FIFO_EMPTY 0x10 /* FIFO empty */ #define TSS_PAR_ERROR 0x08 /* SCSI parity error */ #define TSS_PH_MASK 0x07 /* SCSI phase mask */ /*----------------------------------------------------------------------*/ /* bit definition for Tulip SCSI Status 1 Register */ /*----------------------------------------------------------------------*/ #define TSS_STATUS_RCV 0x08 /* Status received */ #define TSS_MSG_SEND 0x40 /* Message sent */ #define TSS_CMD_PH_CMP 0x20 /* command phase done */ #define TSS_DATA_PH_CMP 0x10 /* Data phase done */ #define TSS_STATUS_SEND 0x08 /* Status sent */ #define TSS_XFER_CMP 0x04 /* Transfer completed */ #define TSS_SEL_CMP 0x02 /* Selection completed */ #define TSS_ARB_CMP 0x01 /* Arbitration completed */ /*----------------------------------------------------------------------*/ /* bit definition for Tulip SCSI Status 2 Register */ /*----------------------------------------------------------------------*/ #define TSS_CMD_ABTED 0x80 /* Command aborted */ #define TSS_OFFSET_0 0x40 /* Offset counter zero */ #define TSS_FIFO_FULL 0x20 /* FIFO full */ #define TSS_TIMEOUT_0 0x10 /* Timeout counter zero */ #define TSS_BUSY_RLS 0x08 /* Busy release */ #define TSS_PH_MISMATCH 0x04 /* Phase mismatch */ #define TSS_SCSI_BUS_EN 0x02 /* SCSI data bus enable */ #define TSS_SCSIRST 0x01 /* SCSI bus reset in progress */