cdc_ncm.c 35.3 KB
Newer Older
A
Alexey Orishko 已提交
1 2 3
/*
 * cdc_ncm.c
 *
4
 * Copyright (C) ST-Ericsson 2010-2012
A
Alexey Orishko 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
 * Contact: Alexey Orishko <alexey.orishko@stericsson.com>
 * Original author: Hans Petter Selasky <hans.petter.selasky@stericsson.com>
 *
 * USB Host Driver for Network Control Model (NCM)
 * http://www.usb.org/developers/devclass_docs/NCM10.zip
 *
 * The NCM encoding, decoding and initialization logic
 * derives from FreeBSD 8.x. if_cdce.c and if_cdcereg.h
 *
 * This software is available to you under a choice of one of two
 * licenses. You may choose this file to be licensed under the terms
 * of the GNU General Public License (GPL) Version 2 or the 2-clause
 * BSD license listed below:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/ctype.h>
#include <linux/ethtool.h>
#include <linux/workqueue.h>
#include <linux/mii.h>
#include <linux/crc32.h>
#include <linux/usb.h>
49
#include <linux/hrtimer.h>
A
Alexey Orishko 已提交
50 51 52
#include <linux/atomic.h>
#include <linux/usb/usbnet.h>
#include <linux/usb/cdc.h>
53
#include <linux/usb/cdc_ncm.h>
A
Alexey Orishko 已提交
54

55 56 57 58 59 60 61 62
#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
static bool prefer_mbim = true;
#else
static bool prefer_mbim;
#endif
module_param(prefer_mbim, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(prefer_mbim, "Prefer MBIM setting on dual NCM/MBIM functions");

63 64 65
static void cdc_ncm_txpath_bh(unsigned long param);
static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
A
Alexey Orishko 已提交
66 67
static struct usb_driver cdc_ncm_driver;

68
static int cdc_ncm_setup(struct usbnet *dev)
A
Alexey Orishko 已提交
69
{
70
	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
B
Bjørn Mork 已提交
71
	struct usb_cdc_ncm_ntb_parameters ncm_parm;
A
Alexey Orishko 已提交
72 73 74 75
	u32 val;
	u8 flags;
	u8 iface_no;
	int err;
76
	int eth_hlen;
77
	u16 ntb_fmt_supported;
78
	__le16 max_datagram_size;
A
Alexey Orishko 已提交
79 80 81

	iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber;

82 83 84
	err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_PARAMETERS,
			      USB_TYPE_CLASS | USB_DIR_IN
			      |USB_RECIP_INTERFACE,
B
Bjørn Mork 已提交
85 86
			      0, iface_no, &ncm_parm,
			      sizeof(ncm_parm));
87
	if (err < 0) {
88 89
		dev_err(&dev->intf->dev, "failed GET_NTB_PARAMETERS\n");
		return err; /* GET_NTB_PARAMETERS is required */
A
Alexey Orishko 已提交
90 91 92
	}

	/* read correct set of parameters according to device mode */
B
Bjørn Mork 已提交
93 94 95 96 97
	ctx->rx_max = le32_to_cpu(ncm_parm.dwNtbInMaxSize);
	ctx->tx_max = le32_to_cpu(ncm_parm.dwNtbOutMaxSize);
	ctx->tx_remainder = le16_to_cpu(ncm_parm.wNdpOutPayloadRemainder);
	ctx->tx_modulus = le16_to_cpu(ncm_parm.wNdpOutDivisor);
	ctx->tx_ndp_modulus = le16_to_cpu(ncm_parm.wNdpOutAlignment);
98
	/* devices prior to NCM Errata shall set this field to zero */
B
Bjørn Mork 已提交
99 100
	ctx->tx_max_datagrams = le16_to_cpu(ncm_parm.wNtbOutMaxDatagrams);
	ntb_fmt_supported = le16_to_cpu(ncm_parm.bmNtbFormatsSupported);
A
Alexey Orishko 已提交
101

102 103 104 105
	/* there are some minor differences in NCM and MBIM defaults */
	if (cdc_ncm_comm_intf_is_mbim(ctx->control->cur_altsetting)) {
		if (!ctx->mbim_desc)
			return -EINVAL;
106
		eth_hlen = 0;
107 108 109 110
		flags = ctx->mbim_desc->bmNetworkCapabilities;
		ctx->max_datagram_size = le16_to_cpu(ctx->mbim_desc->wMaxSegmentSize);
		if (ctx->max_datagram_size < CDC_MBIM_MIN_DATAGRAM_SIZE)
			ctx->max_datagram_size = CDC_MBIM_MIN_DATAGRAM_SIZE;
111
	} else {
112 113 114 115 116 117 118
		if (!ctx->func_desc)
			return -EINVAL;
		eth_hlen = ETH_HLEN;
		flags = ctx->func_desc->bmNetworkCapabilities;
		ctx->max_datagram_size = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
		if (ctx->max_datagram_size < CDC_NCM_MIN_DATAGRAM_SIZE)
			ctx->max_datagram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
119
	}
A
Alexey Orishko 已提交
120

121 122 123 124
	/* common absolute max for NCM and MBIM */
	if (ctx->max_datagram_size > CDC_NCM_MAX_DATAGRAM_SIZE)
		ctx->max_datagram_size = CDC_NCM_MAX_DATAGRAM_SIZE;

125 126 127 128
	dev_dbg(&dev->intf->dev,
		"dwNtbInMaxSize=%u dwNtbOutMaxSize=%u wNdpOutPayloadRemainder=%u wNdpOutDivisor=%u wNdpOutAlignment=%u wNtbOutMaxDatagrams=%u flags=0x%x\n",
		ctx->rx_max, ctx->tx_max, ctx->tx_remainder, ctx->tx_modulus,
		ctx->tx_ndp_modulus, ctx->tx_max_datagrams, flags);
A
Alexey Orishko 已提交
129

130 131 132 133
	/* max count of tx datagrams */
	if ((ctx->tx_max_datagrams == 0) ||
			(ctx->tx_max_datagrams > CDC_NCM_DPT_DATAGRAMS_MAX))
		ctx->tx_max_datagrams = CDC_NCM_DPT_DATAGRAMS_MAX;
A
Alexey Orishko 已提交
134 135

	/* verify maximum size of received NTB in bytes */
136
	if (ctx->rx_max < USB_CDC_NCM_NTB_MIN_IN_SIZE) {
137 138
		dev_dbg(&dev->intf->dev, "Using min receive length=%d\n",
			USB_CDC_NCM_NTB_MIN_IN_SIZE);
139 140 141 142
		ctx->rx_max = USB_CDC_NCM_NTB_MIN_IN_SIZE;
	}

	if (ctx->rx_max > CDC_NCM_NTB_MAX_SIZE_RX) {
143 144
		dev_dbg(&dev->intf->dev, "Using default maximum receive length=%d\n",
			CDC_NCM_NTB_MAX_SIZE_RX);
A
Alexey Orishko 已提交
145 146 147
		ctx->rx_max = CDC_NCM_NTB_MAX_SIZE_RX;
	}

