Merge remote-tracking branch 'lsk/v3.10/topic/gator' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / drivers / net / usb / cdc_mbim.c
1 /*
2  * Copyright (c) 2012  Smith Micro Software, Inc.
3  * Copyright (c) 2012  Bjørn Mork <bjorn@mork.no>
4  *
5  * This driver is based on and reuse most of cdc_ncm, which is
6  * Copyright (C) ST-Ericsson 2010-2012
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  */
12
13 #include <linux/module.h>
14 #include <linux/netdevice.h>
15 #include <linux/ethtool.h>
16 #include <linux/if_vlan.h>
17 #include <linux/ip.h>
18 #include <linux/mii.h>
19 #include <linux/usb.h>
20 #include <linux/usb/cdc.h>
21 #include <linux/usb/usbnet.h>
22 #include <linux/usb/cdc-wdm.h>
23 #include <linux/usb/cdc_ncm.h>
24
25 /* driver specific data - must match cdc_ncm usage */
26 struct cdc_mbim_state {
27         struct cdc_ncm_ctx *ctx;
28         atomic_t pmcount;
29         struct usb_driver *subdriver;
30         struct usb_interface *control;
31         struct usb_interface *data;
32 };
33
34 /* using a counter to merge subdriver requests with our own into a combined state */
35 static int cdc_mbim_manage_power(struct usbnet *dev, int on)
36 {
37         struct cdc_mbim_state *info = (void *)&dev->data;
38         int rv = 0;
39
40         dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on);
41
42         if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) {
43                 /* need autopm_get/put here to ensure the usbcore sees the new value */
44                 rv = usb_autopm_get_interface(dev->intf);
45                 if (rv < 0)
46                         goto err;
47                 dev->intf->needs_remote_wakeup = on;
48                 usb_autopm_put_interface(dev->intf);
49         }
50 err:
51         return rv;
52 }
53
54 static int cdc_mbim_wdm_manage_power(struct usb_interface *intf, int status)
55 {
56         struct usbnet *dev = usb_get_intfdata(intf);
57
58         /* can be called while disconnecting */
59         if (!dev)
60                 return 0;
61
62         return cdc_mbim_manage_power(dev, status);
63 }
64
65
66 static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
67 {
68         struct cdc_ncm_ctx *ctx;
69         struct usb_driver *subdriver = ERR_PTR(-ENODEV);
70         int ret = -ENODEV;
71         u8 data_altsetting = cdc_ncm_select_altsetting(dev, intf);
72         struct cdc_mbim_state *info = (void *)&dev->data;
73
74         /* Probably NCM, defer for cdc_ncm_bind */
75         if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
76                 goto err;
77
78         ret = cdc_ncm_bind_common(dev, intf, data_altsetting);
79         if (ret)
80                 goto err;
81
82         ctx = info->ctx;
83
84         /* The MBIM descriptor and the status endpoint are required */
85         if (ctx->mbim_desc && dev->status)
86                 subdriver = usb_cdc_wdm_register(ctx->control,
87                                                  &dev->status->desc,
88                                                  le16_to_cpu(ctx->mbim_desc->wMaxControlMessage),
89                                                  cdc_mbim_wdm_manage_power);
90         if (IS_ERR(subdriver)) {
91                 ret = PTR_ERR(subdriver);
92                 cdc_ncm_unbind(dev, intf);
93                 goto err;
94         }
95
96         /* can't let usbnet use the interrupt endpoint */
97         dev->status = NULL;
98         info->subdriver = subdriver;
99
100         /* MBIM cannot do ARP */
101         dev->net->flags |= IFF_NOARP;
102
103         /* no need to put the VLAN tci in the packet headers */
104         dev->net->features |= NETIF_F_HW_VLAN_CTAG_TX;
105 err:
106         return ret;
107 }
108
109 static void cdc_mbim_unbind(struct usbnet *dev, struct usb_interface *intf)
110 {
111         struct cdc_mbim_state *info = (void *)&dev->data;
112         struct cdc_ncm_ctx *ctx = info->ctx;
113
114         /* disconnect subdriver from control interface */
115         if (info->subdriver && info->subdriver->disconnect)
116                 info->subdriver->disconnect(ctx->control);
117         info->subdriver = NULL;
118
119         /* let NCM unbind clean up both control and data interface */
120         cdc_ncm_unbind(dev, intf);
121 }
122
123 /* verify that the ethernet protocol is IPv4 or IPv6 */
124 static bool is_ip_proto(__be16 proto)
125 {
126         switch (proto) {
127         case htons(ETH_P_IP):
128         case htons(ETH_P_IPV6):
129                 return true;
130         }
131         return false;
132 }
133
134 static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
135 {
136         struct sk_buff *skb_out;
137         struct cdc_mbim_state *info = (void *)&dev->data;
138         struct cdc_ncm_ctx *ctx = info->ctx;
139         __le32 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN);
140         u16 tci = 0;
141         bool is_ip;
142         u8 *c;
143
144         if (!ctx)
145                 goto error;
146
147         if (skb) {
148                 if (skb->len <= ETH_HLEN)
149                         goto error;
150
151                 /* Some applications using e.g. packet sockets will
152                  * bypass the VLAN acceleration and create tagged
153                  * ethernet frames directly.  We primarily look for
154                  * the accelerated out-of-band tag, but fall back if
155                  * required
156                  */
157                 skb_reset_mac_header(skb);
158                 if (vlan_get_tag(skb, &tci) < 0 && skb->len > VLAN_ETH_HLEN &&
159                     __vlan_get_tag(skb, &tci) == 0) {
160                         is_ip = is_ip_proto(vlan_eth_hdr(skb)->h_vlan_encapsulated_proto);
161                         skb_pull(skb, VLAN_ETH_HLEN);
162                 } else {
163                         is_ip = is_ip_proto(eth_hdr(skb)->h_proto);
164                         skb_pull(skb, ETH_HLEN);
165                 }
166
167                 /* mapping VLANs to MBIM sessions:
168                  *   no tag     => IPS session <0>
169                  *   1 - 255    => IPS session <vlanid>
170                  *   256 - 511  => DSS session <vlanid - 256>
171                  *   512 - 4095 => unsupported, drop
172                  */
173                 switch (tci & 0x0f00) {
174                 case 0x0000: /* VLAN ID 0 - 255 */
175                         if (!is_ip)
176                                 goto error;
177                         c = (u8 *)&sign;
178                         c[3] = tci;
179                         break;
180                 case 0x0100: /* VLAN ID 256 - 511 */
181                         sign = cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN);
182                         c = (u8 *)&sign;
183                         c[3] = tci;
184                         break;
185                 default:
186                         netif_err(dev, tx_err, dev->net,
187                                   "unsupported tci=0x%04x\n", tci);
188                         goto error;
189                 }
190         }
191
192         spin_lock_bh(&ctx->mtx);
193         skb_out = cdc_ncm_fill_tx_frame(ctx, skb, sign);
194         spin_unlock_bh(&ctx->mtx);
195         return skb_out;
196
197 error:
198         if (skb)
199                 dev_kfree_skb_any(skb);
200
201         return NULL;
202 }
203
204 static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci)
205 {
206         __be16 proto = htons(ETH_P_802_3);
207         struct sk_buff *skb = NULL;
208
209         if (tci < 256) { /* IPS session? */
210                 if (len < sizeof(struct iphdr))
211                         goto err;
212
213                 switch (*buf & 0xf0) {
214                 case 0x40:
215                         proto = htons(ETH_P_IP);
216                         break;
217                 case 0x60:
218                         proto = htons(ETH_P_IPV6);
219                         break;
220                 default:
221                         goto err;
222                 }
223         }
224
225         skb = netdev_alloc_skb_ip_align(dev->net,  len + ETH_HLEN);
226         if (!skb)
227                 goto err;
228
229         /* add an ethernet header */
230         skb_put(skb, ETH_HLEN);
231         skb_reset_mac_header(skb);
232         eth_hdr(skb)->h_proto = proto;
233         memset(eth_hdr(skb)->h_source, 0, ETH_ALEN);
234         memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
235
236         /* add datagram */
237         memcpy(skb_put(skb, len), buf, len);
238
239         /* map MBIM session to VLAN */
240         if (tci)
241                 vlan_put_tag(skb, htons(ETH_P_8021Q), tci);
242 err:
243         return skb;
244 }
245
246 static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
247 {
248         struct sk_buff *skb;
249         struct cdc_mbim_state *info = (void *)&dev->data;
250         struct cdc_ncm_ctx *ctx = info->ctx;
251         int len;
252         int nframes;
253         int x;
254         int offset;
255         struct usb_cdc_ncm_ndp16 *ndp16;
256         struct usb_cdc_ncm_dpe16 *dpe16;
257         int ndpoffset;
258         int loopcount = 50; /* arbitrary max preventing infinite loop */
259         u8 *c;
260         u16 tci;
261
262         ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
263         if (ndpoffset < 0)
264                 goto error;
265
266 next_ndp:
267         nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
268         if (nframes < 0)
269                 goto error;
270
271         ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
272
273         switch (ndp16->dwSignature & cpu_to_le32(0x00ffffff)) {
274         case cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN):
275                 c = (u8 *)&ndp16->dwSignature;
276                 tci = c[3];
277                 break;
278         case cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN):
279                 c = (u8 *)&ndp16->dwSignature;
280                 tci = c[3] + 256;
281                 break;
282         default:
283                 netif_dbg(dev, rx_err, dev->net,
284                           "unsupported NDP signature <0x%08x>\n",
285                           le32_to_cpu(ndp16->dwSignature));
286                 goto err_ndp;
287
288         }
289
290         dpe16 = ndp16->dpe16;
291         for (x = 0; x < nframes; x++, dpe16++) {
292                 offset = le16_to_cpu(dpe16->wDatagramIndex);
293                 len = le16_to_cpu(dpe16->wDatagramLength);
294
295                 /*
296                  * CDC NCM ch. 3.7
297                  * All entries after first NULL entry are to be ignored
298                  */
299                 if ((offset == 0) || (len == 0)) {
300                         if (!x)
301                                 goto err_ndp; /* empty NTB */
302                         break;
303                 }
304
305                 /* sanity checking */
306                 if (((offset + len) > skb_in->len) || (len > ctx->rx_max)) {
307                         netif_dbg(dev, rx_err, dev->net,
308                                   "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n",
309                                   x, offset, len, skb_in);
310                         if (!x)
311                                 goto err_ndp;
312                         break;
313                 } else {
314                         skb = cdc_mbim_process_dgram(dev, skb_in->data + offset, len, tci);
315                         if (!skb)
316                                 goto error;
317                         usbnet_skb_return(dev, skb);
318                 }
319         }
320 err_ndp:
321         /* are there more NDPs to process? */
322         ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
323         if (ndpoffset && loopcount--)
324                 goto next_ndp;
325
326         return 1;
327 error:
328         return 0;
329 }
330
331 static int cdc_mbim_suspend(struct usb_interface *intf, pm_message_t message)
332 {
333         int ret = 0;
334         struct usbnet *dev = usb_get_intfdata(intf);
335         struct cdc_mbim_state *info = (void *)&dev->data;
336         struct cdc_ncm_ctx *ctx = info->ctx;
337
338         if (ctx == NULL) {
339                 ret = -1;
340                 goto error;
341         }
342
343         /*
344          * Both usbnet_suspend() and subdriver->suspend() MUST return 0
345          * in system sleep context, otherwise, the resume callback has
346          * to recover device from previous suspend failure.
347          */
348         ret = usbnet_suspend(intf, message);
349         if (ret < 0)
350                 goto error;
351
352         if (intf == ctx->control && info->subdriver && info->subdriver->suspend)
353                 ret = info->subdriver->suspend(intf, message);
354         if (ret < 0)
355                 usbnet_resume(intf);
356
357 error:
358         return ret;
359 }
360
361 static int cdc_mbim_resume(struct usb_interface *intf)
362 {
363         int  ret = 0;
364         struct usbnet *dev = usb_get_intfdata(intf);
365         struct cdc_mbim_state *info = (void *)&dev->data;
366         struct cdc_ncm_ctx *ctx = info->ctx;
367         bool callsub = (intf == ctx->control && info->subdriver && info->subdriver->resume);
368
369         if (callsub)
370                 ret = info->subdriver->resume(intf);
371         if (ret < 0)
372                 goto err;
373         ret = usbnet_resume(intf);
374         if (ret < 0 && callsub && info->subdriver->suspend)
375                 info->subdriver->suspend(intf, PMSG_SUSPEND);
376 err:
377         return ret;
378 }
379
380 static const struct driver_info cdc_mbim_info = {
381         .description = "CDC MBIM",
382         .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN,
383         .bind = cdc_mbim_bind,
384         .unbind = cdc_mbim_unbind,
385         .manage_power = cdc_mbim_manage_power,
386         .rx_fixup = cdc_mbim_rx_fixup,
387         .tx_fixup = cdc_mbim_tx_fixup,
388 };
389
390 /* MBIM and NCM devices should not need a ZLP after NTBs with
391  * dwNtbOutMaxSize length. This driver_info is for the exceptional
392  * devices requiring it anyway, allowing them to be supported without
393  * forcing the performance penalty on all the sane devices.
394  */
395 static const struct driver_info cdc_mbim_info_zlp = {
396         .description = "CDC MBIM",
397         .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP,
398         .bind = cdc_mbim_bind,
399         .unbind = cdc_mbim_unbind,
400         .manage_power = cdc_mbim_manage_power,
401         .rx_fixup = cdc_mbim_rx_fixup,
402         .tx_fixup = cdc_mbim_tx_fixup,
403 };
404
405 static const struct usb_device_id mbim_devs[] = {
406         /* This duplicate NCM entry is intentional. MBIM devices can
407          * be disguised as NCM by default, and this is necessary to
408          * allow us to bind the correct driver_info to such devices.
409          *
410          * bind() will sort out this for us, selecting the correct
411          * entry and reject the other
412          */
413         { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
414           .driver_info = (unsigned long)&cdc_mbim_info,
415         },
416         /* Sierra Wireless MC7710 need ZLPs */
417         { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68a2, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
418           .driver_info = (unsigned long)&cdc_mbim_info_zlp,
419         },
420         /* HP hs2434 Mobile Broadband Module needs ZLPs */
421         { USB_DEVICE_AND_INTERFACE_INFO(0x3f0, 0x4b1d, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
422           .driver_info = (unsigned long)&cdc_mbim_info_zlp,
423         },
424         { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
425           .driver_info = (unsigned long)&cdc_mbim_info,
426         },
427         {
428         },
429 };
430 MODULE_DEVICE_TABLE(usb, mbim_devs);
431
432 static struct usb_driver cdc_mbim_driver = {
433         .name = "cdc_mbim",
434         .id_table = mbim_devs,
435         .probe = usbnet_probe,
436         .disconnect = usbnet_disconnect,
437         .suspend = cdc_mbim_suspend,
438         .resume = cdc_mbim_resume,
439         .reset_resume = cdc_mbim_resume,
440         .supports_autosuspend = 1,
441         .disable_hub_initiated_lpm = 1,
442 };
443 module_usb_driver(cdc_mbim_driver);
444
445 MODULE_AUTHOR("Greg Suarez <gsuarez@smithmicro.com>");
446 MODULE_AUTHOR("Bjørn Mork <bjorn@mork.no>");
447 MODULE_DESCRIPTION("USB CDC MBIM host driver");
448 MODULE_LICENSE("GPL");