Lines Matching +full:merge +full:- +full:fifo +full:- +full:en

1 // SPDX-License-Identifier: GPL-2.0+
3 * f_ncm.c -- USB CDC Network (NCM) link function driver
10 * Copyright (C) 2003-2005,2008 David Brownell
31 * NCM is intended to be used with high-speed network attachments.
38 /* to trigger crc/non-crc ndp signature */
72 /* For multi-frame NDP TX */
84 /*-------------------------------------------------------------------------*/
88 * one max-size ethernet frame.
416 .language = 0x0409, /* en-us */
429 * in NDP32 -- 2 16bit words wide. Also signatures are different.
516 /*-------------------------------------------------------------------------*/
520 ncm->parser_opts = &ndp16_opts; in ncm_reset_values()
521 ncm->is_crc = false; in ncm_reset_values()
522 ncm->ndp_sign = ncm->parser_opts->ndp_sign; in ncm_reset_values()
523 ncm->port.cdc_filter = DEFAULT_FILTER; in ncm_reset_values()
526 ncm->port.header_len = 0; in ncm_reset_values()
528 ncm->port.fixed_out_len = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize); in ncm_reset_values()
529 ncm->port.fixed_in_len = NTB_DEFAULT_IN_SIZE; in ncm_reset_values()
533 * Context: ncm->lock held
537 struct usb_request *req = ncm->notify_req; in ncm_do_notify()
539 struct usb_composite_dev *cdev = ncm->port.func.config->cdev; in ncm_do_notify()
544 if (atomic_read(&ncm->notify_count)) in ncm_do_notify()
547 event = req->buf; in ncm_do_notify()
548 switch (ncm->notify_state) { in ncm_do_notify()
553 event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION; in ncm_do_notify()
554 if (ncm->is_open) in ncm_do_notify()
555 event->wValue = cpu_to_le16(1); in ncm_do_notify()
557 event->wValue = cpu_to_le16(0); in ncm_do_notify()
558 event->wLength = 0; in ncm_do_notify()
559 req->length = sizeof *event; in ncm_do_notify()
562 str_true_false(ncm->is_open)); in ncm_do_notify()
563 ncm->notify_state = NCM_NOTIFY_NONE; in ncm_do_notify()
567 event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE; in ncm_do_notify()
568 event->wValue = cpu_to_le16(0); in ncm_do_notify()
569 event->wLength = cpu_to_le16(8); in ncm_do_notify()
570 req->length = NCM_STATUS_BYTECOUNT; in ncm_do_notify()
573 data = req->buf + sizeof *event; in ncm_do_notify()
574 data[0] = cpu_to_le32(gether_bitrate(cdev->gadget)); in ncm_do_notify()
577 DBG(cdev, "notify speed %u\n", gether_bitrate(cdev->gadget)); in ncm_do_notify()
578 ncm->notify_state = NCM_NOTIFY_CONNECT; in ncm_do_notify()
581 event->bmRequestType = 0xA1; in ncm_do_notify()
582 event->wIndex = cpu_to_le16(ncm->ctrl_id); in ncm_do_notify()
584 atomic_inc(&ncm->notify_count); in ncm_do_notify()
587 * In double buffering if there is a space in FIFO, in ncm_do_notify()
591 spin_unlock(&ncm->lock); in ncm_do_notify()
592 status = usb_ep_queue(ncm->notify, req, GFP_ATOMIC); in ncm_do_notify()
593 spin_lock(&ncm->lock); in ncm_do_notify()
595 atomic_dec(&ncm->notify_count); in ncm_do_notify()
596 DBG(cdev, "notify --> %d\n", status); in ncm_do_notify()
601 * Context: ncm->lock held
606 * NOTE on most versions of Linux, host side cdc-ethernet in ncm_notify()
608 * The first notification then sits in the FIFO for a long in ncm_notify()
615 ncm->notify_state = NCM_NOTIFY_SPEED; in ncm_notify()
621 struct f_ncm *ncm = req->context; in ncm_notify_complete()
622 struct usb_composite_dev *cdev = ncm->port.func.config->cdev; in ncm_notify_complete()
623 struct usb_cdc_notification *event = req->buf; in ncm_notify_complete()
625 spin_lock(&ncm->lock); in ncm_notify_complete()
626 switch (req->status) { in ncm_notify_complete()
629 event->bNotificationType); in ncm_notify_complete()
630 atomic_dec(&ncm->notify_count); in ncm_notify_complete()
632 case -ECONNRESET: in ncm_notify_complete()
633 case -ESHUTDOWN: in ncm_notify_complete()
634 atomic_set(&ncm->notify_count, 0); in ncm_notify_complete()
635 ncm->notify_state = NCM_NOTIFY_NONE; in ncm_notify_complete()
638 DBG(cdev, "event %02x --> %d\n", in ncm_notify_complete()
639 event->bNotificationType, req->status); in ncm_notify_complete()
640 atomic_dec(&ncm->notify_count); in ncm_notify_complete()
644 spin_unlock(&ncm->lock); in ncm_notify_complete()
651 struct usb_function *f = req->context; in ncm_ep0out_complete()
653 struct usb_composite_dev *cdev = f->config->cdev; in ncm_ep0out_complete()
655 req->context = NULL; in ncm_ep0out_complete()
656 if (req->status || req->actual != req->length) { in ncm_ep0out_complete()
657 DBG(cdev, "Bad control-OUT transfer\n"); in ncm_ep0out_complete()
661 in_size = get_unaligned_le32(req->buf); in ncm_ep0out_complete()
668 ncm->port.fixed_in_len = in_size; in ncm_ep0out_complete()
680 struct usb_composite_dev *cdev = f->config->cdev; in ncm_setup()
681 struct usb_request *req = cdev->req; in ncm_setup()
682 int value = -EOPNOTSUPP; in ncm_setup()
683 u16 w_index = le16_to_cpu(ctrl->wIndex); in ncm_setup()
684 u16 w_value = le16_to_cpu(ctrl->wValue); in ncm_setup()
685 u16 w_length = le16_to_cpu(ctrl->wLength); in ncm_setup()
691 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { in ncm_setup()
698 if (w_length != 0 || w_index != ncm->ctrl_id) in ncm_setup()
706 ncm->port.cdc_filter = w_value; in ncm_setup()
722 if (w_length == 0 || w_value != 0 || w_index != ncm->ctrl_id) in ncm_setup()
726 memcpy(req->buf, &ntb_parameters, value); in ncm_setup()
733 if (w_length < 4 || w_value != 0 || w_index != ncm->ctrl_id) in ncm_setup()
735 put_unaligned_le32(ncm->port.fixed_in_len, req->buf); in ncm_setup()
738 ncm->port.fixed_in_len); in ncm_setup()
744 if (w_length != 4 || w_value != 0 || w_index != ncm->ctrl_id) in ncm_setup()
746 req->complete = ncm_ep0out_complete; in ncm_setup()
747 req->length = w_length; in ncm_setup()
748 req->context = f; in ncm_setup()
750 value = req->length; in ncm_setup()
759 if (w_length < 2 || w_value != 0 || w_index != ncm->ctrl_id) in ncm_setup()
761 format = (ncm->parser_opts == &ndp16_opts) ? 0x0000 : 0x0001; in ncm_setup()
762 put_unaligned_le16(format, req->buf); in ncm_setup()
771 if (w_length != 0 || w_index != ncm->ctrl_id) in ncm_setup()
775 ncm->parser_opts = &ndp16_opts; in ncm_setup()
779 ncm->parser_opts = &ndp32_opts; in ncm_setup()
793 if (w_length < 2 || w_value != 0 || w_index != ncm->ctrl_id) in ncm_setup()
795 is_crc = ncm->is_crc ? 0x0001 : 0x0000; in ncm_setup()
796 put_unaligned_le16(is_crc, req->buf); in ncm_setup()
805 if (w_length != 0 || w_index != ncm->ctrl_id) in ncm_setup()
809 ncm->is_crc = false; in ncm_setup()
810 DBG(cdev, "non-CRC mode selected\n"); in ncm_setup()
813 ncm->is_crc = true; in ncm_setup()
832 ctrl->bRequestType, ctrl->bRequest, in ncm_setup()
835 ncm->ndp_sign = ncm->parser_opts->ndp_sign | in ncm_setup()
836 (ncm->is_crc ? NCM_NDP_HDR_CRC : 0); in ncm_setup()
841 ctrl->bRequestType, ctrl->bRequest, in ncm_setup()
843 req->zero = 0; in ncm_setup()
844 req->length = value; in ncm_setup()
845 value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); in ncm_setup()
848 ctrl->bRequestType, ctrl->bRequest, in ncm_setup()
860 struct usb_composite_dev *cdev = f->config->cdev; in ncm_set_alt()
863 if (intf == ncm->ctrl_id) { in ncm_set_alt()
868 usb_ep_disable(ncm->notify); in ncm_set_alt()
870 if (!(ncm->notify->desc)) { in ncm_set_alt()
872 if (config_ep_by_speed(cdev->gadget, f, ncm->notify)) in ncm_set_alt()
875 usb_ep_enable(ncm->notify); in ncm_set_alt()
878 } else if (intf == ncm->data_id) { in ncm_set_alt()
882 if (ncm->netdev) { in ncm_set_alt()
884 ncm->netdev = NULL; in ncm_set_alt()
885 gether_disconnect(&ncm->port); in ncm_set_alt()
890 * CDC Network only sends data in non-default altsettings. in ncm_set_alt()
896 if (!ncm->port.in_ep->desc || in ncm_set_alt()
897 !ncm->port.out_ep->desc) { in ncm_set_alt()
899 if (config_ep_by_speed(cdev->gadget, f, in ncm_set_alt()
900 ncm->port.in_ep) || in ncm_set_alt()
901 config_ep_by_speed(cdev->gadget, f, in ncm_set_alt()
902 ncm->port.out_ep)) { in ncm_set_alt()
903 ncm->port.in_ep->desc = NULL; in ncm_set_alt()
904 ncm->port.out_ep->desc = NULL; in ncm_set_alt()
913 ncm->port.is_zlp_ok = in ncm_set_alt()
914 gadget_is_zlp_supported(cdev->gadget); in ncm_set_alt()
915 ncm->port.cdc_filter = DEFAULT_FILTER; in ncm_set_alt()
917 net = gether_connect(&ncm->port); in ncm_set_alt()
920 ncm->netdev = net; in ncm_set_alt()
923 spin_lock(&ncm->lock); in ncm_set_alt()
925 spin_unlock(&ncm->lock); in ncm_set_alt()
931 return -EINVAL; in ncm_set_alt()
942 if (intf == ncm->ctrl_id) in ncm_get_alt()
944 return ncm->port.in_ep->enabled ? 1 : 0; in ncm_get_alt()
955 const struct ndp_parser_opts *opts = ncm->parser_opts; in package_for_tx()
957 const int dgram_idx_len = 2 * 2 * opts->dgram_item_len; in package_for_tx()
960 hrtimer_try_to_cancel(&ncm->task_timer); in package_for_tx()
962 ndp_pad = ALIGN(ncm->skb_tx_data->len, ndp_align) - in package_for_tx()
963 ncm->skb_tx_data->len; in package_for_tx()
964 ndp_index = ncm->skb_tx_data->len + ndp_pad; in package_for_tx()
965 new_len = ndp_index + dgram_idx_len + ncm->skb_tx_ndp->len; in package_for_tx()
968 ntb_iter = (void *) ncm->skb_tx_data->data; in package_for_tx()
971 put_ncm(&ntb_iter, opts->block_length, new_len); in package_for_tx()
972 put_ncm(&ntb_iter, opts->ndp_index, ndp_index); in package_for_tx()
975 new_len = opts->ndp_size + in package_for_tx()
976 (ncm->ndp_dgram_count * dgram_idx_len); in package_for_tx()
977 ncm->ndp_dgram_count = 0; in package_for_tx()
979 ntb_iter = (void *) ncm->skb_tx_ndp->data; in package_for_tx()
983 /* Merge the skbs */ in package_for_tx()
984 swap(skb2, ncm->skb_tx_data); in package_for_tx()
985 if (ncm->skb_tx_data) { in package_for_tx()
986 dev_consume_skb_any(ncm->skb_tx_data); in package_for_tx()
987 ncm->skb_tx_data = NULL; in package_for_tx()
994 skb_put_data(skb2, ncm->skb_tx_ndp->data, ncm->skb_tx_ndp->len); in package_for_tx()
995 dev_consume_skb_any(ncm->skb_tx_ndp); in package_for_tx()
996 ncm->skb_tx_ndp = NULL; in package_for_tx()
1007 struct f_ncm *ncm = func_to_ncm(&port->func); in ncm_wrap_ntb()
1016 unsigned max_size = ncm->port.fixed_in_len; in ncm_wrap_ntb()
1017 const struct ndp_parser_opts *opts = ncm->parser_opts; in ncm_wrap_ntb()
1021 const int dgram_idx_len = 2 * 2 * opts->dgram_item_len; in ncm_wrap_ntb()
1024 if (ncm->is_crc) { in ncm_wrap_ntb()
1029 skb->data, in ncm_wrap_ntb()
1030 skb->len); in ncm_wrap_ntb()
1040 if (ncm->skb_tx_data in ncm_wrap_ntb()
1041 && (ncm->ndp_dgram_count >= TX_MAX_NUM_DPE in ncm_wrap_ntb()
1042 || (ncm->skb_tx_data->len + in ncm_wrap_ntb()
1043 div + rem + skb->len + in ncm_wrap_ntb()
1044 ncm->skb_tx_ndp->len + ndp_align + (2 * dgram_idx_len)) in ncm_wrap_ntb()
1051 if (!ncm->skb_tx_data) { in ncm_wrap_ntb()
1052 ncb_len = opts->nth_size; in ncm_wrap_ntb()
1053 dgram_pad = ALIGN(ncb_len, div) + rem - ncb_len; in ncm_wrap_ntb()
1057 ncm->skb_tx_data = alloc_skb(max_size, GFP_ATOMIC); in ncm_wrap_ntb()
1058 if (!ncm->skb_tx_data) in ncm_wrap_ntb()
1061 ncm->skb_tx_data->dev = ncm->netdev; in ncm_wrap_ntb()
1062 ntb_data = skb_put_zero(ncm->skb_tx_data, ncb_len); in ncm_wrap_ntb()
1064 put_unaligned_le32(opts->nth_sign, ntb_data); in ncm_wrap_ntb()
1067 put_unaligned_le16(opts->nth_size, ntb_data++); in ncm_wrap_ntb()
1073 ncm->skb_tx_ndp = alloc_skb((int)(opts->ndp_size in ncm_wrap_ntb()
1074 + opts->dpe_size in ncm_wrap_ntb()
1077 if (!ncm->skb_tx_ndp) in ncm_wrap_ntb()
1080 ncm->skb_tx_ndp->dev = ncm->netdev; in ncm_wrap_ntb()
1081 ntb_ndp = skb_put(ncm->skb_tx_ndp, opts->ndp_size); in ncm_wrap_ntb()
1084 put_unaligned_le32(ncm->ndp_sign, ntb_ndp); in ncm_wrap_ntb()
1088 ncm->ndp_dgram_count = 1; in ncm_wrap_ntb()
1090 /* Note: we skip opts->next_ndp_index */ in ncm_wrap_ntb()
1093 hrtimer_start(&ncm->task_timer, TX_TIMEOUT_NSECS, in ncm_wrap_ntb()
1098 ntb_ndp = skb_put_zero(ncm->skb_tx_ndp, dgram_idx_len); in ncm_wrap_ntb()
1100 ncb_len = ncm->skb_tx_data->len; in ncm_wrap_ntb()
1101 dgram_pad = ALIGN(ncb_len, div) + rem - ncb_len; in ncm_wrap_ntb()
1105 put_ncm(&ntb_ndp, opts->dgram_item_len, ncb_len); in ncm_wrap_ntb()
1107 put_ncm(&ntb_ndp, opts->dgram_item_len, skb->len); in ncm_wrap_ntb()
1108 ncm->ndp_dgram_count++; in ncm_wrap_ntb()
1111 skb_put_zero(ncm->skb_tx_data, dgram_pad); in ncm_wrap_ntb()
1112 skb_put_data(ncm->skb_tx_data, skb->data, skb->len); in ncm_wrap_ntb()
1116 } else if (ncm->skb_tx_data) { in ncm_wrap_ntb()
1119 * ncm_tx_timeout() - hence, this is our signal to flush/send. in ncm_wrap_ntb()
1129 ncm->netdev->stats.tx_dropped++; in ncm_wrap_ntb()
1133 if (ncm->skb_tx_data) in ncm_wrap_ntb()
1134 dev_kfree_skb_any(ncm->skb_tx_data); in ncm_wrap_ntb()
1135 if (ncm->skb_tx_ndp) in ncm_wrap_ntb()
1136 dev_kfree_skb_any(ncm->skb_tx_ndp); in ncm_wrap_ntb()
1148 struct net_device *netdev = READ_ONCE(ncm->netdev); in ncm_tx_timeout()
1153 * XXX that the dev->wrap() invocations to build SKBs is transparent in ncm_tx_timeout()
1159 netdev->netdev_ops->ndo_start_xmit(NULL, netdev); in ncm_tx_timeout()
1168 struct f_ncm *ncm = func_to_ncm(&port->func); in ncm_unwrap_ntb()
1169 unsigned char *ntb_ptr = skb->data; in ncm_unwrap_ntb()
1177 int ret = -EINVAL; in ncm_unwrap_ntb()
1180 const struct ndp_parser_opts *opts = ncm->parser_opts; in ncm_unwrap_ntb()
1181 unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0; in ncm_unwrap_ntb()
1183 int to_process = skb->len; in ncm_unwrap_ntb()
1186 ncm_opts = container_of(port->func.fi, struct f_ncm_opts, func_inst); in ncm_unwrap_ntb()
1187 frame_max = ncm_opts->max_segment_size; in ncm_unwrap_ntb()
1193 if (get_unaligned_le32(tmp) != opts->nth_sign) { in ncm_unwrap_ntb()
1194 INFO(port->func.config->cdev, "Wrong NTH SIGN, skblen %d\n", in ncm_unwrap_ntb()
1195 skb->len); in ncm_unwrap_ntb()
1197 skb->data, 32, false); in ncm_unwrap_ntb()
1203 if (get_unaligned_le16(tmp++) != opts->nth_size) { in ncm_unwrap_ntb()
1204 INFO(port->func.config->cdev, "Wrong NTB headersize\n"); in ncm_unwrap_ntb()
1209 block_len = get_ncm(&tmp, opts->block_length); in ncm_unwrap_ntb()
1212 INFO(port->func.config->cdev, "OUT size exceeded\n"); in ncm_unwrap_ntb()
1216 ndp_index = get_ncm(&tmp, opts->ndp_index); in ncm_unwrap_ntb()
1225 (ndp_index < opts->nth_size) || in ncm_unwrap_ntb()
1226 (ndp_index > (block_len - in ncm_unwrap_ntb()
1227 opts->ndp_size))) { in ncm_unwrap_ntb()
1228 INFO(port->func.config->cdev, "Bad index: %#X\n", in ncm_unwrap_ntb()
1238 if (get_unaligned_le32(tmp) != ncm->ndp_sign) { in ncm_unwrap_ntb()
1239 INFO(port->func.config->cdev, "Wrong NDP SIGN\n"); in ncm_unwrap_ntb()
1249 * item size is 16/32 bits, opts->dgram_item_len * 2 bytes in ncm_unwrap_ntb()
1253 if ((ndp_len < opts->ndp_size in ncm_unwrap_ntb()
1254 + 2 * 2 * (opts->dgram_item_len * 2)) || in ncm_unwrap_ntb()
1255 (ndp_len % opts->ndplen_align != 0)) { in ncm_unwrap_ntb()
1256 INFO(port->func.config->cdev, "Bad NDP length: %#X\n", in ncm_unwrap_ntb()
1260 tmp += opts->reserved1; in ncm_unwrap_ntb()
1262 ndp_index = get_ncm(&tmp, opts->next_ndp_index); in ncm_unwrap_ntb()
1263 tmp += opts->reserved2; in ncm_unwrap_ntb()
1265 ndp_len -= opts->ndp_size; in ncm_unwrap_ntb()
1266 index2 = get_ncm(&tmp, opts->dgram_item_len); in ncm_unwrap_ntb()
1267 dg_len2 = get_ncm(&tmp, opts->dgram_item_len); in ncm_unwrap_ntb()
1273 if ((index < opts->nth_size) || in ncm_unwrap_ntb()
1274 (index > block_len - opts->dpe_size)) { in ncm_unwrap_ntb()
1275 INFO(port->func.config->cdev, in ncm_unwrap_ntb()
1287 INFO(port->func.config->cdev, in ncm_unwrap_ntb()
1291 if (ncm->is_crc) { in ncm_unwrap_ntb()
1295 index + dg_len - in ncm_unwrap_ntb()
1299 dg_len - crc_len); in ncm_unwrap_ntb()
1301 INFO(port->func.config->cdev, in ncm_unwrap_ntb()
1307 index2 = get_ncm(&tmp, opts->dgram_item_len); in ncm_unwrap_ntb()
1308 dg_len2 = get_ncm(&tmp, opts->dgram_item_len); in ncm_unwrap_ntb()
1311 if (index2 > block_len - opts->dpe_size) { in ncm_unwrap_ntb()
1312 INFO(port->func.config->cdev, in ncm_unwrap_ntb()
1321 skb2 = netdev_alloc_skb_ip_align(ncm->netdev, in ncm_unwrap_ntb()
1322 dg_len - crc_len); in ncm_unwrap_ntb()
1326 dg_len - crc_len); in ncm_unwrap_ntb()
1330 ndp_len -= 2 * (opts->dgram_item_len * 2); in ncm_unwrap_ntb()
1335 } while (ndp_len > 2 * (opts->dgram_item_len * 2)); in ncm_unwrap_ntb()
1338 VDBG(port->func.config->cdev, in ncm_unwrap_ntb()
1341 to_process -= block_len; in ncm_unwrap_ntb()
1344 * Windows NCM driver avoids USB ZLPs by adding a 1-byte in ncm_unwrap_ntb()
1349 to_process--; in ncm_unwrap_ntb()
1367 struct usb_composite_dev *cdev = f->config->cdev; in ncm_disable()
1371 if (ncm->netdev) { in ncm_disable()
1372 ncm->netdev = NULL; in ncm_disable()
1373 gether_disconnect(&ncm->port); in ncm_disable()
1376 if (ncm->notify->enabled) { in ncm_disable()
1377 usb_ep_disable(ncm->notify); in ncm_disable()
1378 ncm->notify->desc = NULL; in ncm_disable()
1382 /*-------------------------------------------------------------------------*/
1391 * - disconnected/unconfigured
1392 * - configured but inactive (data alt 0)
1393 * - configured and active (data alt 1)
1404 struct f_ncm *ncm = func_to_ncm(&geth->func); in ncm_open()
1406 DBG(ncm->port.func.config->cdev, "%s\n", __func__); in ncm_open()
1408 spin_lock(&ncm->lock); in ncm_open()
1409 ncm->is_open = true; in ncm_open()
1411 spin_unlock(&ncm->lock); in ncm_open()
1416 struct f_ncm *ncm = func_to_ncm(&geth->func); in ncm_close()
1418 DBG(ncm->port.func.config->cdev, "%s\n", __func__); in ncm_close()
1420 spin_lock(&ncm->lock); in ncm_close()
1421 ncm->is_open = false; in ncm_close()
1423 spin_unlock(&ncm->lock); in ncm_close()
1426 /*-------------------------------------------------------------------------*/
1432 struct usb_composite_dev *cdev = c->cdev; in ncm_bind()
1439 if (!can_support_ecm(cdev->gadget)) in ncm_bind()
1440 return -EINVAL; in ncm_bind()
1442 ncm_opts = container_of(f->fi, struct f_ncm_opts, func_inst); in ncm_bind()
1444 if (cdev->use_os_string) { in ncm_bind()
1445 f->os_desc_table = kzalloc(sizeof(*f->os_desc_table), in ncm_bind()
1447 if (!f->os_desc_table) in ncm_bind()
1448 return -ENOMEM; in ncm_bind()
1449 f->os_desc_n = 1; in ncm_bind()
1450 f->os_desc_table[0].os_desc = &ncm_opts->ncm_os_desc; in ncm_bind()
1453 mutex_lock(&ncm_opts->lock); in ncm_bind()
1454 gether_set_gadget(ncm_opts->net, cdev->gadget); in ncm_bind()
1455 if (!ncm_opts->bound) { in ncm_bind()
1456 ncm_opts->net->mtu = (ncm_opts->max_segment_size - ETH_HLEN); in ncm_bind()
1457 status = gether_register_netdev(ncm_opts->net); in ncm_bind()
1459 mutex_unlock(&ncm_opts->lock); in ncm_bind()
1464 ncm_opts->bound = true; in ncm_bind()
1478 /* allocate instance-specific interface IDs */ in ncm_bind()
1482 ncm->ctrl_id = status; in ncm_bind()
1488 if (cdev->use_os_string) in ncm_bind()
1489 f->os_desc_table[0].if_id = in ncm_bind()
1495 ncm->data_id = status; in ncm_bind()
1501 ecm_desc.wMaxSegmentSize = cpu_to_le16(ncm_opts->max_segment_size); in ncm_bind()
1503 status = -ENODEV; in ncm_bind()
1505 /* allocate instance-specific endpoints */ in ncm_bind()
1506 ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_in_desc); in ncm_bind()
1509 ncm->port.in_ep = ep; in ncm_bind()
1511 ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_out_desc); in ncm_bind()
1514 ncm->port.out_ep = ep; in ncm_bind()
1516 ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_notify_desc); in ncm_bind()
1519 ncm->notify = ep; in ncm_bind()
1521 status = -ENOMEM; in ncm_bind()
1524 ncm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL); in ncm_bind()
1525 if (!ncm->notify_req) in ncm_bind()
1527 ncm->notify_req->buf = kmalloc(NCM_STATUS_BYTECOUNT, GFP_KERNEL); in ncm_bind()
1528 if (!ncm->notify_req->buf) in ncm_bind()
1530 ncm->notify_req->context = ncm; in ncm_bind()
1531 ncm->notify_req->complete = ncm_notify_complete; in ncm_bind()
1535 * hardware is dual speed, all bulk-capable endpoints work at in ncm_bind()
1559 ncm->port.open = ncm_open; in ncm_bind()
1560 ncm->port.close = ncm_close; in ncm_bind()
1562 hrtimer_init(&ncm->task_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); in ncm_bind()
1563 ncm->task_timer.function = ncm_tx_timeout; in ncm_bind()
1566 ncm->port.in_ep->name, ncm->port.out_ep->name, in ncm_bind()
1567 ncm->notify->name); in ncm_bind()
1571 kfree(f->os_desc_table); in ncm_bind()
1572 f->os_desc_n = 0; in ncm_bind()
1574 if (ncm->notify_req) { in ncm_bind()
1575 kfree(ncm->notify_req->buf); in ncm_bind()
1576 usb_ep_free_request(ncm->notify, ncm->notify_req); in ncm_bind()
1579 ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); in ncm_bind()
1611 mutex_lock(&opts->lock); in ncm_opts_max_segment_size_show()
1612 segment_size = opts->max_segment_size; in ncm_opts_max_segment_size_show()
1613 mutex_unlock(&opts->lock); in ncm_opts_max_segment_size_show()
1625 mutex_lock(&opts->lock); in ncm_opts_max_segment_size_store()
1626 if (opts->refcnt) { in ncm_opts_max_segment_size_store()
1627 ret = -EBUSY; in ncm_opts_max_segment_size_store()
1636 ret = -EINVAL; in ncm_opts_max_segment_size_store()
1640 opts->max_segment_size = segment_size; in ncm_opts_max_segment_size_store()
1643 mutex_unlock(&opts->lock); in ncm_opts_max_segment_size_store()
1669 if (opts->bound) in ncm_free_inst()
1670 gether_cleanup(netdev_priv(opts->net)); in ncm_free_inst()
1672 free_netdev(opts->net); in ncm_free_inst()
1673 kfree(opts->ncm_interf_group); in ncm_free_inst()
1686 return ERR_PTR(-ENOMEM); in ncm_alloc_inst()
1687 opts->ncm_os_desc.ext_compat_id = opts->ncm_ext_compat_id; in ncm_alloc_inst()
1689 mutex_init(&opts->lock); in ncm_alloc_inst()
1690 opts->func_inst.free_func_inst = ncm_free_inst; in ncm_alloc_inst()
1691 opts->net = gether_setup_default(); in ncm_alloc_inst()
1692 if (IS_ERR(opts->net)) { in ncm_alloc_inst()
1693 struct net_device *net = opts->net; in ncm_alloc_inst()
1697 opts->max_segment_size = ETH_FRAME_LEN; in ncm_alloc_inst()
1698 INIT_LIST_HEAD(&opts->ncm_os_desc.ext_prop); in ncm_alloc_inst()
1700 descs[0] = &opts->ncm_os_desc; in ncm_alloc_inst()
1703 config_group_init_type_name(&opts->func_inst.group, "", &ncm_func_type); in ncm_alloc_inst()
1705 usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs, in ncm_alloc_inst()
1708 ncm_free_inst(&opts->func_inst); in ncm_alloc_inst()
1711 opts->ncm_interf_group = ncm_interf_group; in ncm_alloc_inst()
1713 return &opts->func_inst; in ncm_alloc_inst()
1722 opts = container_of(f->fi, struct f_ncm_opts, func_inst); in ncm_free()
1724 mutex_lock(&opts->lock); in ncm_free()
1725 opts->refcnt--; in ncm_free()
1726 mutex_unlock(&opts->lock); in ncm_free()
1733 DBG(c->cdev, "ncm unbind\n"); in ncm_unbind()
1735 hrtimer_cancel(&ncm->task_timer); in ncm_unbind()
1737 kfree(f->os_desc_table); in ncm_unbind()
1738 f->os_desc_n = 0; in ncm_unbind()
1743 if (atomic_read(&ncm->notify_count)) { in ncm_unbind()
1744 usb_ep_dequeue(ncm->notify, ncm->notify_req); in ncm_unbind()
1745 atomic_set(&ncm->notify_count, 0); in ncm_unbind()
1748 kfree(ncm->notify_req->buf); in ncm_unbind()
1749 usb_ep_free_request(ncm->notify, ncm->notify_req); in ncm_unbind()
1761 return ERR_PTR(-ENOMEM); in ncm_alloc()
1764 mutex_lock(&opts->lock); in ncm_alloc()
1765 opts->refcnt++; in ncm_alloc()
1768 status = gether_get_host_addr_cdc(opts->net, ncm->ethaddr, in ncm_alloc()
1769 sizeof(ncm->ethaddr)); in ncm_alloc()
1772 mutex_unlock(&opts->lock); in ncm_alloc()
1773 return ERR_PTR(-EINVAL); in ncm_alloc()
1775 ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr; in ncm_alloc()
1777 spin_lock_init(&ncm->lock); in ncm_alloc()
1779 ncm->port.ioport = netdev_priv(opts->net); in ncm_alloc()
1780 mutex_unlock(&opts->lock); in ncm_alloc()
1781 ncm->port.is_fixed = true; in ncm_alloc()
1782 ncm->port.supports_multi_frame = true; in ncm_alloc()
1784 ncm->port.func.name = "cdc_network"; in ncm_alloc()
1785 /* descriptors are per-instance copies */ in ncm_alloc()
1786 ncm->port.func.bind = ncm_bind; in ncm_alloc()
1787 ncm->port.func.unbind = ncm_unbind; in ncm_alloc()
1788 ncm->port.func.set_alt = ncm_set_alt; in ncm_alloc()
1789 ncm->port.func.get_alt = ncm_get_alt; in ncm_alloc()
1790 ncm->port.func.setup = ncm_setup; in ncm_alloc()
1791 ncm->port.func.disable = ncm_disable; in ncm_alloc()
1792 ncm->port.func.free_func = ncm_free; in ncm_alloc()
1794 ncm->port.wrap = ncm_wrap_ntb; in ncm_alloc()
1795 ncm->port.unwrap = ncm_unwrap_ntb; in ncm_alloc()
1797 return &ncm->port.func; in ncm_alloc()