148
	/* inform device about NTB input size changes */
B
Bjørn Mork 已提交
149
	if (ctx->rx_max != le32_to_cpu(ncm_parm.dwNtbInMaxSize)) {
150
		__le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
151

152 153 154 155
		err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_INPUT_SIZE,
				       USB_TYPE_CLASS | USB_DIR_OUT
				       | USB_RECIP_INTERFACE,
				       0, iface_no, &dwNtbInMaxSize, 4);
156
		if (err < 0)
157
			dev_dbg(&dev->intf->dev, "Setting NTB Input Size failed\n");
158 159
	}

A
Alexey Orishko 已提交
160
	/* verify maximum size of transmitted NTB in bytes */
161
	if (ctx->tx_max > CDC_NCM_NTB_MAX_SIZE_TX) {
162 163
		dev_dbg(&dev->intf->dev, "Using default maximum transmit length=%d\n",
			CDC_NCM_NTB_MAX_SIZE_TX);
A
Alexey Orishko 已提交
164
		ctx->tx_max = CDC_NCM_NTB_MAX_SIZE_TX;
B
Bjørn Mork 已提交
165 166 167 168 169 170 171 172

		/* Adding a pad byte here simplifies the handling in
		 * cdc_ncm_fill_tx_frame, by making tx_max always
		 * represent the real skb max size.
		 */
		if (ctx->tx_max % usb_maxpacket(dev->udev, dev->out, 1) == 0)
			ctx->tx_max++;

A
Alexey Orishko 已提交
173 174 175 176 177 178 179 180 181 182 183 184
	}

	/*
	 * verify that the structure alignment is:
	 * - power of two
	 * - not greater than the maximum transmit length
	 * - not less than four bytes
	 */
	val = ctx->tx_ndp_modulus;

	if ((val < USB_CDC_NCM_NDP_ALIGN_MIN_SIZE) ||
	    (val != ((-val) & val)) || (val >= ctx->tx_max)) {
185
		dev_dbg(&dev->intf->dev, "Using default alignment: 4 bytes\n");
A
Alexey Orishko 已提交
186 187 188 189 190 191 192 193 194 195 196 197 198
		ctx->tx_ndp_modulus = USB_CDC_NCM_NDP_ALIGN_MIN_SIZE;
	}

	/*
	 * verify that the payload alignment is:
	 * - power of two
	 * - not greater than the maximum transmit length
	 * - not less than four bytes
	 */
	val = ctx->tx_modulus;

	if ((val < USB_CDC_NCM_NDP_ALIGN_MIN_SIZE) ||
	    (val != ((-val) & val)) || (val >= ctx->tx_max)) {
199
		dev_dbg(&dev->intf->dev, "Using default transmit modulus: 4 bytes\n");
A
Alexey Orishko 已提交
200 201 202 203 204
		ctx->tx_modulus = USB_CDC_NCM_NDP_ALIGN_MIN_SIZE;
	}

	/* verify the payload remainder */
	if (ctx->tx_remainder >= ctx->tx_modulus) {
205
		dev_dbg(&dev->intf->dev, "Using default transmit remainder: 0 bytes\n");
A
Alexey Orishko 已提交
206 207 208 209
		ctx->tx_remainder = 0;
	}

	/* adjust TX-remainder according to NCM specification. */
210 211
	ctx->tx_remainder = ((ctx->tx_remainder - eth_hlen) &
			     (ctx->tx_modulus - 1));
A
Alexey Orishko 已提交
212 213 214 215

	/* additional configuration */

	/* set CRC Mode */
216
	if (flags & USB_CDC_NCM_NCAP_CRC_MODE) {
217 218 219 220 221
		err = usbnet_write_cmd(dev, USB_CDC_SET_CRC_MODE,
				       USB_TYPE_CLASS | USB_DIR_OUT
				       | USB_RECIP_INTERFACE,
				       USB_CDC_NCM_CRC_NOT_APPENDED,
				       iface_no, NULL, 0);
222
		if (err < 0)
223
			dev_dbg(&dev->intf->dev, "Setting CRC mode off failed\n");
224
	}
A
Alexey Orishko 已提交
225

226 227
	/* set NTB format, if both formats are supported */
	if (ntb_fmt_supported & USB_CDC_NCM_NTH32_SIGN) {
228 229 230 231 232
		err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
				       USB_TYPE_CLASS | USB_DIR_OUT
				       | USB_RECIP_INTERFACE,
				       USB_CDC_NCM_NTB16_FORMAT,
				       iface_no, NULL, 0);
233
		if (err < 0)
234
			dev_dbg(&dev->intf->dev, "Setting NTB format to 16-bit failed\n");
235
	}
A
Alexey Orishko 已提交
236

237 238 239 240 241 242 243 244 245 246 247
	/* inform the device about the selected Max Datagram Size */
	if (!(flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE))
		goto out;

	/* read current mtu value from device */
	err = usbnet_read_cmd(dev, USB_CDC_GET_MAX_DATAGRAM_SIZE,
			      USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE,
			      0, iface_no, &max_datagram_size, 2);
	if (err < 0) {
		dev_dbg(&dev->intf->dev, "GET_MAX_DATAGRAM_SIZE failed\n");
		goto out;
A
Alexey Orishko 已提交
248 249
	}

250 251 252 253 254 255 256 257 258
	if (le16_to_cpu(max_datagram_size) == ctx->max_datagram_size)
		goto out;

	max_datagram_size = cpu_to_le16(ctx->max_datagram_size);
	err = usbnet_write_cmd(dev, USB_CDC_SET_MAX_DATAGRAM_SIZE,
			       USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE,
			       0, iface_no, &max_datagram_size, 2);
	if (err < 0)
		dev_dbg(&dev->intf->dev, "SET_MAX_DATAGRAM_SIZE failed\n");
A
Alexey Orishko 已提交
259

260 261 262 263
out:
	/* set MTU to max supported by the device if necessary */
	if (dev->net->mtu > ctx->max_datagram_size - eth_hlen)
		dev->net->mtu = ctx->max_datagram_size - eth_hlen;
A
Alexey Orishko 已提交
264 265 266 267
	return 0;
}

