cdc_ncm.c 35.8 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];
A
Alexey Orishko 已提交
71 72 73 74
	u32 val;
	u8 flags;
	u8 iface_no;
	int err;
75
	int eth_hlen;
76
	u16 mbim_mtu;
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,
85 86
			      0, iface_no, &ctx->ncm_parm,
			      sizeof(ctx->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 */
93 94 95 96 97
	ctx->rx_max = le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize);
	ctx->tx_max = le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize);
	ctx->tx_remainder = le16_to_cpu(ctx->ncm_parm.wNdpOutPayloadRemainder);
	ctx->tx_modulus = le16_to_cpu(ctx->ncm_parm.wNdpOutDivisor);
	ctx->tx_ndp_modulus = le16_to_cpu(ctx->ncm_parm.wNdpOutAlignment);
98
	/* devices prior to NCM Errata shall set this field to zero */
99 100
	ctx->tx_max_datagrams = le16_to_cpu(ctx->ncm_parm.wNtbOutMaxDatagrams);
	ntb_fmt_supported = le16_to_cpu(ctx->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 */
149
	if (ctx->rx_max != le32_to_cpu(ctx->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 165 166 167 168 169 170 171 172 173 174 175 176
		ctx->tx_max = CDC_NCM_NTB_MAX_SIZE_TX;
	}

	/*
	 * 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)) {
177
		dev_dbg(&dev->intf->dev, "Using default alignment: 4 bytes\n");
A
Alexey Orishko 已提交
178 179 180 181 182 183 184 185 186 187 188 189 190
		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)) {
191
		dev_dbg(&dev->intf->dev, "Using default transmit modulus: 4 bytes\n");
A
Alexey Orishko 已提交
192 193 194 195 196
		ctx->tx_modulus = USB_CDC_NCM_NDP_ALIGN_MIN_SIZE;
	}

	/* verify the payload remainder */
	if (ctx->tx_remainder >= ctx->tx_modulus) {
197
		dev_dbg(&dev->intf->dev, "Using default transmit remainder: 0 bytes\n");
A
Alexey Orishko 已提交
198 199 200 201
		ctx->tx_remainder = 0;
	}

	/* adjust TX-remainder according to NCM specification. */
202 203
	ctx->tx_remainder = ((ctx->tx_remainder - eth_hlen) &
			     (ctx->tx_modulus - 1));
A
Alexey Orishko 已提交
204 205 206 207

	/* additional configuration */

	/* set CRC Mode */
208
	if (flags & USB_CDC_NCM_NCAP_CRC_MODE) {
209 210 211 212 213
		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);
214
		if (err < 0)
215
			dev_dbg(&dev->intf->dev, "Setting CRC mode off failed\n");
216
	}
A
Alexey Orishko 已提交
217

218 219
	/* set NTB format, if both formats are supported */
	if (ntb_fmt_supported & USB_CDC_NCM_NTH32_SIGN) {
220 221 222 223 224
		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);
225
		if (err < 0)
226
			dev_dbg(&dev->intf->dev, "Setting NTB format to 16-bit failed\n");
227
	}
A
Alexey Orishko 已提交
228

229 230 231 232 233 234 235 236 237 238 239
	/* 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 已提交
240 241
	}

242 243 244 245 246 247 248 249 250
	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 已提交
251

252 253 254 255
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;
256 257 258 259 260 261 262 263

	/* do not exceed operater preferred MTU */
	if (ctx->mbim_extended_desc) {
		mbim_mtu = le16_to_cpu(ctx->mbim_extended_desc->wMTU);
		if (mbim_mtu != 0 && mbim_mtu < dev->net->mtu)
			dev->net->mtu = mbim_mtu;
	}

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;

402 403 404 405 406 407 408 409
		case USB_CDC_MBIM_EXTENDED_TYPE:
			if (buf[0] < sizeof(*(ctx->mbim_extended_desc)))
				break;

			ctx->mbim_extended_desc =
				(const struct usb_cdc_mbim_extended_desc *)buf;
			break;

