summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorJim Baxter <jim_baxter@mentor.com>2014-07-07 13:33:18 -0400
committerFelipe Balbi <balbi@ti.com>2014-07-10 09:49:38 -0400
commit6d3865f9d41f15ddbcecaa6722871fc0db21d7ab (patch)
tree2f4ed7cce199a98fadc042403d6f0088fff3f0a1 /drivers/usb
parent370af734dfaf8336b496b386e194648e097e248a (diff)
usb: gadget: NCM: Add transmit multi-frame.
This adds multi-frame support to the NCM NTB's for the gadget driver. This allows multiple network packets to be put inside a single USB NTB with a maximum size of 16kB. It has a time out of 300ms to ensure that smaller number of packets still maintain a normal latency. Also the .fp_index and .next_fp_index have been changed to .ndp_index and .next_ndp_index to match the latest CDC-NCM specification and help with maintenance. Results transmitting from gadget to host. Before the change: TCP_STREAM Throughput (10^6bits/sec): 22.72 UDP_STREAM Throughput (10^6bits/sec): 25.94 Latency: netperf -H 192.168.1.101 -v2 -l 50 -t TCP_RR -- -r 16384,16384 Trans. RoundTrip Throughput Rate Latency 10^6bits/s per sec usec/Tran Outbound 100.83 9918.116 13.215 After the change: TCP_STREAM Throughput (10^6bits/sec): 124.26 UDP_STREAM Throughput (10^6bits/sec): 227.48 Latency: netperf -H 192.168.1.101 -v2 -l 50 -t TCP_RR -- -r 16384,16384 Trans. RoundTrip Throughput Rate Latency 10^6bits/s per sec usec/Tran Outbound 156.80 6377.730 20.552 Signed-off-by: Jim Baxter <jim_baxter@mentor.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/f_ncm.c335
-rw-r--r--drivers/usb/gadget/u_ether.c19
-rw-r--r--drivers/usb/gadget/u_ether.h2
3 files changed, 269 insertions, 87 deletions
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c
index d0ebbac8845f..5452fb663762 100644
--- a/drivers/usb/gadget/f_ncm.c
+++ b/drivers/usb/gadget/f_ncm.c
@@ -68,6 +68,18 @@ struct f_ncm {
68 * callback and ethernet open/close 68 * callback and ethernet open/close
69 */ 69 */
70 spinlock_t lock; 70 spinlock_t lock;
71
72 struct net_device *netdev;
73
74 /* For multi-frame NDP TX */
75 struct sk_buff *skb_tx_data;
76 struct sk_buff *skb_tx_ndp;
77 u16 ndp_dgram_count;
78 bool timer_force_tx;
79 struct tasklet_struct tx_tasklet;
80 struct hrtimer task_timer;
81
82 bool timer_stopping;
71}; 83};
72 84
73static inline struct f_ncm *func_to_ncm(struct usb_function *f) 85static inline struct f_ncm *func_to_ncm(struct usb_function *f)
@@ -92,15 +104,20 @@ static inline unsigned ncm_bitrate(struct usb_gadget *g)
92 * If the host can group frames, allow it to do that, 16K is selected, 104 * If the host can group frames, allow it to do that, 16K is selected,
93 * because it's used by default by the current linux host driver 105 * because it's used by default by the current linux host driver
94 */ 106 */
95#define NTB_DEFAULT_IN_SIZE USB_CDC_NCM_NTB_MIN_IN_SIZE 107#define NTB_DEFAULT_IN_SIZE 16384
96#define NTB_OUT_SIZE 16384 108#define NTB_OUT_SIZE 16384
97 109
98/* 110/* Allocation for storing the NDP, 32 should suffice for a
99 * skbs of size less than that will not be aligned 111 * 16k packet. This allows a maximum of 32 * 507 Byte packets to
100 * to NCM's dwNtbInMaxSize to save bus bandwidth 112 * be transmitted in a single 16kB skb, though when sending full size
113 * packets this limit will be plenty.
114 * Smaller packets are not likely to be trying to maximize the
115 * throughput and will be mstly sending smaller infrequent frames.
101 */ 116 */
117#define TX_MAX_NUM_DPE 32
102 118
103#define MAX_TX_NONFIXED (512 * 3) 119/* Delay for the transmit to wait before sending an unfilled NTB frame. */
120#define TX_TIMEOUT_NSECS 300000
104 121
105#define FORMATS_SUPPORTED (USB_CDC_NCM_NTB16_SUPPORTED | \ 122#define FORMATS_SUPPORTED (USB_CDC_NCM_NTB16_SUPPORTED | \
106 USB_CDC_NCM_NTB32_SUPPORTED) 123 USB_CDC_NCM_NTB32_SUPPORTED)
@@ -355,14 +372,15 @@ struct ndp_parser_opts {
355 u32 ndp_sign; 372 u32 ndp_sign;
356 unsigned nth_size; 373 unsigned nth_size;
357 unsigned ndp_size; 374 unsigned ndp_size;
375 unsigned dpe_size;
358 unsigned ndplen_align; 376 unsigned ndplen_align;
359 /* sizes in u16 units */ 377 /* sizes in u16 units */
360 unsigned dgram_item_len; /* index or length */ 378 unsigned dgram_item_len; /* index or length */
361 unsigned block_length; 379 unsigned block_length;
362 unsigned fp_index; 380 unsigned ndp_index;
363 unsigned reserved1; 381 unsigned reserved1;
364 unsigned reserved2; 382 unsigned reserved2;
365 unsigned next_fp_index; 383 unsigned next_ndp_index;
366}; 384};
367 385
368#define INIT_NDP16_OPTS { \ 386#define INIT_NDP16_OPTS { \
@@ -370,13 +388,14 @@ struct ndp_parser_opts {
370 .ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN, \ 388 .ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN, \
371 .nth_size = sizeof(struct usb_cdc_ncm_nth16), \ 389 .nth_size = sizeof(struct usb_cdc_ncm_nth16), \
372 .ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \ 390 .ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \
391 .dpe_size = sizeof(struct usb_cdc_ncm_dpe16), \
373 .ndplen_align = 4, \ 392 .ndplen_align = 4, \
374 .dgram_item_len = 1, \ 393 .dgram_item_len = 1, \
375 .block_length = 1, \ 394 .block_length = 1, \
376 .fp_index = 1, \ 395 .ndp_index = 1, \
377 .reserved1 = 0, \ 396 .reserved1 = 0, \
378 .reserved2 = 0, \ 397 .reserved2 = 0, \
379 .next_fp_index = 1, \ 398 .next_ndp_index = 1, \
380 } 399 }
381 400
382 401
@@ -385,13 +404,14 @@ struct ndp_parser_opts {
385 .ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN, \ 404 .ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN, \
386 .nth_size = sizeof(struct usb_cdc_ncm_nth32), \ 405 .nth_size = sizeof(struct usb_cdc_ncm_nth32), \
387 .ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \ 406 .ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \
407 .dpe_size = sizeof(struct usb_cdc_ncm_dpe32), \
388 .ndplen_align = 8, \ 408 .ndplen_align = 8, \
389 .dgram_item_len = 2, \ 409 .dgram_item_len = 2, \
390 .block_length = 2, \ 410 .block_length = 2, \
391 .fp_index = 2, \ 411 .ndp_index = 2, \
392 .reserved1 = 1, \ 412 .reserved1 = 1, \
393 .reserved2 = 2, \ 413 .reserved2 = 2, \
394 .next_fp_index = 2, \ 414 .next_ndp_index = 2, \
395 } 415 }
396 416
397static const struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS; 417static const struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
@@ -803,6 +823,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
803 823
804 if (ncm->port.in_ep->driver_data) { 824 if (ncm->port.in_ep->driver_data) {
805 DBG(cdev, "reset ncm\n"); 825 DBG(cdev, "reset ncm\n");
826 ncm->timer_stopping = true;
827 ncm->netdev = NULL;
806 gether_disconnect(&ncm->port); 828 gether_disconnect(&ncm->port);
807 ncm_reset_values(ncm); 829 ncm_reset_values(ncm);
808 } 830 }
@@ -839,6 +861,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
839 net = gether_connect(&ncm->port); 861 net = gether_connect(&ncm->port);
840 if (IS_ERR(net)) 862 if (IS_ERR(net))
841 return PTR_ERR(net); 863 return PTR_ERR(net);
864 ncm->netdev = net;
865 ncm->timer_stopping = false;
842 } 866 }
843 867
844 spin_lock(&ncm->lock); 868 spin_lock(&ncm->lock);
@@ -865,95 +889,232 @@ static int ncm_get_alt(struct usb_function *f, unsigned intf)
865 return ncm->port.in_ep->driver_data ? 1 : 0; 889 return ncm->port.in_ep->driver_data ? 1 : 0;
866} 890}
867 891
892static struct sk_buff *package_for_tx(struct f_ncm *ncm)
893{
894 __le16 *ntb_iter;
895 struct sk_buff *skb2 = NULL;
896 unsigned ndp_pad;
897 unsigned ndp_index;
898 unsigned new_len;
899
900 const struct ndp_parser_opts *opts = ncm->parser_opts;
901 const int ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
902 const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
903
904 /* Stop the timer */
905 hrtimer_try_to_cancel(&ncm->task_timer);
906
907 ndp_pad = ALIGN(ncm->skb_tx_data->len, ndp_align) -
908 ncm->skb_tx_data->len;
909 ndp_index = ncm->skb_tx_data->len + ndp_pad;
910 new_len = ndp_index + dgram_idx_len + ncm->skb_tx_ndp->len;
911
912 /* Set the final BlockLength and wNdpIndex */
913 ntb_iter = (void *) ncm->skb_tx_data->data;
914 /* Increment pointer to BlockLength */
915 ntb_iter += 2 + 1 + 1;
916 put_ncm(&ntb_iter, opts->block_length, new_len);
917 put_ncm(&ntb_iter, opts->ndp_index, ndp_index);
918
919 /* Set the final NDP wLength */
920 new_len = opts->ndp_size +
921 (ncm->ndp_dgram_count * dgram_idx_len);
922 ncm->ndp_dgram_count = 0;
923 /* Increment from start to wLength */
924 ntb_iter = (void *) ncm->skb_tx_ndp->data;
925 ntb_iter += 2;
926 put_unaligned_le16(new_len, ntb_iter);
927
928 /* Merge the skbs */
929 swap(skb2, ncm->skb_tx_data);
930 if (ncm->skb_tx_data) {
931 dev_kfree_skb_any(ncm->skb_tx_data);
932 ncm->skb_tx_data = NULL;
933 }
934
935 /* Insert NDP alignment. */
936 ntb_iter = (void *) skb_put(skb2, ndp_pad);
937 memset(ntb_iter, 0, ndp_pad);
938
939 /* Copy NTB across. */
940 ntb_iter = (void *) skb_put(skb2, ncm->skb_tx_ndp->len);
941 memcpy(ntb_iter, ncm->skb_tx_ndp->data, ncm->skb_tx_ndp->len);
942 dev_kfree_skb_any(ncm->skb_tx_ndp);
943 ncm->skb_tx_ndp = NULL;
944
945 /* Insert zero'd datagram. */
946 ntb_iter = (void *) skb_put(skb2, dgram_idx_len);
947 memset(ntb_iter, 0, dgram_idx_len);
948
949 return skb2;
950}
951
868static struct sk_buff *ncm_wrap_ntb(struct gether *port, 952static struct sk_buff *ncm_wrap_ntb(struct gether *port,
869 struct sk_buff *skb) 953 struct sk_buff *skb)
870{ 954{
871 struct f_ncm *ncm = func_to_ncm(&port->func); 955 struct f_ncm *ncm = func_to_ncm(&port->func);
872 struct sk_buff *skb2; 956 struct sk_buff *skb2 = NULL;
873 int ncb_len = 0; 957 int ncb_len = 0;
874 __le16 *tmp; 958 __le16 *ntb_data;
875 int div; 959 __le16 *ntb_ndp;
876 int rem; 960 int dgram_pad;
877 int pad; 961
878 int ndp_align;
879 int ndp_pad;
880 unsigned max_size = ncm->port.fixed_in_len; 962 unsigned max_size = ncm->port.fixed_in_len;
881 const struct ndp_parser_opts *opts = ncm->parser_opts; 963 const struct ndp_parser_opts *opts = ncm->parser_opts;
882 unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0; 964 const int ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
883 965 const int div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
884 div = le16_to_cpu(ntb_parameters.wNdpInDivisor); 966 const int rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
885 rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder); 967 const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
886 ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
887
888 ncb_len += opts->nth_size;
889 ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len;
890 ncb_len += ndp_pad;
891 ncb_len += opts->ndp_size;
892 ncb_len += 2 * 2 * opts->dgram_item_len; /* Datagram entry */
893 ncb_len += 2 * 2 * opts->dgram_item_len; /* Zero datagram entry */
894 pad = ALIGN(ncb_len, div) + rem - ncb_len;
895 ncb_len += pad;
896 968
897 if (ncb_len + skb->len + crc_len > max_size) { 969 if (!skb && !ncm->skb_tx_data)
898 dev_kfree_skb_any(skb);
899 return NULL; 970 return NULL;
900 }
901 971
902 skb2 = skb_copy_expand(skb, ncb_len, 972 if (skb) {
903 max_size - skb->len - ncb_len - crc_len, 973 /* Add the CRC if required up front */
904 GFP_ATOMIC); 974 if (ncm->is_crc) {
905 dev_kfree_skb_any(skb); 975 uint32_t crc;
906 if (!skb2) 976 __le16 *crc_pos;
907 return NULL; 977
978 crc = ~crc32_le(~0,
979 skb->data,
980 skb->len);
981 crc_pos = (void *) skb_put(skb, sizeof(uint32_t));
982 put_unaligned_le32(crc, crc_pos);
983 }
908 984
909 skb = skb2; 985 /* If the new skb is too big for the current NCM NTB then
986 * set the current stored skb to be sent now and clear it
987 * ready for new data.
988 * NOTE: Assume maximum align for speed of calculation.
989 */
990 if (ncm->skb_tx_data
991 && (ncm->ndp_dgram_count >= TX_MAX_NUM_DPE
992 || (ncm->skb_tx_data->len +
993 div + rem + skb->len +
994 ncm->skb_tx_ndp->len + ndp_align + (2 * dgram_idx_len))
995 > max_size)) {
996 skb2 = package_for_tx(ncm);
997 if (!skb2)
998 goto err;
999 }
910 1000
911 tmp = (void *) skb_push(skb, ncb_len); 1001 if (!ncm->skb_tx_data) {
912 memset(tmp, 0, ncb_len); 1002 ncb_len = opts->nth_size;
1003 dgram_pad = ALIGN(ncb_len, div) + rem - ncb_len;
1004 ncb_len += dgram_pad;
913 1005
914 put_unaligned_le32(opts->nth_sign, tmp); /* dwSignature */ 1006 /* Create a new skb for the NTH and datagrams. */
915 tmp += 2; 1007 ncm->skb_tx_data = alloc_skb(max_size, GFP_ATOMIC);
916 /* wHeaderLength */ 1008 if (!ncm->skb_tx_data)
917 put_unaligned_le16(opts->nth_size, tmp++); 1009 goto err;
918 tmp++; /* skip wSequence */
919 put_ncm(&tmp, opts->block_length, skb->len); /* (d)wBlockLength */
920 /* (d)wFpIndex */
921 /* the first pointer is right after the NTH + align */
922 put_ncm(&tmp, opts->fp_index, opts->nth_size + ndp_pad);
923 1010
924 tmp = (void *)tmp + ndp_pad; 1011 ntb_data = (void *) skb_put(ncm->skb_tx_data, ncb_len);
1012 memset(ntb_data, 0, ncb_len);
1013 /* dwSignature */
1014 put_unaligned_le32(opts->nth_sign, ntb_data);
1015 ntb_data += 2;
1016 /* wHeaderLength */
1017 put_unaligned_le16(opts->nth_size, ntb_data++);
1018
1019 /* Allocate an skb for storing the NDP,
1020 * TX_MAX_NUM_DPE should easily suffice for a
1021 * 16k packet.
1022 */
1023 ncm->skb_tx_ndp = alloc_skb((int)(opts->ndp_size
1024 + opts->dpe_size
1025 * TX_MAX_NUM_DPE),
1026 GFP_ATOMIC);
1027 if (!ncm->skb_tx_ndp)
1028 goto err;
1029 ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp,
1030 opts->ndp_size);
1031 memset(ntb_ndp, 0, ncb_len);
1032 /* dwSignature */
1033 put_unaligned_le32(ncm->ndp_sign, ntb_ndp);
1034 ntb_ndp += 2;
925 1035
926 /* NDP */ 1036 /* There is always a zeroed entry */
927 put_unaligned_le32(ncm->ndp_sign, tmp); /* dwSignature */ 1037 ncm->ndp_dgram_count = 1;
928 tmp += 2;
929 /* wLength */
930 put_unaligned_le16(ncb_len - opts->nth_size - pad, tmp++);
931 1038
932 tmp += opts->reserved1; 1039 /* Note: we skip opts->next_ndp_index */
933 tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */ 1040 }
934 tmp += opts->reserved2;
935 1041
936 if (ncm->is_crc) { 1042 /* Delay the timer. */
937 uint32_t crc; 1043 hrtimer_start(&ncm->task_timer,
1044 ktime_set(0, TX_TIMEOUT_NSECS),
1045 HRTIMER_MODE_REL);
1046
1047 /* Add the datagram position entries */
1048 ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp, dgram_idx_len);
1049 memset(ntb_ndp, 0, dgram_idx_len);
1050
1051 ncb_len = ncm->skb_tx_data->len;
1052 dgram_pad = ALIGN(ncb_len, div) + rem - ncb_len;
1053 ncb_len += dgram_pad;
1054
1055 /* (d)wDatagramIndex */
1056 put_ncm(&ntb_ndp, opts->dgram_item_len, ncb_len);
1057 /* (d)wDatagramLength */
1058 put_ncm(&ntb_ndp, opts->dgram_item_len, skb->len);
1059 ncm->ndp_dgram_count++;
1060
1061 /* Add the new data to the skb */
1062 ntb_data = (void *) skb_put(ncm->skb_tx_data, dgram_pad);
1063 memset(ntb_data, 0, dgram_pad);
1064 ntb_data = (void *) skb_put(ncm->skb_tx_data, skb->len);
1065 memcpy(ntb_data, skb->data, skb->len);
1066 dev_kfree_skb_any(skb);
1067 skb = NULL;
938 1068
939 crc = ~crc32_le(~0, 1069 } else if (ncm->skb_tx_data && ncm->timer_force_tx) {
940 skb->data + ncb_len, 1070 /* If the tx was requested because of a timeout then send */
941 skb->len - ncb_len); 1071 skb2 = package_for_tx(ncm);
942 put_unaligned_le32(crc, skb->data + skb->len); 1072 if (!skb2)
943 skb_put(skb, crc_len); 1073 goto err;
944 } 1074 }
945 1075
946 /* (d)wDatagramIndex[0] */ 1076 return skb2;
947 put_ncm(&tmp, opts->dgram_item_len, ncb_len); 1077
948 /* (d)wDatagramLength[0] */ 1078err:
949 put_ncm(&tmp, opts->dgram_item_len, skb->len - ncb_len); 1079 ncm->netdev->stats.tx_dropped++;
950 /* (d)wDatagramIndex[1] and (d)wDatagramLength[1] already zeroed */ 1080
1081 if (skb)
1082 dev_kfree_skb_any(skb);
1083 if (ncm->skb_tx_data)
1084 dev_kfree_skb_any(ncm->skb_tx_data);
1085 if (ncm->skb_tx_ndp)
1086 dev_kfree_skb_any(ncm->skb_tx_ndp);
1087
1088 return NULL;
1089}
1090
1091/*
1092 * This transmits the NTB if there are frames waiting.
1093 */
1094static void ncm_tx_tasklet(unsigned long data)
1095{
1096 struct f_ncm *ncm = (void *)data;
951 1097
952 if (skb->len > MAX_TX_NONFIXED) 1098 if (ncm->timer_stopping)
953 memset(skb_put(skb, max_size - skb->len), 1099 return;
954 0, max_size - skb->len); 1100
1101 /* Only send if data is available. */
1102 if (ncm->skb_tx_data) {
1103 ncm->timer_force_tx = true;
1104 ncm->netdev->netdev_ops->ndo_start_xmit(NULL, ncm->netdev);
1105 ncm->timer_force_tx = false;
1106 }
1107}
955 1108
956 return skb; 1109/*
1110 * The transmit should only be run if no skb data has been sent
1111 * for a certain duration.
1112 */
1113static enum hrtimer_restart ncm_tx_timeout(struct hrtimer *data)
1114{
1115 struct f_ncm *ncm = container_of(data, struct f_ncm, task_timer);
1116 tasklet_schedule(&ncm->tx_tasklet);
1117 return HRTIMER_NORESTART;
957} 1118}
958 1119
959static int ncm_unwrap_ntb(struct gether *port, 1120static int ncm_unwrap_ntb(struct gether *port,
@@ -996,7 +1157,7 @@ static int ncm_unwrap_ntb(struct gether *port,
996 goto err; 1157 goto err;
997 } 1158 }
998 1159
999 ndp_index = get_ncm(&tmp, opts->fp_index); 1160 ndp_index = get_ncm(&tmp, opts->ndp_index);
1000 1161
1001 /* Run through all the NDP's in the NTB */ 1162 /* Run through all the NDP's in the NTB */
1002 do { 1163 do {
@@ -1033,7 +1194,7 @@ static int ncm_unwrap_ntb(struct gether *port,
1033 } 1194 }
1034 tmp += opts->reserved1; 1195 tmp += opts->reserved1;
1035 /* Check for another NDP (d)wNextNdpIndex */ 1196 /* Check for another NDP (d)wNextNdpIndex */
1036 ndp_index = get_ncm(&tmp, opts->next_fp_index); 1197 ndp_index = get_ncm(&tmp, opts->next_ndp_index);
1037 tmp += opts->reserved2; 1198 tmp += opts->reserved2;
1038 1199
1039 ndp_len -= opts->ndp_size; 1200 ndp_len -= opts->ndp_size;
@@ -1107,8 +1268,11 @@ static void ncm_disable(struct usb_function *f)
1107 1268
1108 DBG(cdev, "ncm deactivated\n"); 1269 DBG(cdev, "ncm deactivated\n");
1109 1270
1110 if (ncm->port.in_ep->driver_data) 1271 if (ncm->port.in_ep->driver_data) {
1272 ncm->timer_stopping = true;
1273 ncm->netdev = NULL;
1111 gether_disconnect(&ncm->port); 1274 gether_disconnect(&ncm->port);
1275 }
1112 1276
1113 if (ncm->notify->driver_data) { 1277 if (ncm->notify->driver_data) {
1114 usb_ep_disable(ncm->notify); 1278 usb_ep_disable(ncm->notify);
@@ -1277,6 +1441,10 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
1277 ncm->port.open = ncm_open; 1441 ncm->port.open = ncm_open;
1278 ncm->port.close = ncm_close; 1442 ncm->port.close = ncm_close;
1279 1443
1444 tasklet_init(&ncm->tx_tasklet, ncm_tx_tasklet, (unsigned long) ncm);
1445 hrtimer_init(&ncm->task_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
1446 ncm->task_timer.function = ncm_tx_timeout;
1447
1280 DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n", 1448 DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n",
1281 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", 1449 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
1282 ncm->port.in_ep->name, ncm->port.out_ep->name, 1450 ncm->port.in_ep->name, ncm->port.out_ep->name,
@@ -1390,6 +1558,10 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
1390 1558
1391 DBG(c->cdev, "ncm unbind\n"); 1559 DBG(c->cdev, "ncm unbind\n");
1392 1560
1561 hrtimer_cancel(&ncm->task_timer);
1562 tasklet_kill(&ncm->tx_tasklet);
1563
1564 ncm_string_defs[0].id = 0;
1393 usb_free_all_descriptors(f); 1565 usb_free_all_descriptors(f);
1394 1566
1395 kfree(ncm->notify_req->buf); 1567 kfree(ncm->notify_req->buf);
@@ -1426,6 +1598,7 @@ static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
1426 ncm->port.ioport = netdev_priv(opts->net); 1598 ncm->port.ioport = netdev_priv(opts->net);
1427 mutex_unlock(&opts->lock); 1599 mutex_unlock(&opts->lock);
1428 ncm->port.is_fixed = true; 1600 ncm->port.is_fixed = true;
1601 ncm->port.supports_multi_frame = true;
1429 1602
1430 ncm->port.func.name = "cdc_network"; 1603 ncm->port.func.name = "cdc_network";
1431 /* descriptors are per-instance copies */ 1604 /* descriptors are per-instance copies */
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 3d78a8844e43..6e6f87656e7b 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -483,7 +483,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
483 struct net_device *net) 483 struct net_device *net)
484{ 484{
485 struct eth_dev *dev = netdev_priv(net); 485 struct eth_dev *dev = netdev_priv(net);
486 int length = skb->len; 486 int length = 0;
487 int retval; 487 int retval;
488 struct usb_request *req = NULL; 488 struct usb_request *req = NULL;
489 unsigned long flags; 489 unsigned long flags;
@@ -500,13 +500,13 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
500 } 500 }
501 spin_unlock_irqrestore(&dev->lock, flags); 501 spin_unlock_irqrestore(&dev->lock, flags);
502 502
503 if (!in) { 503 if (skb && !in) {
504 dev_kfree_skb_any(skb); 504 dev_kfree_skb_any(skb);
505 return NETDEV_TX_OK; 505 return NETDEV_TX_OK;
506 } 506 }
507 507
508 /* apply outgoing CDC or RNDIS filters */ 508 /* apply outgoing CDC or RNDIS filters */
509 if (!is_promisc(cdc_filter)) { 509 if (skb && !is_promisc(cdc_filter)) {
510 u8 *dest = skb->data; 510 u8 *dest = skb->data;
511 511
512 if (is_multicast_ether_addr(dest)) { 512 if (is_multicast_ether_addr(dest)) {
@@ -557,11 +557,17 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
557 if (dev->port_usb) 557 if (dev->port_usb)
558 skb = dev->wrap(dev->port_usb, skb); 558 skb = dev->wrap(dev->port_usb, skb);
559 spin_unlock_irqrestore(&dev->lock, flags); 559 spin_unlock_irqrestore(&dev->lock, flags);
560 if (!skb) 560 if (!skb) {
561 /* Multi frame CDC protocols may store the frame for
562 * later which is not a dropped frame.
563 */
564 if (dev->port_usb->supports_multi_frame)
565 goto multiframe;
561 goto drop; 566 goto drop;
562 567 }
563 length = skb->len;
564 } 568 }
569
570 length = skb->len;
565 req->buf = skb->data; 571 req->buf = skb->data;
566 req->context = skb; 572 req->context = skb;
567 req->complete = tx_complete; 573 req->complete = tx_complete;
@@ -604,6 +610,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
604 dev_kfree_skb_any(skb); 610 dev_kfree_skb_any(skb);
605drop: 611drop:
606 dev->net->stats.tx_dropped++; 612 dev->net->stats.tx_dropped++;
613multiframe:
607 spin_lock_irqsave(&dev->req_lock, flags); 614 spin_lock_irqsave(&dev->req_lock, flags);
608 if (list_empty(&dev->tx_reqs)) 615 if (list_empty(&dev->tx_reqs))
609 netif_start_queue(net); 616 netif_start_queue(net);
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index 0f0290acea7e..334b38947916 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -18,6 +18,7 @@
18#include <linux/if_ether.h> 18#include <linux/if_ether.h>
19#include <linux/usb/composite.h> 19#include <linux/usb/composite.h>
20#include <linux/usb/cdc.h> 20#include <linux/usb/cdc.h>
21#include <linux/netdevice.h>
21 22
22#include "gadget_chips.h" 23#include "gadget_chips.h"
23 24
@@ -74,6 +75,7 @@ struct gether {
74 bool is_fixed; 75 bool is_fixed;
75 u32 fixed_out_len; 76 u32 fixed_out_len;
76 u32 fixed_in_len; 77 u32 fixed_in_len;
78 bool supports_multi_frame;
77 struct sk_buff *(*wrap)(struct gether *port, 79 struct sk_buff *(*wrap)(struct gether *port,
78 struct sk_buff *skb); 80 struct sk_buff *skb);
79 int (*unwrap)(struct gether *port, 81 int (*unwrap)(struct gether *port,