static void
268
cdc_ncm_find_endpoints(struct usbnet *dev, struct usb_interface *intf)
A
Alexey Orishko 已提交
269
{
270
	struct usb_host_endpoint *e, *in = NULL, *out = NULL;
A
Alexey Orishko 已提交
271 272 273 274 275 276 277 278
	u8 ep;

	for (ep = 0; ep < intf->cur_altsetting->desc.bNumEndpoints; ep++) {

		e = intf->cur_altsetting->endpoint + ep;
		switch (e->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
		case USB_ENDPOINT_XFER_INT:
			if (usb_endpoint_dir_in(&e->desc)) {
279 280
				if (!dev->status)
					dev->status = e;
A
Alexey Orishko 已提交
281 282 283 284 285
			}
			break;

		case USB_ENDPOINT_XFER_BULK:
			if (usb_endpoint_dir_in(&e->desc)) {
286 287
				if (!in)
					in = e;
A
Alexey Orishko 已提交
288
			} else {
289 290
				if (!out)
					out = e;
A
Alexey Orishko 已提交
291 292 293 294 295 296 297
			}
			break;

		default:
			break;
		}
	}
298 299 300 301 302 303 304 305
	if (in && !dev->in)
		dev->in = usb_rcvbulkpipe(dev->udev,
					  in->desc.bEndpointAddress &
					  USB_ENDPOINT_NUMBER_MASK);
	if (out && !dev->out)
		dev->out = usb_sndbulkpipe(dev->udev,
					   out->desc.bEndpointAddress &
					   USB_ENDPOINT_NUMBER_MASK);
A
Alexey Orishko 已提交
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
}

static void cdc_ncm_free(struct cdc_ncm_ctx *ctx)
{
	if (ctx == NULL)
		return;

	if (ctx->tx_rem_skb != NULL) {
		dev_kfree_skb_any(ctx->tx_rem_skb);
		ctx->tx_rem_skb = NULL;
	}

	if (ctx->tx_curr_skb != NULL) {
		dev_kfree_skb_any(ctx->tx_curr_skb);
		ctx->tx_curr_skb = NULL;
	}

	kfree(ctx);
}

326
int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting)
A
Alexey Orishko 已提交
327
{
328
	const struct usb_cdc_union_desc *union_desc = NULL;
A
Alexey Orishko 已提交
329 330 331 332 333 334 335
	struct cdc_ncm_ctx *ctx;
	struct usb_driver *driver;
	u8 *buf;
	int len;
	int temp;
	u8 iface_no;

336
	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
337 338
	if (!ctx)
		return -ENOMEM;
A
Alexey Orishko 已提交
339

340 341
	hrtimer_init(&ctx->tx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	ctx->tx_timer.function = &cdc_ncm_tx_timer_cb;
342
	ctx->bh.data = (unsigned long)dev;
343 344
	ctx->bh.func = cdc_ncm_txpath_bh;
	atomic_set(&ctx->stop, 0);
A
Alexey Orishko 已提交
345 346 347 348 349
	spin_lock_init(&ctx->mtx);

	/* store ctx pointer in device data field */
	dev->data[0] = (unsigned long)ctx;

350 351 352
	/* only the control interface can be successfully probed */
	ctx->control = intf;

A
Alexey Orishko 已提交
353 354 355 356 357 358 359 360 361 362 363 364 365
	/* get some pointers */
	driver = driver_of(intf);
	buf = intf->cur_altsetting->extra;
	len = intf->cur_altsetting->extralen;

	/* parse through descriptors associated with control interface */
	while ((len > 0) && (buf[0] > 2) && (buf[0] <= len)) {

		if (buf[1] != USB_DT_CS_INTERFACE)
			goto advance;

		switch (buf[2]) {
		case USB_CDC_UNION_TYPE:
366
			if (buf[0] < sizeof(*union_desc))
A
Alexey Orishko 已提交
367 368
				break;

369
			union_desc = (const struct usb_cdc_union_desc *)buf;
370 371
			/* the master must be the interface we are probing */
			if (intf->cur_altsetting->desc.bInterfaceNumber !=
372 373
			    union_desc->bMasterInterface0) {
				dev_dbg(&intf->dev, "bogus CDC Union\n");
374
				goto error;
375
			}
A
Alexey Orishko 已提交
376
			ctx->data = usb_ifnum_to_if(dev->udev,
377
						    union_desc->bSlaveInterface0);
A
Alexey Orishko 已提交
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
			break;

		case USB_CDC_ETHERNET_TYPE:
			if (buf[0] < sizeof(*(ctx->ether_desc)))
				break;

			ctx->ether_desc =
					(const struct usb_cdc_ether_desc *)buf;
			break;

		case USB_CDC_NCM_TYPE:
			if (buf[0] < sizeof(*(ctx->func_desc)))
				break;

			ctx->func_desc = (const struct usb_cdc_ncm_desc *)buf;
			break;

395 396 397 398 399 400 401
		case USB_CDC_MBIM_TYPE:
			if (buf[0] < sizeof(*(ctx->mbim_desc)))
				break;

			ctx->mbim_desc = (const struct usb_cdc_mbim_desc *)buf;
			break;

A
Alexey Orishko 已提交
402 403 404 405 406 407 408 409 410 411
		default:
			break;
		}
advance:
		/* advance to next descriptor */
		temp = buf[0];
		buf += temp;
		len -= temp;
	}

412
	/* some buggy devices have an IAD but no CDC Union */
413
	if (!union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) {
414 415
		ctx->data = usb_ifnum_to_if(dev->udev, intf->cur_altsetting->desc.bInterfaceNumber + 1);
		dev_dbg(&intf->dev, "CDC Union missing - got slave from IAD\n");
416 417
	}

A
Alexey Orishko 已提交
418
	/* check if we got everything */
419 420
	if (!ctx->data || (!ctx->mbim_desc && !ctx->ether_desc)) {
		dev_dbg(&intf->dev, "CDC descriptors missing\n");
A
Alexey Orishko 已提交
421
		goto error;
422
	}
A
Alexey Orishko 已提交
423

B
Bjørn Mork 已提交
424 425 426
	/* claim data interface, if different from control */
	if (ctx->data != ctx->control) {
		temp = usb_driver_claim_interface(driver, ctx->data, dev);
427 428
		if (temp) {
			dev_dbg(&intf->dev, "failed to claim data intf\n");
B
Bjørn Mork 已提交
429
			goto error;
430
		}
B
Bjørn Mork 已提交
431
	}
A
Alexey Orishko 已提交
432 433 434 435 436

	iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber;

	/* reset data interface */
	temp = usb_set_interface(dev->udev, iface_no, 0);
437 438
	if (temp) {
		dev_dbg(&intf->dev, "set interface failed\n");
439
		goto error2;
440
	}
A
Alexey Orishko 已提交
441 442

	/* configure data interface */
443
	temp = usb_set_interface(dev->udev, iface_no, data_altsetting);
444 445
	if (temp) {
		dev_dbg(&intf->dev, "set interface failed\n");
446
		goto error2;
447
	}
A
Alexey Orishko 已提交
448

449 450
	cdc_ncm_find_endpoints(dev, ctx->data);
	cdc_ncm_find_endpoints(dev, ctx->control);
451 452
	if (!dev->in || !dev->out || !dev->status) {
		dev_dbg(&intf->dev, "failed to collect endpoints\n");
453
		goto error2;
454
	}
A
Alexey Orishko 已提交
455

B
Bjørn Mork 已提交
456
	/* initialize data interface */
457 458
	if (cdc_ncm_setup(dev))	{
		dev_dbg(&intf->dev, "cdc_ncm_setup() failed\n");
B
Bjørn Mork 已提交
459
		goto error2;
460
	}
B
Bjørn Mork 已提交
461

A
Alexey Orishko 已提交
462 463 464
	usb_set_intfdata(ctx->data, dev);
	usb_set_intfdata(ctx->control, dev);

465 466
	if (ctx->ether_desc) {
		temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
467 468
		if (temp) {
			dev_dbg(&intf->dev, "failed to get mac address\n");
469
			goto error2;
470 471
		}
		dev_info(&intf->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
472
	}
A
Alexey Orishko 已提交
473

474 475
	/* usbnet use these values for sizing tx/rx queues */
	dev->hard_mtu = ctx->tx_max;
A
Alexey Orishko 已提交
476 477 478 479
	dev->rx_urb_size = ctx->rx_max;

	return 0;

480 481 482
error2:
	usb_set_intfdata(ctx->control, NULL);
	usb_set_intfdata(ctx->data, NULL);
483 484
	if (ctx->data != ctx->control)
		usb_driver_release_interface(driver, ctx->data);
A
Alexey Orishko 已提交
485 486 487
error:
	cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]);
	dev->data[0] = 0;
488
	dev_info(&intf->dev, "bind() failure\n");
A
Alexey Orishko 已提交
489 490
	return -ENODEV;
}
491
EXPORT_SYMBOL_GPL(cdc_ncm_bind_common);
A
Alexey Orishko 已提交
492