A
Alexey Orishko 已提交
410 411 412 413 414 415 416 417 418 419
		default:
			break;
		}
advance:
		/* advance to next descriptor */
		temp = buf[0];
		buf += temp;
		len -= temp;
	}

420
	/* some buggy devices have an IAD but no CDC Union */
421
	if (!union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) {
422 423
		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");
424 425
	}

A
Alexey Orishko 已提交
426
	/* check if we got everything */
427 428
	if (!ctx->data || (!ctx->mbim_desc && !ctx->ether_desc)) {
		dev_dbg(&intf->dev, "CDC descriptors missing\n");
A
Alexey Orishko 已提交
429
		goto error;
430
	}
A
Alexey Orishko 已提交
431

B
Bjørn Mork 已提交
432 433 434
	/* claim data interface, if different from control */
	if (ctx->data != ctx->control) {
		temp = usb_driver_claim_interface(driver, ctx->data, dev);
435 436
		if (temp) {
			dev_dbg(&intf->dev, "failed to claim data intf\n");
B
Bjørn Mork 已提交
437
			goto error;
438
		}
B
Bjørn Mork 已提交
439
	}
A
Alexey Orishko 已提交
440 441 442 443 444

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

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

450 451 452 453
	/* initialize data interface */
	if (cdc_ncm_setup(dev))
		goto error2;

A
Alexey Orishko 已提交
454
	/* configure data interface */
455
	temp = usb_set_interface(dev->udev, iface_no, data_altsetting);
456 457
	if (temp) {
		dev_dbg(&intf->dev, "set interface failed\n");
458
		goto error2;
459
	}
A
Alexey Orishko 已提交
460

461 462
	cdc_ncm_find_endpoints(dev, ctx->data);
	cdc_ncm_find_endpoints(dev, ctx->control);
463 464
	if (!dev->in || !dev->out || !dev->status) {
		dev_dbg(&intf->dev, "failed to collect endpoints\n");
465
		goto error2;
466
	}
A
Alexey Orishko 已提交
467 468 469 470

	usb_set_intfdata(ctx->data, dev);
	usb_set_intfdata(ctx->control, dev);

471 472
	if (ctx->ether_desc) {
		temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
473 474
		if (temp) {
			dev_dbg(&intf->dev, "failed to get mac address\n");
475
			goto error2;
476 477
		}
		dev_info(&intf->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
478
	}
A
Alexey Orishko 已提交
479

480 481
	/* usbnet use these values for sizing tx/rx queues */
	dev->hard_mtu = ctx->tx_max;
A
Alexey Orishko 已提交
482 483
	dev->rx_urb_size = ctx->rx_max;

484 485 486 487 488 489 490 491 492
	/* cdc_ncm_setup will override dwNtbOutMaxSize if it is
	 * outside the sane range. Adding a pad byte here if necessary
	 * simplifies the handling in cdc_ncm_fill_tx_frame, making
	 * tx_max always represent the real skb max size.
	 */
	if (ctx->tx_max != le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize) &&
	    ctx->tx_max % usb_maxpacket(dev->udev, dev->out, 1) == 0)
		ctx->tx_max++;

A
Alexey Orishko 已提交
493 494
	return 0;

495 496 497
error2:
	usb_set_intfdata(ctx->control, NULL);
	usb_set_intfdata(ctx->data, NULL);
498 499
	if (ctx->data != ctx->control)
		usb_driver_release_interface(driver, ctx->data);
A
Alexey Orishko 已提交
500 501 502
error:
	cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]);
	dev->data[0] = 0;
503
	dev_info(&intf->dev, "bind() failure\n");
A
Alexey Orishko 已提交
504 505
	return -ENODEV;
}
506
EXPORT_SYMBOL_GPL(cdc_ncm_bind_common);
A
Alexey Orishko 已提交
507

