xref: /linux/drivers/net/usb/cdc_mbim.c (revision d91517839e5d95adc0cf4b28caa7af62a71de526)
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 #include <net/ipv6.h>
25 #include <net/addrconf.h>
26 
27 /* driver specific data - must match cdc_ncm usage */
28 struct cdc_mbim_state {
29 	struct cdc_ncm_ctx *ctx;
30 	atomic_t pmcount;
31 	struct usb_driver *subdriver;
32 	struct usb_interface *control;
33 	struct usb_interface *data;
34 };
35 
36 /* using a counter to merge subdriver requests with our own into a combined state */
37 static int cdc_mbim_manage_power(struct usbnet *dev, int on)
38 {
39 	struct cdc_mbim_state *info = (void *)&dev->data;
40 	int rv = 0;
41 
42 	dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on);
43 
44 	if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) {
45 		/* need autopm_get/put here to ensure the usbcore sees the new value */
46 		rv = usb_autopm_get_interface(dev->intf);
47 		dev->intf->needs_remote_wakeup = on;
48 		if (!rv)
49 			usb_autopm_put_interface(dev->intf);
50 	}
51 	return 0;
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 
124 static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
125 {
126 	struct sk_buff *skb_out;
127 	struct cdc_mbim_state *info = (void *)&dev->data;
128 	struct cdc_ncm_ctx *ctx = info->ctx;
129 	__le32 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN);
130 	u16 tci = 0;
131 	u8 *c;
132 
133 	if (!ctx)
134 		goto error;
135 
136 	if (skb) {
137 		if (skb->len <= ETH_HLEN)
138 			goto error;
139 
140 		/* mapping VLANs to MBIM sessions:
141 		 *   no tag     => IPS session <0>
142 		 *   1 - 255    => IPS session <vlanid>
143 		 *   256 - 511  => DSS session <vlanid - 256>
144 		 *   512 - 4095 => unsupported, drop
145 		 */
146 		vlan_get_tag(skb, &tci);
147 
148 		switch (tci & 0x0f00) {
149 		case 0x0000: /* VLAN ID 0 - 255 */
150 			/* verify that datagram is IPv4 or IPv6 */
151 			skb_reset_mac_header(skb);
152 			switch (eth_hdr(skb)->h_proto) {
153 			case htons(ETH_P_IP):
154 			case htons(ETH_P_IPV6):
155 				break;
156 			default:
157 				goto error;
158 			}
159 			c = (u8 *)&sign;
160 			c[3] = tci;
161 			break;
162 		case 0x0100: /* VLAN ID 256 - 511 */
163 			sign = cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN);
164 			c = (u8 *)&sign;
165 			c[3] = tci;
166 			break;
167 		default:
168 			netif_err(dev, tx_err, dev->net,
169 				  "unsupported tci=0x%04x\n", tci);
170 			goto error;
171 		}
172 		skb_pull(skb, ETH_HLEN);
173 	}
174 
175 	spin_lock_bh(&ctx->mtx);
176 	skb_out = cdc_ncm_fill_tx_frame(dev, skb, sign);
177 	spin_unlock_bh(&ctx->mtx);
178 	return skb_out;
179 
180 error:
181 	if (skb)
182 		dev_kfree_skb_any(skb);
183 
184 	return NULL;
185 }
186 
187 /* Some devices are known to send Neigbor Solicitation messages and
188  * require Neigbor Advertisement replies.  The IPv6 core will not
189  * respond since IFF_NOARP is set, so we must handle them ourselves.
190  */
191 static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
192 {
193 	struct ipv6hdr *iph = (void *)buf;
194 	struct nd_msg *msg = (void *)(iph + 1);
195 	struct net_device *netdev;
196 	struct inet6_dev *in6_dev;
197 	bool is_router;
198 
199 	/* we'll only respond to requests from unicast addresses to
200 	 * our solicited node addresses.
201 	 */
202 	if (!ipv6_addr_is_solict_mult(&iph->daddr) ||
203 	    !(ipv6_addr_type(&iph->saddr) & IPV6_ADDR_UNICAST))
204 		return;
205 
206 	/* need to send the NA on the VLAN dev, if any */
207 	if (tci)
208 		netdev = __vlan_find_dev_deep(dev->net, htons(ETH_P_8021Q),
209 					      tci);
210 	else
211 		netdev = dev->net;
212 	if (!netdev)
213 		return;
214 
215 	in6_dev = in6_dev_get(netdev);
216 	if (!in6_dev)
217 		return;
218 	is_router = !!in6_dev->cnf.forwarding;
219 	in6_dev_put(in6_dev);
220 
221 	/* ipv6_stub != NULL if in6_dev_get returned an inet6_dev */
222 	ipv6_stub->ndisc_send_na(netdev, NULL, &iph->saddr, &msg->target,
223 				 is_router /* router */,
224 				 true /* solicited */,
225 				 false /* override */,
226 				 true /* inc_opt */);
227 }
228 
229 static bool is_neigh_solicit(u8 *buf, size_t len)
230 {
231 	struct ipv6hdr *iph = (void *)buf;
232 	struct nd_msg *msg = (void *)(iph + 1);
233 
234 	return (len >= sizeof(struct ipv6hdr) + sizeof(struct nd_msg) &&
235 		iph->nexthdr == IPPROTO_ICMPV6 &&
236 		msg->icmph.icmp6_code == 0 &&
237 		msg->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION);
238 }
239 
240 
241 static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci)
242 {
243 	__be16 proto = htons(ETH_P_802_3);
244 	struct sk_buff *skb = NULL;
245 
246 	if (tci < 256) { /* IPS session? */
247 		if (len < sizeof(struct iphdr))
248 			goto err;
249 
250 		switch (*buf & 0xf0) {
251 		case 0x40:
252 			proto = htons(ETH_P_IP);
253 			break;
254 		case 0x60:
255 			if (is_neigh_solicit(buf, len))
256 				do_neigh_solicit(dev, buf, tci);
257 			proto = htons(ETH_P_IPV6);
258 			break;
259 		default:
260 			goto err;
261 		}
262 	}
263 
264 	skb = netdev_alloc_skb_ip_align(dev->net,  len + ETH_HLEN);
265 	if (!skb)
266 		goto err;
267 
268 	/* add an ethernet header */
269 	skb_put(skb, ETH_HLEN);
270 	skb_reset_mac_header(skb);
271 	eth_hdr(skb)->h_proto = proto;
272 	memset(eth_hdr(skb)->h_source, 0, ETH_ALEN);
273 	memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
274 
275 	/* add datagram */
276 	memcpy(skb_put(skb, len), buf, len);
277 
278 	/* map MBIM session to VLAN */
279 	if (tci)
280 		vlan_put_tag(skb, htons(ETH_P_8021Q), tci);
281 err:
282 	return skb;
283 }
284 
285 static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
286 {
287 	struct sk_buff *skb;
288 	struct cdc_mbim_state *info = (void *)&dev->data;
289 	struct cdc_ncm_ctx *ctx = info->ctx;
290 	int len;
291 	int nframes;
292 	int x;
293 	int offset;
294 	struct usb_cdc_ncm_ndp16 *ndp16;
295 	struct usb_cdc_ncm_dpe16 *dpe16;
296 	int ndpoffset;
297 	int loopcount = 50; /* arbitrary max preventing infinite loop */
298 	u8 *c;
299 	u16 tci;
300 
301 	ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
302 	if (ndpoffset < 0)
303 		goto error;
304 
305 next_ndp:
306 	nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
307 	if (nframes < 0)
308 		goto error;
309 
310 	ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
311 
312 	switch (ndp16->dwSignature & cpu_to_le32(0x00ffffff)) {
313 	case cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN):
314 		c = (u8 *)&ndp16->dwSignature;
315 		tci = c[3];
316 		break;
317 	case cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN):
318 		c = (u8 *)&ndp16->dwSignature;
319 		tci = c[3] + 256;
320 		break;
321 	default:
322 		netif_dbg(dev, rx_err, dev->net,
323 			  "unsupported NDP signature <0x%08x>\n",
324 			  le32_to_cpu(ndp16->dwSignature));
325 		goto err_ndp;
326 
327 	}
328 
329 	dpe16 = ndp16->dpe16;
330 	for (x = 0; x < nframes; x++, dpe16++) {
331 		offset = le16_to_cpu(dpe16->wDatagramIndex);
332 		len = le16_to_cpu(dpe16->wDatagramLength);
333 
334 		/*
335 		 * CDC NCM ch. 3.7
336 		 * All entries after first NULL entry are to be ignored
337 		 */
338 		if ((offset == 0) || (len == 0)) {
339 			if (!x)
340 				goto err_ndp; /* empty NTB */
341 			break;
342 		}
343 
344 		/* sanity checking */
345 		if (((offset + len) > skb_in->len) || (len > ctx->rx_max)) {
346 			netif_dbg(dev, rx_err, dev->net,
347 				  "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n",
348 				  x, offset, len, skb_in);
349 			if (!x)
350 				goto err_ndp;
351 			break;
352 		} else {
353 			skb = cdc_mbim_process_dgram(dev, skb_in->data + offset, len, tci);
354 			if (!skb)
355 				goto error;
356 			usbnet_skb_return(dev, skb);
357 		}
358 	}
359 err_ndp:
360 	/* are there more NDPs to process? */
361 	ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
362 	if (ndpoffset && loopcount--)
363 		goto next_ndp;
364 
365 	return 1;
366 error:
367 	return 0;
368 }
369 
370 static int cdc_mbim_suspend(struct usb_interface *intf, pm_message_t message)
371 {
372 	int ret = -ENODEV;
373 	struct usbnet *dev = usb_get_intfdata(intf);
374 	struct cdc_mbim_state *info = (void *)&dev->data;
375 	struct cdc_ncm_ctx *ctx = info->ctx;
376 
377 	if (!ctx)
378 		goto error;
379 
380 	/*
381 	 * Both usbnet_suspend() and subdriver->suspend() MUST return 0
382 	 * in system sleep context, otherwise, the resume callback has
383 	 * to recover device from previous suspend failure.
384 	 */
385 	ret = usbnet_suspend(intf, message);
386 	if (ret < 0)
387 		goto error;
388 
389 	if (intf == ctx->control && info->subdriver && info->subdriver->suspend)
390 		ret = info->subdriver->suspend(intf, message);
391 	if (ret < 0)
392 		usbnet_resume(intf);
393 
394 error:
395 	return ret;
396 }
397 
398 static int cdc_mbim_resume(struct usb_interface *intf)
399 {
400 	int  ret = 0;
401 	struct usbnet *dev = usb_get_intfdata(intf);
402 	struct cdc_mbim_state *info = (void *)&dev->data;
403 	struct cdc_ncm_ctx *ctx = info->ctx;
404 	bool callsub = (intf == ctx->control && info->subdriver && info->subdriver->resume);
405 
406 	if (callsub)
407 		ret = info->subdriver->resume(intf);
408 	if (ret < 0)
409 		goto err;
410 	ret = usbnet_resume(intf);
411 	if (ret < 0 && callsub)
412 		info->subdriver->suspend(intf, PMSG_SUSPEND);
413 err:
414 	return ret;
415 }
416 
417 static const struct driver_info cdc_mbim_info = {
418 	.description = "CDC MBIM",
419 	.flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN,
420 	.bind = cdc_mbim_bind,
421 	.unbind = cdc_mbim_unbind,
422 	.manage_power = cdc_mbim_manage_power,
423 	.rx_fixup = cdc_mbim_rx_fixup,
424 	.tx_fixup = cdc_mbim_tx_fixup,
425 };
426 
427 /* MBIM and NCM devices should not need a ZLP after NTBs with
428  * dwNtbOutMaxSize length. Nevertheless, a number of devices from
429  * different vendor IDs will fail unless we send ZLPs, forcing us
430  * to make this the default.
431  *
432  * This default may cause a performance penalty for spec conforming
433  * devices wanting to take advantage of optimizations possible without
434  * ZLPs.  A whitelist is added in an attempt to avoid this for devices
435  * known to conform to the MBIM specification.
436  *
437  * All known devices supporting NCM compatibility mode are also
438  * conforming to the NCM and MBIM specifications. For this reason, the
439  * NCM subclass entry is also in the ZLP whitelist.
440  */
441 static const struct driver_info cdc_mbim_info_zlp = {
442 	.description = "CDC MBIM",
443 	.flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP,
444 	.bind = cdc_mbim_bind,
445 	.unbind = cdc_mbim_unbind,
446 	.manage_power = cdc_mbim_manage_power,
447 	.rx_fixup = cdc_mbim_rx_fixup,
448 	.tx_fixup = cdc_mbim_tx_fixup,
449 };
450 
451 static const struct usb_device_id mbim_devs[] = {
452 	/* This duplicate NCM entry is intentional. MBIM devices can
453 	 * be disguised as NCM by default, and this is necessary to
454 	 * allow us to bind the correct driver_info to such devices.
455 	 *
456 	 * bind() will sort out this for us, selecting the correct
457 	 * entry and reject the other
458 	 */
459 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
460 	  .driver_info = (unsigned long)&cdc_mbim_info,
461 	},
462 	/* ZLP conformance whitelist: All Ericsson MBIM devices */
463 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0bdb, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
464 	  .driver_info = (unsigned long)&cdc_mbim_info,
465 	},
466 	/* default entry */
467 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
468 	  .driver_info = (unsigned long)&cdc_mbim_info_zlp,
469 	},
470 	{
471 	},
472 };
473 MODULE_DEVICE_TABLE(usb, mbim_devs);
474 
475 static struct usb_driver cdc_mbim_driver = {
476 	.name = "cdc_mbim",
477 	.id_table = mbim_devs,
478 	.probe = usbnet_probe,
479 	.disconnect = usbnet_disconnect,
480 	.suspend = cdc_mbim_suspend,
481 	.resume = cdc_mbim_resume,
482 	.reset_resume =	cdc_mbim_resume,
483 	.supports_autosuspend = 1,
484 	.disable_hub_initiated_lpm = 1,
485 };
486 module_usb_driver(cdc_mbim_driver);
487 
488 MODULE_AUTHOR("Greg Suarez <gsuarez@smithmicro.com>");
489 MODULE_AUTHOR("Bjørn Mork <bjorn@mork.no>");
490 MODULE_DESCRIPTION("USB CDC MBIM host driver");
491 MODULE_LICENSE("GPL");
492