493
void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
A
Alexey Orishko 已提交
494 495
{
	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
496
	struct usb_driver *driver = driver_of(intf);
A
Alexey Orishko 已提交
497 498 499 500

	if (ctx == NULL)
		return;		/* no setup */

501 502 503 504 505 506 507
	atomic_set(&ctx->stop, 1);

	if (hrtimer_active(&ctx->tx_timer))
		hrtimer_cancel(&ctx->tx_timer);

	tasklet_kill(&ctx->bh);

B
Bjørn Mork 已提交
508 509 510 511
	/* handle devices with combined control and data interface */
	if (ctx->control == ctx->data)
		ctx->data = NULL;

512 513 514
	/* disconnect master --> disconnect slave */
	if (intf == ctx->control && ctx->data) {
		usb_set_intfdata(ctx->data, NULL);
A
Alexey Orishko 已提交
515
		usb_driver_release_interface(driver, ctx->data);
516
		ctx->data = NULL;
A
Alexey Orishko 已提交
517

518 519
	} else if (intf == ctx->data && ctx->control) {
		usb_set_intfdata(ctx->control, NULL);
A
Alexey Orishko 已提交
520
		usb_driver_release_interface(driver, ctx->control);
521
		ctx->control = NULL;
A
Alexey Orishko 已提交
522 523
	}

524
	usb_set_intfdata(intf, NULL);
A
Alexey Orishko 已提交
525 526
	cdc_ncm_free(ctx);
}
527
EXPORT_SYMBOL_GPL(cdc_ncm_unbind);
A
Alexey Orishko 已提交
528

529 530 531 532
/* Select the MBIM altsetting iff it is preferred and available,
 * returning the number of the corresponding data interface altsetting
 */
u8 cdc_ncm_select_altsetting(struct usbnet *dev, struct usb_interface *intf)
533
{
534
	struct usb_host_interface *alt;
535

536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
	/* The MBIM spec defines a NCM compatible default altsetting,
	 * which we may have matched:
	 *
	 *  "Functions that implement both NCM 1.0 and MBIM (an
	 *   “NCM/MBIM function”) according to this recommendation
	 *   shall provide two alternate settings for the
	 *   Communication Interface.  Alternate setting 0, and the
	 *   associated class and endpoint descriptors, shall be
	 *   constructed according to the rules given for the
	 *   Communication Interface in section 5 of [USBNCM10].
	 *   Alternate setting 1, and the associated class and
	 *   endpoint descriptors, shall be constructed according to
	 *   the rules given in section 6 (USB Device Model) of this
	 *   specification."
	 */
551 552 553 554 555 556 557
	if (prefer_mbim && intf->num_altsetting == 2) {
		alt = usb_altnum_to_altsetting(intf, CDC_NCM_COMM_ALTSETTING_MBIM);
		if (alt && cdc_ncm_comm_intf_is_mbim(alt) &&
		    !usb_set_interface(dev->udev,
				       intf->cur_altsetting->desc.bInterfaceNumber,
				       CDC_NCM_COMM_ALTSETTING_MBIM))
			return CDC_NCM_DATA_ALTSETTING_MBIM;
558
	}
559 560 561 562 563 564 565 566 567 568 569 570
	return CDC_NCM_DATA_ALTSETTING_NCM;
}
EXPORT_SYMBOL_GPL(cdc_ncm_select_altsetting);

static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
{
	int ret;

	/* MBIM backwards compatible function? */
	cdc_ncm_select_altsetting(dev, intf);
	if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
		return -ENODEV;
571

572 573 574 575 576 577 578 579 580
	/* NCM data altsetting is always 1 */
	ret = cdc_ncm_bind_common(dev, intf, 1);

	/*
	 * We should get an event when network connection is "connected" or
	 * "disconnected". Set network connection in "disconnected" state
	 * (carrier is OFF) during attach, so the IP network stack does not
	 * start IPv6 negotiation and more.
	 */
581
	usbnet_link_change(dev, 0, 0);
582 583 584
	return ret;
}

585
static void cdc_ncm_align_tail(struct sk_buff *skb, size_t modulus, size_t remainder, size_t max)
A
Alexey Orishko 已提交
586
{
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629
	size_t align = ALIGN(skb->len, modulus) - skb->len + remainder;

	if (skb->len + align > max)
		align = max - skb->len;
	if (align && skb_tailroom(skb) >= align)
		memset(skb_put(skb, align), 0, align);
}

/* return a pointer to a valid struct usb_cdc_ncm_ndp16 of type sign, possibly
 * allocating a new one within skb
 */