508
void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
A
Alexey Orishko 已提交
509 510
{
	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
511
	struct usb_driver *driver = driver_of(intf);
A
Alexey Orishko 已提交
512 513 514 515

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

516 517 518 519 520 521 522
	atomic_set(&ctx->stop, 1);

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

	tasklet_kill(&ctx->bh);

B
Bjørn Mork 已提交
523 524 525 526
	/* handle devices with combined control and data interface */
	if (ctx->control == ctx->data)
		ctx->data = NULL;

527 528 529
	/* disconnect master --> disconnect slave */
	if (intf == ctx->control && ctx->data) {
		usb_set_intfdata(ctx->data, NULL);
A
Alexey Orishko 已提交
530
		usb_driver_release_interface(driver, ctx->data);
531
		ctx->data = NULL;
A
Alexey Orishko 已提交
532

533 534
	} else if (intf == ctx->data && ctx->control) {
		usb_set_intfdata(ctx->control, NULL);
A
Alexey Orishko 已提交
535
		usb_driver_release_interface(driver, ctx->control);
536
		ctx->control = NULL;
A
Alexey Orishko 已提交
537 538
	}

539
	usb_set_intfdata(intf, NULL);
A
Alexey Orishko 已提交
540 541
	cdc_ncm_free(ctx);
}
542
EXPORT_SYMBOL_GPL(cdc_ncm_unbind);
A
Alexey Orishko 已提交
543

544 545 546 547
/* 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)
548
{
549
	struct usb_host_interface *alt;
550

551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
	/* 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."
	 */
566 567 568 569 570 571 572
	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;
573
	}
574 575 576 577 578 579 580 581 582 583 584 585
	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;
586

587 588 589 590 591 592 593 594 595
	/* 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.
	 */
596
	usbnet_link_change(dev, 0, 0);
597 598 599
	return ret;
}

600
static void cdc_ncm_align_tail(struct sk_buff *skb, size_t modulus, size_t remainder, size_t max)
A
Alexey Orishko 已提交
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 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
	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 已提交
645 646
}

647
struct sk_buff *
648
cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
A
Alexey Orishko 已提交
649
{
650
	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
651 652
	struct usb_cdc_ncm_nth16 *nth16;
	struct usb_cdc_ncm_ndp16 *ndp16;
A
Alexey Orishko 已提交
653
	struct sk_buff *skb_out;
654
	u16 n = 0, index, ndplen;
655
	u8 ready2send = 0;
A
Alexey Orishko 已提交
656 657

	/* if there is a remaining skb, it gets priority */
658
	if (skb != NULL) {
A
Alexey Orishko 已提交
659
		swap(skb, ctx->tx_rem_skb);
660 661
		swap(sign, ctx->tx_rem_sign);
	} else {
662
		ready2send = 1;
663
	}
A
Alexey Orishko 已提交
664 665

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

668 669
	/* allocate a new OUT skb */
	if (!skb_out) {
670
		skb_out = alloc_skb(ctx->tx_max, GFP_ATOMIC);
A
Alexey Orishko 已提交
671 672 673
		if (skb_out == NULL) {
			if (skb != NULL) {
				dev_kfree_skb_any(skb);
674
				dev->net->stats.tx_dropped++;
A
Alexey Orishko 已提交
675 676 677
			}
			goto exit_no_skb;
		}
678 679 680 681 682
		/* 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 已提交
683

684
		/* count total number of frames in this NTB */
A
Alexey Orishko 已提交
685 686 687
		ctx->tx_curr_frame_num = 0;
	}

688 689
	for (n = ctx->tx_curr_frame_num; n < ctx->tx_max_datagrams; n++) {
		/* send any remaining skb first */
A
Alexey Orishko 已提交
690 691
		if (skb == NULL) {
			skb = ctx->tx_rem_skb;
692
			sign = ctx->tx_rem_sign;
A
Alexey Orishko 已提交
693 694 695 696 697 698 699
			ctx->tx_rem_skb = NULL;

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

700 701 702 703 704 705 706 707
		/* 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 已提交
708 709 710 711
			if (n == 0) {
				/* won't fit, MTU problem? */
				dev_kfree_skb_any(skb);
				skb = NULL;
712
				dev->net->stats.tx_dropped++;
A
Alexey Orishko 已提交
713 714 715 716
			} else {
				/* no room for skb - store for later */
				if (ctx->tx_rem_skb != NULL) {
					dev_kfree_skb_any(ctx->tx_rem_skb);
717
					dev->net->stats.tx_dropped++;
A
Alexey Orishko 已提交
718 719
				}
				ctx->tx_rem_skb = skb;
720
				ctx->tx_rem_sign = sign;
A
Alexey Orishko 已提交
721
				skb = NULL;
722
				ready2send = 1;
A
Alexey Orishko 已提交
723 724 725 726
			}
			break;
		}

727 728 729
		/* 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 已提交
730

731 732 733 734 735
		/* 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 已提交
736 737
		dev_kfree_skb_any(skb);
		skb = NULL;
738 739 740 741 742 743

		/* send now if this NDP is full */
		if (index >= CDC_NCM_DPT_DATAGRAMS_MAX) {
			ready2send = 1;
			break;
		}
A
Alexey Orishko 已提交
744 745 746 747 748 749
	}

	/* free up any dangling skb */
	if (skb != NULL) {
		dev_kfree_skb_any(skb);
		skb = NULL;
750
		dev->net->stats.tx_dropped++;
A
Alexey Orishko 已提交
751 752 753 754 755 756 757 758 759 760
	}

	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;