static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign, size_t reserve)
{
	struct usb_cdc_ncm_ndp16 *ndp16 = NULL;
	struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data;
	size_t ndpoffset = le16_to_cpu(nth16->wNdpIndex);

	/* follow the chain of NDPs, looking for a match */
	while (ndpoffset) {
		ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset);
		if  (ndp16->dwSignature == sign)
			return ndp16;
		ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
	}

	/* align new NDP */
	cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max);

	/* verify that there is room for the NDP and the datagram (reserve) */
	if ((ctx->tx_max - skb->len - reserve) < CDC_NCM_NDP_SIZE)
		return NULL;

	/* link to it */
	if (ndp16)
		ndp16->wNextNdpIndex = cpu_to_le16(skb->len);
	else
		nth16->wNdpIndex = cpu_to_le16(skb->len);

	/* push a new empty NDP */
	ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, CDC_NCM_NDP_SIZE), 0, CDC_NCM_NDP_SIZE);
	ndp16->dwSignature = sign;
	ndp16->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16));
	return ndp16;
A
Alexey Orishko 已提交
630 631
}

632
struct sk_buff *
633
cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
A
Alexey Orishko 已提交
634
{
635
	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
636 637
	struct usb_cdc_ncm_nth16 *nth16;
	struct usb_cdc_ncm_ndp16 *ndp16;
A
Alexey Orishko 已提交
638
	struct sk_buff *skb_out;
639
	u16 n = 0, index, ndplen;
640
	u8 ready2send = 0;
A
Alexey Orishko 已提交
641 642

	/* if there is a remaining skb, it gets priority */
643
	if (skb != NULL) {
A
Alexey Orishko 已提交
644
		swap(skb, ctx->tx_rem_skb);
645 646
		swap(sign, ctx->tx_rem_sign);
	} else {
647
		ready2send = 1;
648
	}
A
Alexey Orishko 已提交
649 650

	/* check if we are resuming an OUT skb */
651
	skb_out = ctx->tx_curr_skb;
A
Alexey Orishko 已提交
652

653 654
	/* allocate a new OUT skb */
	if (!skb_out) {
655
		skb_out = alloc_skb(ctx->tx_max, GFP_ATOMIC);
A
Alexey Orishko 已提交
656 657 658
		if (skb_out == NULL) {
			if (skb != NULL) {
				dev_kfree_skb_any(skb);
659
				dev->net->stats.tx_dropped++;
A
Alexey Orishko 已提交
660 661 662
			}
			goto exit_no_skb;
		}
663 664 665 666 667
		/* fill out the initial 16-bit NTB header */
		nth16 = (struct usb_cdc_ncm_nth16 *)memset(skb_put(skb_out, sizeof(struct usb_cdc_ncm_nth16)), 0, sizeof(struct usb_cdc_ncm_nth16));
		nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
		nth16->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16));
		nth16->wSequence = cpu_to_le16(ctx->tx_seq++);
A
Alexey Orishko 已提交
668

669
		/* count total number of frames in this NTB */
A
Alexey Orishko 已提交
670 671 672
		ctx->tx_curr_frame_num = 0;
	}

673 674
	for (n = ctx->tx_curr_frame_num; n < ctx->tx_max_datagrams; n++) {
		/* send any remaining skb first */
A
Alexey Orishko 已提交
675 676
		if (skb == NULL) {
			skb = ctx->tx_rem_skb;
677
			sign = ctx->tx_rem_sign;
A
Alexey Orishko 已提交
678 679 680 681 682 683 684
			ctx->tx_rem_skb = NULL;

			/* check for end of skb */
			if (skb == NULL)
				break;
		}

685 686 687 688 689 690 691 692
		/* get the appropriate NDP for this skb */
		ndp16 = cdc_ncm_ndp(ctx, skb_out, sign, skb->len + ctx->tx_modulus + ctx->tx_remainder);

		/* align beginning of next frame */
		cdc_ncm_align_tail(skb_out,  ctx->tx_modulus, ctx->tx_remainder, ctx->tx_max);

		/* check if we had enough room left for both NDP and frame */
		if (!ndp16 || skb_out->len + skb->len > ctx->tx_max) {
A
Alexey Orishko 已提交
693 694 695 696
			if (n == 0) {
				/* won't fit, MTU problem? */
				dev_kfree_skb_any(skb);
				skb = NULL;
697
				dev->net->stats.tx_dropped++;
A
Alexey Orishko 已提交
698 699 700 701
			} else {
				/* no room for skb - store for later */
				if (ctx->tx_rem_skb != NULL) {
					dev_kfree_skb_any(ctx->tx_rem_skb);
702
					dev->net->stats.tx_dropped++;
A
Alexey Orishko 已提交
703 704
				}
				ctx->tx_rem_skb = skb;
705
				ctx->tx_rem_sign = sign;
A
Alexey Orishko 已提交
706
				skb = NULL;
707
				ready2send = 1;
A
Alexey Orishko 已提交
708 709 710 711
			}
			break;
		}

712 713 714
		/* calculate frame number withing this NDP */
		ndplen = le16_to_cpu(ndp16->wLength);
		index = (ndplen - sizeof(struct usb_cdc_ncm_ndp16)) / sizeof(struct usb_cdc_ncm_dpe16) - 1;
A
Alexey Orishko 已提交
715

716 717 718 719 720
		/* OK, add this skb */
		ndp16->dpe16[index].wDatagramLength = cpu_to_le16(skb->len);
		ndp16->dpe16[index].wDatagramIndex = cpu_to_le16(skb_out->len);
		ndp16->wLength = cpu_to_le16(ndplen + sizeof(struct usb_cdc_ncm_dpe16));
		memcpy(skb_put(skb_out, skb->len), skb->data, skb->len);
A
Alexey Orishko 已提交
721 722
		dev_kfree_skb_any(skb);
		skb = NULL;
723 724 725 726 727 728

		/* send now if this NDP is full */
		if (index >= CDC_NCM_DPT_DATAGRAMS_MAX) {
			ready2send = 1;
			break;
		}
A
Alexey Orishko 已提交
729 730 731 732 733 734
	}

	/* free up any dangling skb */
	if (skb != NULL) {
		dev_kfree_skb_any(skb);
		skb = NULL;
735
		dev->net->stats.tx_dropped++;
A
Alexey Orishko 已提交
736 737 738 739 740 741 742 743 744 745
	}

	ctx->tx_curr_frame_num = n;

	if (n == 0) {
		/* wait for more frames */
		/* push variables */
		ctx->tx_curr_skb = skb_out;
		goto exit_no_skb;

746
	} else if ((n < ctx->tx_max_datagrams) && (ready2send == 0)) {
A
Alexey Orishko 已提交
747 748 749 750 751
		/* wait for more frames */
		/* push variables */
		ctx->tx_curr_skb = skb_out;
		/* set the pending count */
		if (n < CDC_NCM_RESTART_TIMER_DATAGRAM_CNT)
752
			ctx->tx_timer_pending = CDC_NCM_TIMER_PENDING_CNT;
A
Alexey Orishko 已提交
753 754 755 756 757 758 759
		goto exit_no_skb;

	} else {
		/* frame goes out */
		/* variables will be reset at next call */
	}

760 761 762 763 764
	/* If collected data size is less or equal CDC_NCM_MIN_TX_PKT
	 * bytes, we send buffers as it is. If we get more data, it
	 * would be more efficient for USB HS mobile device with DMA
	 * engine to receive a full size NTB, than canceling DMA
	 * transfer and receiving a short packet.
765 766 767
	 *
	 * This optimization support is pointless if we end up sending
	 * a ZLP after full sized NTBs.
A
Alexey Orishko 已提交
768
	 */
769 770
	if (!(dev->driver_info->flags & FLAG_SEND_ZLP) &&
	    skb_out->len > CDC_NCM_MIN_TX_PKT)
771 772 773
		memset(skb_put(skb_out, ctx->tx_max - skb_out->len), 0,
		       ctx->tx_max - skb_out->len);
	else if ((skb_out->len % dev->maxpacket) == 0)
774
		*skb_put(skb_out, 1) = 0;	/* force short packet */
A
Alexey Orishko 已提交
775

776 777 778
	/* set final frame length */
	nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
	nth16->wBlockLength = cpu_to_le16(skb_out->len);
A
Alexey Orishko 已提交
779 780 781

	/* return skb */
	ctx->tx_curr_skb = NULL;
782
	dev->net->stats.tx_packets += ctx->tx_curr_frame_num;
A
Alexey Orishko 已提交
783 784 785
	return skb_out;

exit_no_skb:
786 787 788
	/* Start timer, if there is a remaining skb */
	if (ctx->tx_curr_skb != NULL)
		cdc_ncm_tx_timeout_start(ctx);
A
Alexey Orishko 已提交
789 790
	return NULL;
}
791
EXPORT_SYMBOL_GPL(cdc_ncm_fill_tx_frame);
A
Alexey Orishko 已提交
792 793 794 795

static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx)
{
	/* start timer, if not already started */
796 797 798 799
	if (!(hrtimer_active(&ctx->tx_timer) || atomic_read(&ctx->stop)))
		hrtimer_start(&ctx->tx_timer,
				ktime_set(0, CDC_NCM_TIMER_INTERVAL),
				HRTIMER_MODE_REL);
A
Alexey Orishko 已提交
800 801
}

802
static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *timer)
A
Alexey Orishko 已提交
803
{
804 805
	struct cdc_ncm_ctx *ctx =
			container_of(timer, struct cdc_ncm_ctx, tx_timer);
A
Alexey Orishko 已提交
806

807 808 809 810
	if (!atomic_read(&ctx->stop))
		tasklet_schedule(&ctx->bh);
	return HRTIMER_NORESTART;
}
A
Alexey Orishko 已提交
811

812 813
static void cdc_ncm_txpath_bh(unsigned long param)
{
814 815
	struct usbnet *dev = (struct usbnet *)param;
	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
A
Alexey Orishko 已提交
816

817 818 819
	spin_lock_bh(&ctx->mtx);
	if (ctx->tx_timer_pending != 0) {
		ctx->tx_timer_pending--;
A
Alexey Orishko 已提交
820
		cdc_ncm_tx_timeout_start(ctx);
821
		spin_unlock_bh(&ctx->mtx);
822
	} else if (dev->net != NULL) {
823
		spin_unlock_bh(&ctx->mtx);
824 825 826
		netif_tx_lock_bh(dev->net);
		usbnet_start_xmit(NULL, dev->net);
		netif_tx_unlock_bh(dev->net);
B
Bjørn Mork 已提交
827 828
	} else {
		spin_unlock_bh(&ctx->mtx);
829
	}
A
Alexey Orishko 已提交
830 831
}

832
struct sk_buff *
A
Alexey Orishko 已提交
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
{
	struct sk_buff *skb_out;
	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];

	/*
	 * The Ethernet API we are using does not support transmitting
	 * multiple Ethernet frames in a single call. This driver will
	 * accumulate multiple Ethernet frames and send out a larger
	 * USB frame when the USB buffer is full or when a single jiffies
	 * timeout happens.
	 */
	if (ctx == NULL)
		goto error;

848
	spin_lock_bh(&ctx->mtx);
849
	skb_out = cdc_ncm_fill_tx_frame(dev, skb, cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN));
850
	spin_unlock_bh(&ctx->mtx);
A
Alexey Orishko 已提交
851 852 853 854 855 856 857 858
	return skb_out;

error:
	if (skb != NULL)
		dev_kfree_skb_any(skb);

	return NULL;
}
859
EXPORT_SYMBOL_GPL(cdc_ncm_tx_fixup);
A
Alexey Orishko 已提交
860

861
/* verify NTB header and return offset of first NDP, or negative error */
862
int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in)
A
Alexey Orishko 已提交
863
{
864
	struct usbnet *dev = netdev_priv(skb_in->dev);
865
	struct usb_cdc_ncm_nth16 *nth16;
866 867
	int len;
	int ret = -EINVAL;
A
Alexey Orishko 已提交
868 869 870 871

	if (ctx == NULL)
		goto error;

872 873
	if (skb_in->len < (sizeof(struct usb_cdc_ncm_nth16) +
					sizeof(struct usb_cdc_ncm_ndp16))) {
874
		netif_dbg(dev, rx_err, dev->net, "frame too short\n");
A
Alexey Orishko 已提交
875 876 877
		goto error;
	}

878
	nth16 = (struct usb_cdc_ncm_nth16 *)skb_in->data;
A
Alexey Orishko 已提交
879

880
	if (nth16->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH16_SIGN)) {
B
Bjørn Mork 已提交
881 882 883
		netif_dbg(dev, rx_err, dev->net,
			  "invalid NTH16 signature <%#010x>\n",
			  le32_to_cpu(nth16->dwSignature));
A
Alexey Orishko 已提交
884 885 886
		goto error;
	}

887 888
	len = le16_to_cpu(nth16->wBlockLength);
	if (len > ctx->rx_max) {
889 890 891
		netif_dbg(dev, rx_err, dev->net,
			  "unsupported NTB block length %u/%u\n", len,
			  ctx->rx_max);
A
Alexey Orishko 已提交
892 893 894
		goto error;
	}

895
	if ((ctx->rx_seq + 1) != le16_to_cpu(nth16->wSequence) &&
896 897 898 899 900
	    (ctx->rx_seq || le16_to_cpu(nth16->wSequence)) &&
	    !((ctx->rx_seq == 0xffff) && !le16_to_cpu(nth16->wSequence))) {
		netif_dbg(dev, rx_err, dev->net,
			  "sequence number glitch prev=%d curr=%d\n",
			  ctx->rx_seq, le16_to_cpu(nth16->wSequence));
901 902 903
	}
	ctx->rx_seq = le16_to_cpu(nth16->wSequence);