761
	} else if ((n < ctx->tx_max_datagrams) && (ready2send == 0)) {
A
Alexey Orishko 已提交
762 763 764 765 766
		/* wait for more frames */
		/* push variables */
		ctx->tx_curr_skb = skb_out;
		/* set the pending count */
		if (n < CDC_NCM_RESTART_TIMER_DATAGRAM_CNT)
767
			ctx->tx_timer_pending = CDC_NCM_TIMER_PENDING_CNT;
A
Alexey Orishko 已提交
768 769 770 771 772 773 774
		goto exit_no_skb;

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

775 776 777 778 779
	/* 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.
780 781 782
	 *
	 * This optimization support is pointless if we end up sending
	 * a ZLP after full sized NTBs.
A
Alexey Orishko 已提交
783
	 */
784 785
	if (!(dev->driver_info->flags & FLAG_SEND_ZLP) &&
	    skb_out->len > CDC_NCM_MIN_TX_PKT)
786 787 788
		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)
789
		*skb_put(skb_out, 1) = 0;	/* force short packet */
A
Alexey Orishko 已提交
790

791 792 793
	/* set final frame length */
	nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
	nth16->wBlockLength = cpu_to_le16(skb_out->len);
A
Alexey Orishko 已提交
794 795 796

	/* return skb */
	ctx->tx_curr_skb = NULL;
797
	dev->net->stats.tx_packets += ctx->tx_curr_frame_num;
A
Alexey Orishko 已提交
798 799 800
	return skb_out;

exit_no_skb:
801 802 803
	/* Start timer, if there is a remaining skb */
	if (ctx->tx_curr_skb != NULL)
		cdc_ncm_tx_timeout_start(ctx);
A
Alexey Orishko 已提交
804 805
	return NULL;
}
806
EXPORT_SYMBOL_GPL(cdc_ncm_fill_tx_frame);
A
Alexey Orishko 已提交
807 808 809 810

static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx)
{
	/* start timer, if not already started */
811 812 813 814
	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 已提交
815 816
}

817
static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *timer)
A
Alexey Orishko 已提交
818
{
819 820
	struct cdc_ncm_ctx *ctx =
			container_of(timer, struct cdc_ncm_ctx, tx_timer);
A
Alexey Orishko 已提交
821

822 823 824 825
	if (!atomic_read(&ctx->stop))
		tasklet_schedule(&ctx->bh);
	return HRTIMER_NORESTART;
}
A
Alexey Orishko 已提交
826