904 905 906 907
	ret = le16_to_cpu(nth16->wNdpIndex);
error:
	return ret;
}
908
EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_nth16);
909 910

/* verify NDP header and return number of datagrams, or negative error */
911
int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset)
912
{
913
	struct usbnet *dev = netdev_priv(skb_in->dev);
914 915 916
	struct usb_cdc_ncm_ndp16 *ndp16;
	int ret = -EINVAL;

B
Bjørn Mork 已提交
917
	if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
918 919
		netif_dbg(dev, rx_err, dev->net, "invalid NDP offset  <%u>\n",
			  ndpoffset);
A
Alexey Orishko 已提交
920 921
		goto error;
	}
B
Bjørn Mork 已提交
922
	ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
A
Alexey Orishko 已提交
923

924
	if (le16_to_cpu(ndp16->wLength) < USB_CDC_NCM_NDP16_LENGTH_MIN) {
925 926
		netif_dbg(dev, rx_err, dev->net, "invalid DPT16 length <%u>\n",
			  le16_to_cpu(ndp16->wLength));
927
		goto error;
A
Alexey Orishko 已提交
928 929
	}

930
	ret = ((le16_to_cpu(ndp16->wLength) -
A
Alexey Orishko 已提交
931 932
					sizeof(struct usb_cdc_ncm_ndp16)) /
					sizeof(struct usb_cdc_ncm_dpe16));
933
	ret--; /* we process NDP entries except for the last one */
A
Alexey Orishko 已提交
934

935 936 937
	if ((sizeof(struct usb_cdc_ncm_ndp16) +
	     ret * (sizeof(struct usb_cdc_ncm_dpe16))) > skb_in->len) {
		netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret);
938
		ret = -EINVAL;
A
Alexey Orishko 已提交
939 940
	}

941 942 943
error:
	return ret;
}
944
EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp16);
945

946
int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969
{
	struct sk_buff *skb;
	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
	int len;
	int nframes;
	int x;
	int offset;
	struct usb_cdc_ncm_ndp16 *ndp16;
	struct usb_cdc_ncm_dpe16 *dpe16;
	int ndpoffset;
	int loopcount = 50; /* arbitrary max preventing infinite loop */

	ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
	if (ndpoffset < 0)
		goto error;

next_ndp:
	nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
	if (nframes < 0)
		goto error;

	ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);

970
	if (ndp16->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN)) {
B
Bjørn Mork 已提交
971 972 973
		netif_dbg(dev, rx_err, dev->net,
			  "invalid DPT16 signature <%#010x>\n",
			  le32_to_cpu(ndp16->dwSignature));
974 975 976
		goto err_ndp;
	}
	dpe16 = ndp16->dpe16;
A
Alexey Orishko 已提交
977

978 979 980
	for (x = 0; x < nframes; x++, dpe16++) {
		offset = le16_to_cpu(dpe16->wDatagramIndex);
		len = le16_to_cpu(dpe16->wDatagramLength);
A
Alexey Orishko 已提交
981 982 983 984 985

		/*
		 * CDC NCM ch. 3.7
		 * All entries after first NULL entry are to be ignored
		 */
986
		if ((offset == 0) || (len == 0)) {
A
Alexey Orishko 已提交
987
			if (!x)
B
Bjørn Mork 已提交
988
				goto err_ndp; /* empty NTB */
A
Alexey Orishko 已提交
989 990 991 992
			break;
		}

		/* sanity checking */
993 994
		if (((offset + len) > skb_in->len) ||
				(len > ctx->rx_max) || (len < ETH_HLEN)) {
995 996 997
			netif_dbg(dev, rx_err, dev->net,
				  "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n",
				  x, offset, len, skb_in);
A
Alexey Orishko 已提交
998
			if (!x)
B
Bjørn Mork 已提交
999
				goto err_ndp;
A
Alexey Orishko 已提交
1000 1001 1002 1003
			break;

		} else {
			skb = skb_clone(skb_in, GFP_ATOMIC);
1004 1005
			if (!skb)
				goto error;
1006
			skb->len = len;
A
Alexey Orishko 已提交
1007
			skb->data = ((u8 *)skb_in->data) + offset;
1008
			skb_set_tail_pointer(skb, len);
A
Alexey Orishko 已提交
1009 1010 1011
			usbnet_skb_return(dev, skb);
		}
	}
B
Bjørn Mork 已提交
1012 1013 1014 1015 1016 1017
err_ndp:
	/* are there more NDPs to process? */
	ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
	if (ndpoffset && loopcount--)
		goto next_ndp;

A
Alexey Orishko 已提交
1018 1019 1020 1021
	return 1;
error:
	return 0;
}
1022
EXPORT_SYMBOL_GPL(cdc_ncm_rx_fixup);
A
Alexey Orishko 已提交
1023 1024

static void
1025
cdc_ncm_speed_change(struct usbnet *dev,
1026
		     struct usb_cdc_speed_change *data)
A
Alexey Orishko 已提交
1027
{
1028 1029
	uint32_t rx_speed = le32_to_cpu(data->DLBitRRate);
	uint32_t tx_speed = le32_to_cpu(data->ULBitRate);
A
Alexey Orishko 已提交
1030 1031 1032 1033 1034

	/*
	 * Currently the USB-NET API does not support reporting the actual
	 * device speed. Do print it instead.
	 */
1035
	if ((tx_speed > 1000000) && (rx_speed > 1000000)) {
1036 1037
		netif_info(dev, link, dev->net,
		       "%u mbit/s downlink %u mbit/s uplink\n",
1038 1039 1040
		       (unsigned int)(rx_speed / 1000000U),
		       (unsigned int)(tx_speed / 1000000U));
	} else {
1041 1042
		netif_info(dev, link, dev->net,
		       "%u kbit/s downlink %u kbit/s uplink\n",
1043 1044
		       (unsigned int)(rx_speed / 1000U),
		       (unsigned int)(tx_speed / 1000U));
A
Alexey Orishko 已提交
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
	}
}