827 828
static void cdc_ncm_txpath_bh(unsigned long param)
{
829 830
	struct usbnet *dev = (struct usbnet *)param;
	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
A
Alexey Orishko 已提交
831

832 833 834
	spin_lock_bh(&ctx->mtx);
	if (ctx->tx_timer_pending != 0) {
		ctx->tx_timer_pending--;
A
Alexey Orishko 已提交
835
		cdc_ncm_tx_timeout_start(ctx);
836
		spin_unlock_bh(&ctx->mtx);
837
	} else if (dev->net != NULL) {
838
		spin_unlock_bh(&ctx->mtx);
839 840 841
		netif_tx_lock_bh(dev->net);
		usbnet_start_xmit(NULL, dev->net);
		netif_tx_unlock_bh(dev->net);
B
Bjørn Mork 已提交
842 843
	} else {
		spin_unlock_bh(&ctx->mtx);
844
	}
A
Alexey Orishko 已提交
845 846
}

847
struct sk_buff *
A
Alexey Orishko 已提交
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862
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;

863
	spin_lock_bh(&ctx->mtx);
864
	skb_out = cdc_ncm_fill_tx_frame(dev, skb, cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN));
865
	spin_unlock_bh(&ctx->mtx);
A
Alexey Orishko 已提交
866 867 868 869 870 871 872 873
	return skb_out;

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

	return NULL;
}
874
EXPORT_SYMBOL_GPL(cdc_ncm_tx_fixup);
A
Alexey Orishko 已提交
875

876
/* verify NTB header and return offset of first NDP, or negative error */
877
int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in)
A
Alexey Orishko 已提交
878
{
879
	struct usbnet *dev = netdev_priv(skb_in->dev);
880
	struct usb_cdc_ncm_nth16 *nth16;
881 882
	int len;
	int ret = -EINVAL;
A
Alexey Orishko 已提交
883 884 885 886

	if (ctx == NULL)
		goto error;

887 888
	if (skb_in->len < (sizeof(struct usb_cdc_ncm_nth16) +
					sizeof(struct usb_cdc_ncm_ndp16))) {
889
		netif_dbg(dev, rx_err, dev->net, "frame too short\n");
A
Alexey Orishko 已提交
890 891 892
		goto error;
	}

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

895
	if (nth16->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH16_SIGN)) {
B
Bjørn Mork 已提交
896 897 898
		netif_dbg(dev, rx_err, dev->net,
			  "invalid NTH16 signature <%#010x>\n",
			  le32_to_cpu(nth16->dwSignature));
A
Alexey Orishko 已提交
899 900 901
		goto error;
	}

902 903
	len = le16_to_cpu(nth16->wBlockLength);
	if (len > ctx->rx_max) {
904 905 906
		netif_dbg(dev, rx_err, dev->net,
			  "unsupported NTB block length %u/%u\n", len,
			  ctx->rx_max);
A
Alexey Orishko 已提交
907 908 909
		goto error;
	}

910
	if ((ctx->rx_seq + 1) != le16_to_cpu(nth16->wSequence) &&
911 912 913 914 915
	    (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));
916 917 918
	}
	ctx->rx_seq = le16_to_cpu(nth16->wSequence);

919 920 921 922
	ret = le16_to_cpu(nth16->wNdpIndex);
error:
	return ret;
}
923
EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_nth16);
924 925

/* verify NDP header and return number of datagrams, or negative error */
926
int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset)
927
{
928
	struct usbnet *dev = netdev_priv(skb_in->dev);
929 930 931
	struct usb_cdc_ncm_ndp16 *ndp16;
	int ret = -EINVAL;

B
Bjørn Mork 已提交
932
	if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
933 934
		netif_dbg(dev, rx_err, dev->net, "invalid NDP offset  <%u>\n",
			  ndpoffset);
A
Alexey Orishko 已提交
935 936
		goto error;
	}