static void cdc_ncm_status(struct usbnet *dev, struct urb *urb)
{
	struct cdc_ncm_ctx *ctx;
	struct usb_cdc_notification *event;

	ctx = (struct cdc_ncm_ctx *)dev->data[0];

	if (urb->actual_length < sizeof(*event))
		return;

	/* test for split data in 8-byte chunks */
	if (test_and_clear_bit(EVENT_STS_SPLIT, &dev->flags)) {
1060
		cdc_ncm_speed_change(dev,
1061
		      (struct usb_cdc_speed_change *)urb->transfer_buffer);
A
Alexey Orishko 已提交
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
		return;
	}

	event = urb->transfer_buffer;

	switch (event->bNotificationType) {
	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
		/*
		 * According to the CDC NCM specification ch.7.1
		 * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be
		 * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE.
		 */
B
Bjørn Mork 已提交
1074
		ctx->connected = le16_to_cpu(event->wValue);
1075 1076 1077
		netif_info(dev, link, dev->net,
			   "network connection: %sconnected\n",
			   ctx->connected ? "" : "dis");
1078
		usbnet_link_change(dev, ctx->connected, 0);
A
Alexey Orishko 已提交
1079 1080 1081
		break;

	case USB_CDC_NOTIFY_SPEED_CHANGE:
1082 1083
		if (urb->actual_length < (sizeof(*event) +
					sizeof(struct usb_cdc_speed_change)))
A
Alexey Orishko 已提交
1084 1085
			set_bit(EVENT_STS_SPLIT, &dev->flags);
		else
1086 1087
			cdc_ncm_speed_change(dev,
					     (struct usb_cdc_speed_change *)&event[1]);
A
Alexey Orishko 已提交
1088 1089 1090
		break;

	default:
1091 1092 1093
		dev_dbg(&dev->udev->dev,
			"NCM: unexpected notification 0x%02x!\n",
			event->bNotificationType);
A
Alexey Orishko 已提交
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
		break;
	}
}

static int cdc_ncm_check_connect(struct usbnet *dev)
{
	struct cdc_ncm_ctx *ctx;

	ctx = (struct cdc_ncm_ctx *)dev->data[0];
	if (ctx == NULL)
		return 1;	/* disconnected */

	return !ctx->connected;
}

static const struct driver_info cdc_ncm_info = {
	.description = "CDC NCM",
1111
	.flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET,
A
Alexey Orishko 已提交
1112 1113 1114
	.bind = cdc_ncm_bind,
	.unbind = cdc_ncm_unbind,
	.check_connect = cdc_ncm_check_connect,
O
Oliver Neukum 已提交
1115
	.manage_power = usbnet_manage_power,
A
Alexey Orishko 已提交
1116 1117 1118 1119 1120
	.status = cdc_ncm_status,
	.rx_fixup = cdc_ncm_rx_fixup,
	.tx_fixup = cdc_ncm_tx_fixup,
};

1121 1122 1123 1124 1125 1126 1127 1128
/* Same as cdc_ncm_info, but with FLAG_WWAN */
static const struct driver_info wwan_info = {
	.description = "Mobile Broadband Network Device",
	.flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
			| FLAG_WWAN,
	.bind = cdc_ncm_bind,
	.unbind = cdc_ncm_unbind,
	.check_connect = cdc_ncm_check_connect,
O
Oliver Neukum 已提交
1129
	.manage_power = usbnet_manage_power,
1130 1131 1132 1133 1134
	.status = cdc_ncm_status,
	.rx_fixup = cdc_ncm_rx_fixup,
	.tx_fixup = cdc_ncm_tx_fixup,
};

1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
/* Same as wwan_info, but with FLAG_NOARP  */
static const struct driver_info wwan_noarp_info = {
	.description = "Mobile Broadband Network Device (NO ARP)",
	.flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
			| FLAG_WWAN | FLAG_NOARP,
	.bind = cdc_ncm_bind,
	.unbind = cdc_ncm_unbind,
	.check_connect = cdc_ncm_check_connect,
	.manage_power = usbnet_manage_power,
	.status = cdc_ncm_status,
	.rx_fixup = cdc_ncm_rx_fixup,
	.tx_fixup = cdc_ncm_tx_fixup,
};

1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
static const struct usb_device_id cdc_devs[] = {
	/* Ericsson MBM devices like F5521gw */
	{ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
		| USB_DEVICE_ID_MATCH_VENDOR,
	  .idVendor = 0x0bdb,
	  .bInterfaceClass = USB_CLASS_COMM,
	  .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM,
	  .bInterfaceProtocol = USB_CDC_PROTO_NONE,
	  .driver_info = (unsigned long) &wwan_info,
	},

1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
	/* Dell branded MBM devices like DW5550 */
	{ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
		| USB_DEVICE_ID_MATCH_VENDOR,
	  .idVendor = 0x413c,
	  .bInterfaceClass = USB_CLASS_COMM,
	  .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM,
	  .bInterfaceProtocol = USB_CDC_PROTO_NONE,
	  .driver_info = (unsigned long) &wwan_info,
	},

	/* Toshiba branded MBM devices */
	{ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
		| USB_DEVICE_ID_MATCH_VENDOR,
	  .idVendor = 0x0930,
	  .bInterfaceClass = USB_CLASS_COMM,
	  .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM,
	  .bInterfaceProtocol = USB_CDC_PROTO_NONE,
	  .driver_info = (unsigned long) &wwan_info,
	},

1180 1181 1182 1183 1184 1185 1186 1187
	/* tag Huawei devices as wwan */
	{ USB_VENDOR_AND_INTERFACE_INFO(0x12d1,
					USB_CLASS_COMM,
					USB_CDC_SUBCLASS_NCM,
					USB_CDC_PROTO_NONE),
	  .driver_info = (unsigned long)&wwan_info,
	},

1188 1189 1190 1191 1192 1193 1194
	/* Infineon(now Intel) HSPA Modem platform */
	{ USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443,
		USB_CLASS_COMM,
		USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
	  .driver_info = (unsigned long)&wwan_noarp_info,
	},

1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
	/* Generic CDC-NCM devices */
	{ USB_INTERFACE_INFO(USB_CLASS_COMM,
		USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
		.driver_info = (unsigned long)&cdc_ncm_info,
	},
	{
	},
};
MODULE_DEVICE_TABLE(usb, cdc_devs);

A
Alexey Orishko 已提交
1205 1206 1207
static struct usb_driver cdc_ncm_driver = {
	.name = "cdc_ncm",
	.id_table = cdc_devs,
1208 1209
	.probe = usbnet_probe,
	.disconnect = usbnet_disconnect,
A
Alexey Orishko 已提交
1210 1211
	.suspend = usbnet_suspend,
	.resume = usbnet_resume,
1212
	.reset_resume =	usbnet_resume,
A
Alexey Orishko 已提交
1213
	.supports_autosuspend = 1,
1214
	.disable_hub_initiated_lpm = 1,
A
Alexey Orishko 已提交
1215 1216
};

1217
module_usb_driver(cdc_ncm_driver);
A
Alexey Orishko 已提交
1218 1219 1220 1221

MODULE_AUTHOR("Hans Petter Selasky");
MODULE_DESCRIPTION("USB CDC NCM host driver");
MODULE_LICENSE("Dual BSD/GPL");