B
Bjørn Mork 已提交
937
	ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
A
Alexey Orishko 已提交
938

939
	if (le16_to_cpu(ndp16->wLength) < USB_CDC_NCM_NDP16_LENGTH_MIN) {
940 941
		netif_dbg(dev, rx_err, dev->net, "invalid DPT16 length <%u>\n",
			  le16_to_cpu(ndp16->wLength));
942
		goto error;
A
Alexey Orishko 已提交
943 944
	}

945
	ret = ((le16_to_cpu(ndp16->wLength) -
A
Alexey Orishko 已提交
946 947
					sizeof(struct usb_cdc_ncm_ndp16)) /
					sizeof(struct usb_cdc_ncm_dpe16));
948
	ret--; /* we process NDP entries except for the last one */
A
Alexey Orishko 已提交
949

950 951 952
	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);
953
		ret = -EINVAL;
A
Alexey Orishko 已提交
954 955
	}

956 957 958
error:
	return ret;
}
959
EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp16);
960

961
int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984
{
	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);

985
	if (ndp16->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN)) {
B
Bjørn Mork 已提交
986 987 988
		netif_dbg(dev, rx_err, dev->net,
			  "invalid DPT16 signature <%#010x>\n",
			  le32_to_cpu(ndp16->dwSignature));
989 990 991
		goto err_ndp;
	}
	dpe16 = ndp16->dpe16;
A
Alexey Orishko 已提交
992

993 994 995
	for (x = 0; x < nframes; x++, dpe16++) {
		offset = le16_to_cpu(dpe16->wDatagramIndex);
		len = le16_to_cpu(dpe16->wDatagramLength);
A
Alexey Orishko 已提交
996 997 998 999 1000

		/*
		 * CDC NCM ch. 3.7
		 * All entries after first NULL entry are to be ignored
		 */
1001
		if ((offset == 0) || (len == 0)) {
A
Alexey Orishko 已提交
1002
			if (!x)
B
Bjørn Mork 已提交
1003
				goto err_ndp; /* empty NTB */
A
Alexey Orishko 已提交
1004 1005 1006 1007
			break;
		}

		/* sanity checking */
1008 1009
		if (((offset + len) > skb_in->len) ||
				(len > ctx->rx_max) || (len < ETH_HLEN)) {
1010 1011 1012
			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 已提交
1013
			if (!x)
B
Bjørn Mork 已提交
1014
				goto err_ndp;
A
Alexey Orishko 已提交
1015 1016 1017 1018
			break;

		} else {
			skb = skb_clone(skb_in, GFP_ATOMIC);
1019 1020
			if (!skb)
				goto error;
1021
			skb->len = len;
A
Alexey Orishko 已提交
1022
			skb->data = ((u8 *)skb_in->data) + offset;
1023
			skb_set_tail_pointer(skb, len);
A
Alexey Orishko 已提交
1024 1025 1026
			usbnet_skb_return(dev, skb);
		}
	}
B
Bjørn Mork 已提交
1027 1028 1029 1030 1031 1032
err_ndp:
	/* are there more NDPs to process? */
	ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
	if (ndpoffset && loopcount--)
		goto next_ndp;

A
Alexey Orishko 已提交
1033 1034 1035 1036
	return 1;
error:
	return 0;
}
1037
EXPORT_SYMBOL_GPL(cdc_ncm_rx_fixup);
A
Alexey Orishko 已提交
1038 1039

static void
1040
cdc_ncm_speed_change(struct usbnet *dev,
1041
		     struct usb_cdc_speed_change *data)
A
Alexey Orishko 已提交
1042
{
1043 1044
	uint32_t rx_speed = le32_to_cpu(data->DLBitRRate);
	uint32_t tx_speed = le32_to_cpu(data->ULBitRate);
A
Alexey Orishko 已提交
1045 1046 1047 1048 1049

	/*
	 * Currently the USB-NET API does not support reporting the actual
	 * device speed. Do print it instead.
	 */
1050
	if ((tx_speed > 1000000) && (rx_speed > 1000000)) {
1051 1052
		netif_info(dev, link, dev->net,
		       "%u mbit/s downlink %u mbit/s uplink\n",
1053 1054 1055
		       (unsigned int)(rx_speed / 1000000U),
		       (unsigned int)(tx_speed / 1000000U));
	} else {
1056 1057
		netif_info(dev, link, dev->net,
		       "%u kbit/s downlink %u kbit/s uplink\n",
1058 1059
		       (unsigned int)(rx_speed / 1000U),
		       (unsigned int)(tx_speed / 1000U));
A
Alexey Orishko 已提交
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
	}
}

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)) {
1075
		cdc_ncm_speed_change(dev,
1076
		      (struct usb_cdc_speed_change *)urb->transfer_buffer);
A
Alexey Orishko 已提交
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
		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 已提交
1089
		ctx->connected = le16_to_cpu(event->wValue);
1090 1091 1092
		netif_info(dev, link, dev->net,
			   "network connection: %sconnected\n",
			   ctx->connected ? "" : "dis");
1093
		usbnet_link_change(dev, ctx->connected, 0);
A
Alexey Orishko 已提交
1094 1095 1096
		break;

	case USB_CDC_NOTIFY_SPEED_CHANGE:
1097 1098
		if (urb->actual_length < (sizeof(*event) +
					sizeof(struct usb_cdc_speed_change)))
A
Alexey Orishko 已提交
1099 1100
			set_bit(EVENT_STS_SPLIT, &dev->flags);
		else
1101 1102
			cdc_ncm_speed_change(dev,
					     (struct usb_cdc_speed_change *)&event[1]);
A
Alexey Orishko 已提交
1103 1104 1105
		break;

	default:
1106 1107 1108
		dev_dbg(&dev->udev->dev,
			"NCM: unexpected notification 0x%02x!\n",
			event->bNotificationType);
A
Alexey Orishko 已提交
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
		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",
1126
	.flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET,
A
Alexey Orishko 已提交
1127 1128 1129
	.bind = cdc_ncm_bind,
	.unbind = cdc_ncm_unbind,
	.check_connect = cdc_ncm_check_connect,
O
Oliver Neukum 已提交
1130
	.manage_power = usbnet_manage_power,
A
Alexey Orishko 已提交
1131 1132 1133 1134 1135
	.status = cdc_ncm_status,
	.rx_fixup = cdc_ncm_rx_fixup,
	.tx_fixup = cdc_ncm_tx_fixup,
};

1136 1137 1138 1139 1140 1141 1142 1143
/* 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 已提交
1144
	.manage_power = usbnet_manage_power,
1145 1146 1147 1148 1149
	.status = cdc_ncm_status,
	.rx_fixup = cdc_ncm_rx_fixup,
	.tx_fixup = cdc_ncm_tx_fixup,
};

1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
/* 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,
};

1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
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,
	},

1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194
	/* 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,
	},

1195 1196 1197 1198 1199 1200 1201 1202
	/* 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,
	},

1203 1204 1205 1206 1207 1208 1209
	/* 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,
	},

1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
	/* 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 已提交
1220 1221 1222
static struct usb_driver cdc_ncm_driver = {
	.name = "cdc_ncm",
	.id_table = cdc_devs,
1223 1224
	.probe = usbnet_probe,
	.disconnect = usbnet_disconnect,
A
Alexey Orishko 已提交
1225 1226
	.suspend = usbnet_suspend,
	.resume = usbnet_resume,
1227
	.reset_resume =	usbnet_resume,
A
Alexey Orishko 已提交
1228
	.supports_autosuspend = 1,
1229
	.disable_hub_initiated_lpm = 1,
A
Alexey Orishko 已提交
1230 1231
};

1232
module_usb_driver(cdc_ncm_driver);
A
Alexey Orishko 已提交
1233 1234 1235 1236

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