| .. | .. |
|---|
| 175 | 175 | u32 val, max, min; |
|---|
| 176 | 176 | |
|---|
| 177 | 177 | /* clamp new_tx to sane values */ |
|---|
| 178 | | - min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth16); |
|---|
| 179 | | - max = min_t(u32, CDC_NCM_NTB_MAX_SIZE_TX, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)); |
|---|
| 180 | | - if (max == 0) |
|---|
| 178 | + if (ctx->is_ndp16) |
|---|
| 179 | + min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth16); |
|---|
| 180 | + else |
|---|
| 181 | + min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth32); |
|---|
| 182 | + |
|---|
| 183 | + if (le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize) == 0) |
|---|
| 181 | 184 | max = CDC_NCM_NTB_MAX_SIZE_TX; /* dwNtbOutMaxSize not set */ |
|---|
| 185 | + else |
|---|
| 186 | + max = clamp_t(u32, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize), |
|---|
| 187 | + USB_CDC_NCM_NTB_MIN_OUT_SIZE, |
|---|
| 188 | + CDC_NCM_NTB_MAX_SIZE_TX); |
|---|
| 182 | 189 | |
|---|
| 183 | 190 | /* some devices set dwNtbOutMaxSize too low for the above default */ |
|---|
| 184 | 191 | min = min(min, max); |
|---|
| .. | .. |
|---|
| 309 | 316 | if (enable == (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)) |
|---|
| 310 | 317 | return len; |
|---|
| 311 | 318 | |
|---|
| 312 | | - if (enable && !ctx->delayed_ndp16) { |
|---|
| 313 | | - ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL); |
|---|
| 314 | | - if (!ctx->delayed_ndp16) |
|---|
| 315 | | - return -ENOMEM; |
|---|
| 319 | + if (enable) { |
|---|
| 320 | + if (ctx->is_ndp16 && !ctx->delayed_ndp16) { |
|---|
| 321 | + ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL); |
|---|
| 322 | + if (!ctx->delayed_ndp16) |
|---|
| 323 | + return -ENOMEM; |
|---|
| 324 | + } |
|---|
| 325 | + if (!ctx->is_ndp16 && !ctx->delayed_ndp32) { |
|---|
| 326 | + ctx->delayed_ndp32 = kzalloc(ctx->max_ndp_size, GFP_KERNEL); |
|---|
| 327 | + if (!ctx->delayed_ndp32) |
|---|
| 328 | + return -ENOMEM; |
|---|
| 329 | + } |
|---|
| 316 | 330 | } |
|---|
| 317 | 331 | |
|---|
| 318 | 332 | /* flush pending data before changing flag */ |
|---|
| .. | .. |
|---|
| 514 | 528 | dev_err(&dev->intf->dev, "SET_CRC_MODE failed\n"); |
|---|
| 515 | 529 | } |
|---|
| 516 | 530 | |
|---|
| 531 | + /* use ndp16 by default */ |
|---|
| 532 | + ctx->is_ndp16 = 1; |
|---|
| 533 | + |
|---|
| 517 | 534 | /* set NTB format, if both formats are supported. |
|---|
| 518 | 535 | * |
|---|
| 519 | 536 | * "The host shall only send this command while the NCM Data |
|---|
| .. | .. |
|---|
| 521 | 538 | */ |
|---|
| 522 | 539 | if (le16_to_cpu(ctx->ncm_parm.bmNtbFormatsSupported) & |
|---|
| 523 | 540 | USB_CDC_NCM_NTB32_SUPPORTED) { |
|---|
| 524 | | - dev_dbg(&dev->intf->dev, "Setting NTB format to 16-bit\n"); |
|---|
| 525 | | - err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT, |
|---|
| 526 | | - USB_TYPE_CLASS | USB_DIR_OUT |
|---|
| 527 | | - | USB_RECIP_INTERFACE, |
|---|
| 528 | | - USB_CDC_NCM_NTB16_FORMAT, |
|---|
| 529 | | - iface_no, NULL, 0); |
|---|
| 530 | | - if (err < 0) |
|---|
| 541 | + if (ctx->drvflags & CDC_NCM_FLAG_PREFER_NTB32) { |
|---|
| 542 | + ctx->is_ndp16 = 0; |
|---|
| 543 | + dev_dbg(&dev->intf->dev, "Setting NTB format to 32-bit\n"); |
|---|
| 544 | + err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT, |
|---|
| 545 | + USB_TYPE_CLASS | USB_DIR_OUT |
|---|
| 546 | + | USB_RECIP_INTERFACE, |
|---|
| 547 | + USB_CDC_NCM_NTB32_FORMAT, |
|---|
| 548 | + iface_no, NULL, 0); |
|---|
| 549 | + } else { |
|---|
| 550 | + ctx->is_ndp16 = 1; |
|---|
| 551 | + dev_dbg(&dev->intf->dev, "Setting NTB format to 16-bit\n"); |
|---|
| 552 | + err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT, |
|---|
| 553 | + USB_TYPE_CLASS | USB_DIR_OUT |
|---|
| 554 | + | USB_RECIP_INTERFACE, |
|---|
| 555 | + USB_CDC_NCM_NTB16_FORMAT, |
|---|
| 556 | + iface_no, NULL, 0); |
|---|
| 557 | + } |
|---|
| 558 | + if (err < 0) { |
|---|
| 559 | + ctx->is_ndp16 = 1; |
|---|
| 531 | 560 | dev_err(&dev->intf->dev, "SET_NTB_FORMAT failed\n"); |
|---|
| 561 | + } |
|---|
| 532 | 562 | } |
|---|
| 533 | 563 | |
|---|
| 534 | 564 | /* set initial device values */ |
|---|
| .. | .. |
|---|
| 551 | 581 | ctx->tx_max_datagrams = CDC_NCM_DPT_DATAGRAMS_MAX; |
|---|
| 552 | 582 | |
|---|
| 553 | 583 | /* set up maximum NDP size */ |
|---|
| 554 | | - ctx->max_ndp_size = sizeof(struct usb_cdc_ncm_ndp16) + (ctx->tx_max_datagrams + 1) * sizeof(struct usb_cdc_ncm_dpe16); |
|---|
| 584 | + if (ctx->is_ndp16) |
|---|
| 585 | + ctx->max_ndp_size = sizeof(struct usb_cdc_ncm_ndp16) + (ctx->tx_max_datagrams + 1) * sizeof(struct usb_cdc_ncm_dpe16); |
|---|
| 586 | + else |
|---|
| 587 | + ctx->max_ndp_size = sizeof(struct usb_cdc_ncm_ndp32) + (ctx->tx_max_datagrams + 1) * sizeof(struct usb_cdc_ncm_dpe32); |
|---|
| 555 | 588 | |
|---|
| 556 | 589 | /* initial coalescing timer interval */ |
|---|
| 557 | 590 | ctx->timer_interval = CDC_NCM_TIMER_INTERVAL_USEC * NSEC_PER_USEC; |
|---|
| .. | .. |
|---|
| 736 | 769 | ctx->tx_curr_skb = NULL; |
|---|
| 737 | 770 | } |
|---|
| 738 | 771 | |
|---|
| 739 | | - kfree(ctx->delayed_ndp16); |
|---|
| 772 | + if (ctx->is_ndp16) |
|---|
| 773 | + kfree(ctx->delayed_ndp16); |
|---|
| 774 | + else |
|---|
| 775 | + kfree(ctx->delayed_ndp32); |
|---|
| 740 | 776 | |
|---|
| 741 | 777 | kfree(ctx); |
|---|
| 742 | 778 | } |
|---|
| .. | .. |
|---|
| 761 | 797 | .ndo_stop = usbnet_stop, |
|---|
| 762 | 798 | .ndo_start_xmit = usbnet_start_xmit, |
|---|
| 763 | 799 | .ndo_tx_timeout = usbnet_tx_timeout, |
|---|
| 800 | + .ndo_set_rx_mode = usbnet_set_rx_mode, |
|---|
| 764 | 801 | .ndo_get_stats64 = usbnet_get_stats64, |
|---|
| 765 | 802 | .ndo_change_mtu = cdc_ncm_change_mtu, |
|---|
| 766 | 803 | .ndo_set_mac_address = eth_mac_addr, |
|---|
| .. | .. |
|---|
| 774 | 811 | u8 *buf; |
|---|
| 775 | 812 | int len; |
|---|
| 776 | 813 | int temp; |
|---|
| 777 | | - int err; |
|---|
| 778 | 814 | u8 iface_no; |
|---|
| 779 | 815 | struct usb_cdc_parsed_header hdr; |
|---|
| 780 | | - __le16 curr_ntb_format; |
|---|
| 781 | 816 | |
|---|
| 782 | 817 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
|---|
| 783 | 818 | if (!ctx) |
|---|
| .. | .. |
|---|
| 785 | 820 | |
|---|
| 786 | 821 | hrtimer_init(&ctx->tx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
|---|
| 787 | 822 | ctx->tx_timer.function = &cdc_ncm_tx_timer_cb; |
|---|
| 788 | | - ctx->bh.data = (unsigned long)dev; |
|---|
| 789 | | - ctx->bh.func = cdc_ncm_txpath_bh; |
|---|
| 823 | + tasklet_init(&ctx->bh, cdc_ncm_txpath_bh, (unsigned long)dev); |
|---|
| 790 | 824 | atomic_set(&ctx->stop, 0); |
|---|
| 791 | 825 | spin_lock_init(&ctx->mtx); |
|---|
| 792 | 826 | |
|---|
| .. | .. |
|---|
| 882 | 916 | goto error2; |
|---|
| 883 | 917 | } |
|---|
| 884 | 918 | |
|---|
| 885 | | - /* |
|---|
| 886 | | - * Some Huawei devices have been observed to come out of reset in NDP32 mode. |
|---|
| 887 | | - * Let's check if this is the case, and set the device to NDP16 mode again if |
|---|
| 888 | | - * needed. |
|---|
| 889 | | - */ |
|---|
| 890 | | - if (ctx->drvflags & CDC_NCM_FLAG_RESET_NTB16) { |
|---|
| 891 | | - err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_FORMAT, |
|---|
| 892 | | - USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE, |
|---|
| 893 | | - 0, iface_no, &curr_ntb_format, 2); |
|---|
| 894 | | - if (err < 0) { |
|---|
| 895 | | - goto error2; |
|---|
| 896 | | - } |
|---|
| 897 | | - |
|---|
| 898 | | - if (curr_ntb_format == cpu_to_le16(USB_CDC_NCM_NTB32_FORMAT)) { |
|---|
| 899 | | - dev_info(&intf->dev, "resetting NTB format to 16-bit"); |
|---|
| 900 | | - err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT, |
|---|
| 901 | | - USB_TYPE_CLASS | USB_DIR_OUT |
|---|
| 902 | | - | USB_RECIP_INTERFACE, |
|---|
| 903 | | - USB_CDC_NCM_NTB16_FORMAT, |
|---|
| 904 | | - iface_no, NULL, 0); |
|---|
| 905 | | - |
|---|
| 906 | | - if (err < 0) |
|---|
| 907 | | - goto error2; |
|---|
| 908 | | - } |
|---|
| 909 | | - } |
|---|
| 910 | | - |
|---|
| 911 | 919 | cdc_ncm_find_endpoints(dev, ctx->data); |
|---|
| 912 | 920 | cdc_ncm_find_endpoints(dev, ctx->control); |
|---|
| 913 | 921 | if (!dev->in || !dev->out || !dev->status) { |
|---|
| .. | .. |
|---|
| 932 | 940 | |
|---|
| 933 | 941 | /* Allocate the delayed NDP if needed. */ |
|---|
| 934 | 942 | if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) { |
|---|
| 935 | | - ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL); |
|---|
| 936 | | - if (!ctx->delayed_ndp16) |
|---|
| 937 | | - goto error2; |
|---|
| 943 | + if (ctx->is_ndp16) { |
|---|
| 944 | + ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL); |
|---|
| 945 | + if (!ctx->delayed_ndp16) |
|---|
| 946 | + goto error2; |
|---|
| 947 | + } else { |
|---|
| 948 | + ctx->delayed_ndp32 = kzalloc(ctx->max_ndp_size, GFP_KERNEL); |
|---|
| 949 | + if (!ctx->delayed_ndp32) |
|---|
| 950 | + goto error2; |
|---|
| 951 | + } |
|---|
| 938 | 952 | dev_info(&intf->dev, "NDP will be placed at end of frame for this device."); |
|---|
| 939 | 953 | } |
|---|
| 940 | 954 | |
|---|
| .. | .. |
|---|
| 1058 | 1072 | /* return a pointer to a valid struct usb_cdc_ncm_ndp16 of type sign, possibly |
|---|
| 1059 | 1073 | * allocating a new one within skb |
|---|
| 1060 | 1074 | */ |
|---|
| 1061 | | -static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign, size_t reserve) |
|---|
| 1075 | +static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign, size_t reserve) |
|---|
| 1062 | 1076 | { |
|---|
| 1063 | 1077 | struct usb_cdc_ncm_ndp16 *ndp16 = NULL; |
|---|
| 1064 | 1078 | struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data; |
|---|
| .. | .. |
|---|
| 1113 | 1127 | return ndp16; |
|---|
| 1114 | 1128 | } |
|---|
| 1115 | 1129 | |
|---|
| 1130 | +static struct usb_cdc_ncm_ndp32 *cdc_ncm_ndp32(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign, size_t reserve) |
|---|
| 1131 | +{ |
|---|
| 1132 | + struct usb_cdc_ncm_ndp32 *ndp32 = NULL; |
|---|
| 1133 | + struct usb_cdc_ncm_nth32 *nth32 = (void *)skb->data; |
|---|
| 1134 | + size_t ndpoffset = le32_to_cpu(nth32->dwNdpIndex); |
|---|
| 1135 | + |
|---|
| 1136 | + /* If NDP should be moved to the end of the NCM package, we can't follow the |
|---|
| 1137 | + * NTH32 header as we would normally do. NDP isn't written to the SKB yet, and |
|---|
| 1138 | + * the wNdpIndex field in the header is actually not consistent with reality. It will be later. |
|---|
| 1139 | + */ |
|---|
| 1140 | + if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) { |
|---|
| 1141 | + if (ctx->delayed_ndp32->dwSignature == sign) |
|---|
| 1142 | + return ctx->delayed_ndp32; |
|---|
| 1143 | + |
|---|
| 1144 | + /* We can only push a single NDP to the end. Return |
|---|
| 1145 | + * NULL to send what we've already got and queue this |
|---|
| 1146 | + * skb for later. |
|---|
| 1147 | + */ |
|---|
| 1148 | + else if (ctx->delayed_ndp32->dwSignature) |
|---|
| 1149 | + return NULL; |
|---|
| 1150 | + } |
|---|
| 1151 | + |
|---|
| 1152 | + /* follow the chain of NDPs, looking for a match */ |
|---|
| 1153 | + while (ndpoffset) { |
|---|
| 1154 | + ndp32 = (struct usb_cdc_ncm_ndp32 *)(skb->data + ndpoffset); |
|---|
| 1155 | + if (ndp32->dwSignature == sign) |
|---|
| 1156 | + return ndp32; |
|---|
| 1157 | + ndpoffset = le32_to_cpu(ndp32->dwNextNdpIndex); |
|---|
| 1158 | + } |
|---|
| 1159 | + |
|---|
| 1160 | + /* align new NDP */ |
|---|
| 1161 | + if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)) |
|---|
| 1162 | + cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size); |
|---|
| 1163 | + |
|---|
| 1164 | + /* verify that there is room for the NDP and the datagram (reserve) */ |
|---|
| 1165 | + if ((ctx->tx_curr_size - skb->len - reserve) < ctx->max_ndp_size) |
|---|
| 1166 | + return NULL; |
|---|
| 1167 | + |
|---|
| 1168 | + /* link to it */ |
|---|
| 1169 | + if (ndp32) |
|---|
| 1170 | + ndp32->dwNextNdpIndex = cpu_to_le32(skb->len); |
|---|
| 1171 | + else |
|---|
| 1172 | + nth32->dwNdpIndex = cpu_to_le32(skb->len); |
|---|
| 1173 | + |
|---|
| 1174 | + /* push a new empty NDP */ |
|---|
| 1175 | + if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)) |
|---|
| 1176 | + ndp32 = skb_put_zero(skb, ctx->max_ndp_size); |
|---|
| 1177 | + else |
|---|
| 1178 | + ndp32 = ctx->delayed_ndp32; |
|---|
| 1179 | + |
|---|
| 1180 | + ndp32->dwSignature = sign; |
|---|
| 1181 | + ndp32->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp32) + sizeof(struct usb_cdc_ncm_dpe32)); |
|---|
| 1182 | + return ndp32; |
|---|
| 1183 | +} |
|---|
| 1184 | + |
|---|
| 1116 | 1185 | struct sk_buff * |
|---|
| 1117 | 1186 | cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) |
|---|
| 1118 | 1187 | { |
|---|
| 1119 | 1188 | struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; |
|---|
| 1120 | | - struct usb_cdc_ncm_nth16 *nth16; |
|---|
| 1121 | | - struct usb_cdc_ncm_ndp16 *ndp16; |
|---|
| 1189 | + union { |
|---|
| 1190 | + struct usb_cdc_ncm_nth16 *nth16; |
|---|
| 1191 | + struct usb_cdc_ncm_nth32 *nth32; |
|---|
| 1192 | + } nth; |
|---|
| 1193 | + union { |
|---|
| 1194 | + struct usb_cdc_ncm_ndp16 *ndp16; |
|---|
| 1195 | + struct usb_cdc_ncm_ndp32 *ndp32; |
|---|
| 1196 | + } ndp; |
|---|
| 1122 | 1197 | struct sk_buff *skb_out; |
|---|
| 1123 | 1198 | u16 n = 0, index, ndplen; |
|---|
| 1124 | 1199 | u8 ready2send = 0; |
|---|
| .. | .. |
|---|
| 1158 | 1233 | * further. |
|---|
| 1159 | 1234 | */ |
|---|
| 1160 | 1235 | if (skb_out == NULL) { |
|---|
| 1236 | + /* If even the smallest allocation fails, abort. */ |
|---|
| 1237 | + if (ctx->tx_curr_size == USB_CDC_NCM_NTB_MIN_OUT_SIZE) |
|---|
| 1238 | + goto alloc_failed; |
|---|
| 1161 | 1239 | ctx->tx_low_mem_max_cnt = min(ctx->tx_low_mem_max_cnt + 1, |
|---|
| 1162 | 1240 | (unsigned)CDC_NCM_LOW_MEM_MAX_CNT); |
|---|
| 1163 | 1241 | ctx->tx_low_mem_val = ctx->tx_low_mem_max_cnt; |
|---|
| .. | .. |
|---|
| 1176 | 1254 | skb_out = alloc_skb(ctx->tx_curr_size, GFP_ATOMIC); |
|---|
| 1177 | 1255 | |
|---|
| 1178 | 1256 | /* No allocation possible so we will abort */ |
|---|
| 1179 | | - if (skb_out == NULL) { |
|---|
| 1180 | | - if (skb != NULL) { |
|---|
| 1181 | | - dev_kfree_skb_any(skb); |
|---|
| 1182 | | - dev->net->stats.tx_dropped++; |
|---|
| 1183 | | - } |
|---|
| 1184 | | - goto exit_no_skb; |
|---|
| 1185 | | - } |
|---|
| 1257 | + if (!skb_out) |
|---|
| 1258 | + goto alloc_failed; |
|---|
| 1186 | 1259 | ctx->tx_low_mem_val--; |
|---|
| 1187 | 1260 | } |
|---|
| 1188 | | - /* fill out the initial 16-bit NTB header */ |
|---|
| 1189 | | - nth16 = skb_put_zero(skb_out, sizeof(struct usb_cdc_ncm_nth16)); |
|---|
| 1190 | | - nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN); |
|---|
| 1191 | | - nth16->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16)); |
|---|
| 1192 | | - nth16->wSequence = cpu_to_le16(ctx->tx_seq++); |
|---|
| 1261 | + if (ctx->is_ndp16) { |
|---|
| 1262 | + /* fill out the initial 16-bit NTB header */ |
|---|
| 1263 | + nth.nth16 = skb_put_zero(skb_out, sizeof(struct usb_cdc_ncm_nth16)); |
|---|
| 1264 | + nth.nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN); |
|---|
| 1265 | + nth.nth16->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16)); |
|---|
| 1266 | + nth.nth16->wSequence = cpu_to_le16(ctx->tx_seq++); |
|---|
| 1267 | + } else { |
|---|
| 1268 | + /* fill out the initial 32-bit NTB header */ |
|---|
| 1269 | + nth.nth32 = skb_put_zero(skb_out, sizeof(struct usb_cdc_ncm_nth32)); |
|---|
| 1270 | + nth.nth32->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH32_SIGN); |
|---|
| 1271 | + nth.nth32->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth32)); |
|---|
| 1272 | + nth.nth32->wSequence = cpu_to_le16(ctx->tx_seq++); |
|---|
| 1273 | + } |
|---|
| 1193 | 1274 | |
|---|
| 1194 | 1275 | /* count total number of frames in this NTB */ |
|---|
| 1195 | 1276 | ctx->tx_curr_frame_num = 0; |
|---|
| .. | .. |
|---|
| 1211 | 1292 | } |
|---|
| 1212 | 1293 | |
|---|
| 1213 | 1294 | /* get the appropriate NDP for this skb */ |
|---|
| 1214 | | - ndp16 = cdc_ncm_ndp(ctx, skb_out, sign, skb->len + ctx->tx_modulus + ctx->tx_remainder); |
|---|
| 1295 | + if (ctx->is_ndp16) |
|---|
| 1296 | + ndp.ndp16 = cdc_ncm_ndp16(ctx, skb_out, sign, skb->len + ctx->tx_modulus + ctx->tx_remainder); |
|---|
| 1297 | + else |
|---|
| 1298 | + ndp.ndp32 = cdc_ncm_ndp32(ctx, skb_out, sign, skb->len + ctx->tx_modulus + ctx->tx_remainder); |
|---|
| 1215 | 1299 | |
|---|
| 1216 | 1300 | /* align beginning of next frame */ |
|---|
| 1217 | 1301 | cdc_ncm_align_tail(skb_out, ctx->tx_modulus, ctx->tx_remainder, ctx->tx_curr_size); |
|---|
| 1218 | 1302 | |
|---|
| 1219 | 1303 | /* check if we had enough room left for both NDP and frame */ |
|---|
| 1220 | | - if (!ndp16 || skb_out->len + skb->len + delayed_ndp_size > ctx->tx_curr_size) { |
|---|
| 1304 | + if ((ctx->is_ndp16 && !ndp.ndp16) || (!ctx->is_ndp16 && !ndp.ndp32) || |
|---|
| 1305 | + skb_out->len + skb->len + delayed_ndp_size > ctx->tx_curr_size) { |
|---|
| 1221 | 1306 | if (n == 0) { |
|---|
| 1222 | 1307 | /* won't fit, MTU problem? */ |
|---|
| 1223 | 1308 | dev_kfree_skb_any(skb); |
|---|
| .. | .. |
|---|
| 1239 | 1324 | } |
|---|
| 1240 | 1325 | |
|---|
| 1241 | 1326 | /* calculate frame number withing this NDP */ |
|---|
| 1242 | | - ndplen = le16_to_cpu(ndp16->wLength); |
|---|
| 1243 | | - index = (ndplen - sizeof(struct usb_cdc_ncm_ndp16)) / sizeof(struct usb_cdc_ncm_dpe16) - 1; |
|---|
| 1327 | + if (ctx->is_ndp16) { |
|---|
| 1328 | + ndplen = le16_to_cpu(ndp.ndp16->wLength); |
|---|
| 1329 | + index = (ndplen - sizeof(struct usb_cdc_ncm_ndp16)) / sizeof(struct usb_cdc_ncm_dpe16) - 1; |
|---|
| 1244 | 1330 | |
|---|
| 1245 | | - /* OK, add this skb */ |
|---|
| 1246 | | - ndp16->dpe16[index].wDatagramLength = cpu_to_le16(skb->len); |
|---|
| 1247 | | - ndp16->dpe16[index].wDatagramIndex = cpu_to_le16(skb_out->len); |
|---|
| 1248 | | - ndp16->wLength = cpu_to_le16(ndplen + sizeof(struct usb_cdc_ncm_dpe16)); |
|---|
| 1331 | + /* OK, add this skb */ |
|---|
| 1332 | + ndp.ndp16->dpe16[index].wDatagramLength = cpu_to_le16(skb->len); |
|---|
| 1333 | + ndp.ndp16->dpe16[index].wDatagramIndex = cpu_to_le16(skb_out->len); |
|---|
| 1334 | + ndp.ndp16->wLength = cpu_to_le16(ndplen + sizeof(struct usb_cdc_ncm_dpe16)); |
|---|
| 1335 | + } else { |
|---|
| 1336 | + ndplen = le16_to_cpu(ndp.ndp32->wLength); |
|---|
| 1337 | + index = (ndplen - sizeof(struct usb_cdc_ncm_ndp32)) / sizeof(struct usb_cdc_ncm_dpe32) - 1; |
|---|
| 1338 | + |
|---|
| 1339 | + ndp.ndp32->dpe32[index].dwDatagramLength = cpu_to_le32(skb->len); |
|---|
| 1340 | + ndp.ndp32->dpe32[index].dwDatagramIndex = cpu_to_le32(skb_out->len); |
|---|
| 1341 | + ndp.ndp32->wLength = cpu_to_le16(ndplen + sizeof(struct usb_cdc_ncm_dpe32)); |
|---|
| 1342 | + } |
|---|
| 1249 | 1343 | skb_put_data(skb_out, skb->data, skb->len); |
|---|
| 1250 | 1344 | ctx->tx_curr_frame_payload += skb->len; /* count real tx payload data */ |
|---|
| 1251 | 1345 | dev_kfree_skb_any(skb); |
|---|
| .. | .. |
|---|
| 1292 | 1386 | |
|---|
| 1293 | 1387 | /* If requested, put NDP at end of frame. */ |
|---|
| 1294 | 1388 | if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) { |
|---|
| 1295 | | - nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data; |
|---|
| 1296 | | - cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size - ctx->max_ndp_size); |
|---|
| 1297 | | - nth16->wNdpIndex = cpu_to_le16(skb_out->len); |
|---|
| 1298 | | - skb_put_data(skb_out, ctx->delayed_ndp16, ctx->max_ndp_size); |
|---|
| 1389 | + if (ctx->is_ndp16) { |
|---|
| 1390 | + nth.nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data; |
|---|
| 1391 | + cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size - ctx->max_ndp_size); |
|---|
| 1392 | + nth.nth16->wNdpIndex = cpu_to_le16(skb_out->len); |
|---|
| 1393 | + skb_put_data(skb_out, ctx->delayed_ndp16, ctx->max_ndp_size); |
|---|
| 1299 | 1394 | |
|---|
| 1300 | | - /* Zero out delayed NDP - signature checking will naturally fail. */ |
|---|
| 1301 | | - ndp16 = memset(ctx->delayed_ndp16, 0, ctx->max_ndp_size); |
|---|
| 1395 | + /* Zero out delayed NDP - signature checking will naturally fail. */ |
|---|
| 1396 | + ndp.ndp16 = memset(ctx->delayed_ndp16, 0, ctx->max_ndp_size); |
|---|
| 1397 | + } else { |
|---|
| 1398 | + nth.nth32 = (struct usb_cdc_ncm_nth32 *)skb_out->data; |
|---|
| 1399 | + cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size - ctx->max_ndp_size); |
|---|
| 1400 | + nth.nth32->dwNdpIndex = cpu_to_le32(skb_out->len); |
|---|
| 1401 | + skb_put_data(skb_out, ctx->delayed_ndp32, ctx->max_ndp_size); |
|---|
| 1402 | + |
|---|
| 1403 | + ndp.ndp32 = memset(ctx->delayed_ndp32, 0, ctx->max_ndp_size); |
|---|
| 1404 | + } |
|---|
| 1302 | 1405 | } |
|---|
| 1303 | 1406 | |
|---|
| 1304 | 1407 | /* If collected data size is less or equal ctx->min_tx_pkt |
|---|
| .. | .. |
|---|
| 1321 | 1424 | } |
|---|
| 1322 | 1425 | |
|---|
| 1323 | 1426 | /* set final frame length */ |
|---|
| 1324 | | - nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data; |
|---|
| 1325 | | - nth16->wBlockLength = cpu_to_le16(skb_out->len); |
|---|
| 1427 | + if (ctx->is_ndp16) { |
|---|
| 1428 | + nth.nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data; |
|---|
| 1429 | + nth.nth16->wBlockLength = cpu_to_le16(skb_out->len); |
|---|
| 1430 | + } else { |
|---|
| 1431 | + nth.nth32 = (struct usb_cdc_ncm_nth32 *)skb_out->data; |
|---|
| 1432 | + nth.nth32->dwBlockLength = cpu_to_le32(skb_out->len); |
|---|
| 1433 | + } |
|---|
| 1326 | 1434 | |
|---|
| 1327 | 1435 | /* return skb */ |
|---|
| 1328 | 1436 | ctx->tx_curr_skb = NULL; |
|---|
| .. | .. |
|---|
| 1340 | 1448 | |
|---|
| 1341 | 1449 | return skb_out; |
|---|
| 1342 | 1450 | |
|---|
| 1451 | +alloc_failed: |
|---|
| 1452 | + if (skb) { |
|---|
| 1453 | + dev_kfree_skb_any(skb); |
|---|
| 1454 | + dev->net->stats.tx_dropped++; |
|---|
| 1455 | + } |
|---|
| 1343 | 1456 | exit_no_skb: |
|---|
| 1344 | 1457 | /* Start timer, if there is a remaining non-empty skb */ |
|---|
| 1345 | 1458 | if (ctx->tx_curr_skb != NULL && n > 0) |
|---|
| .. | .. |
|---|
| 1405 | 1518 | goto error; |
|---|
| 1406 | 1519 | |
|---|
| 1407 | 1520 | spin_lock_bh(&ctx->mtx); |
|---|
| 1408 | | - skb_out = cdc_ncm_fill_tx_frame(dev, skb, cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN)); |
|---|
| 1521 | + |
|---|
| 1522 | + if (ctx->is_ndp16) |
|---|
| 1523 | + skb_out = cdc_ncm_fill_tx_frame(dev, skb, cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN)); |
|---|
| 1524 | + else |
|---|
| 1525 | + skb_out = cdc_ncm_fill_tx_frame(dev, skb, cpu_to_le32(USB_CDC_NCM_NDP32_NOCRC_SIGN)); |
|---|
| 1526 | + |
|---|
| 1409 | 1527 | spin_unlock_bh(&ctx->mtx); |
|---|
| 1410 | 1528 | return skb_out; |
|---|
| 1411 | 1529 | |
|---|
| .. | .. |
|---|
| 1466 | 1584 | } |
|---|
| 1467 | 1585 | EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_nth16); |
|---|
| 1468 | 1586 | |
|---|
| 1587 | +int cdc_ncm_rx_verify_nth32(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in) |
|---|
| 1588 | +{ |
|---|
| 1589 | + struct usbnet *dev = netdev_priv(skb_in->dev); |
|---|
| 1590 | + struct usb_cdc_ncm_nth32 *nth32; |
|---|
| 1591 | + int len; |
|---|
| 1592 | + int ret = -EINVAL; |
|---|
| 1593 | + |
|---|
| 1594 | + if (ctx == NULL) |
|---|
| 1595 | + goto error; |
|---|
| 1596 | + |
|---|
| 1597 | + if (skb_in->len < (sizeof(struct usb_cdc_ncm_nth32) + |
|---|
| 1598 | + sizeof(struct usb_cdc_ncm_ndp32))) { |
|---|
| 1599 | + netif_dbg(dev, rx_err, dev->net, "frame too short\n"); |
|---|
| 1600 | + goto error; |
|---|
| 1601 | + } |
|---|
| 1602 | + |
|---|
| 1603 | + nth32 = (struct usb_cdc_ncm_nth32 *)skb_in->data; |
|---|
| 1604 | + |
|---|
| 1605 | + if (nth32->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH32_SIGN)) { |
|---|
| 1606 | + netif_dbg(dev, rx_err, dev->net, |
|---|
| 1607 | + "invalid NTH32 signature <%#010x>\n", |
|---|
| 1608 | + le32_to_cpu(nth32->dwSignature)); |
|---|
| 1609 | + goto error; |
|---|
| 1610 | + } |
|---|
| 1611 | + |
|---|
| 1612 | + len = le32_to_cpu(nth32->dwBlockLength); |
|---|
| 1613 | + if (len > ctx->rx_max) { |
|---|
| 1614 | + netif_dbg(dev, rx_err, dev->net, |
|---|
| 1615 | + "unsupported NTB block length %u/%u\n", len, |
|---|
| 1616 | + ctx->rx_max); |
|---|
| 1617 | + goto error; |
|---|
| 1618 | + } |
|---|
| 1619 | + |
|---|
| 1620 | + if ((ctx->rx_seq + 1) != le16_to_cpu(nth32->wSequence) && |
|---|
| 1621 | + (ctx->rx_seq || le16_to_cpu(nth32->wSequence)) && |
|---|
| 1622 | + !((ctx->rx_seq == 0xffff) && !le16_to_cpu(nth32->wSequence))) { |
|---|
| 1623 | + netif_dbg(dev, rx_err, dev->net, |
|---|
| 1624 | + "sequence number glitch prev=%d curr=%d\n", |
|---|
| 1625 | + ctx->rx_seq, le16_to_cpu(nth32->wSequence)); |
|---|
| 1626 | + } |
|---|
| 1627 | + ctx->rx_seq = le16_to_cpu(nth32->wSequence); |
|---|
| 1628 | + |
|---|
| 1629 | + ret = le32_to_cpu(nth32->dwNdpIndex); |
|---|
| 1630 | +error: |
|---|
| 1631 | + return ret; |
|---|
| 1632 | +} |
|---|
| 1633 | +EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_nth32); |
|---|
| 1634 | + |
|---|
| 1469 | 1635 | /* verify NDP header and return number of datagrams, or negative error */ |
|---|
| 1470 | 1636 | int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset) |
|---|
| 1471 | 1637 | { |
|---|
| .. | .. |
|---|
| 1502 | 1668 | } |
|---|
| 1503 | 1669 | EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp16); |
|---|
| 1504 | 1670 | |
|---|
| 1671 | +/* verify NDP header and return number of datagrams, or negative error */ |
|---|
| 1672 | +int cdc_ncm_rx_verify_ndp32(struct sk_buff *skb_in, int ndpoffset) |
|---|
| 1673 | +{ |
|---|
| 1674 | + struct usbnet *dev = netdev_priv(skb_in->dev); |
|---|
| 1675 | + struct usb_cdc_ncm_ndp32 *ndp32; |
|---|
| 1676 | + int ret = -EINVAL; |
|---|
| 1677 | + |
|---|
| 1678 | + if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp32)) > skb_in->len) { |
|---|
| 1679 | + netif_dbg(dev, rx_err, dev->net, "invalid NDP offset <%u>\n", |
|---|
| 1680 | + ndpoffset); |
|---|
| 1681 | + goto error; |
|---|
| 1682 | + } |
|---|
| 1683 | + ndp32 = (struct usb_cdc_ncm_ndp32 *)(skb_in->data + ndpoffset); |
|---|
| 1684 | + |
|---|
| 1685 | + if (le16_to_cpu(ndp32->wLength) < USB_CDC_NCM_NDP32_LENGTH_MIN) { |
|---|
| 1686 | + netif_dbg(dev, rx_err, dev->net, "invalid DPT32 length <%u>\n", |
|---|
| 1687 | + le16_to_cpu(ndp32->wLength)); |
|---|
| 1688 | + goto error; |
|---|
| 1689 | + } |
|---|
| 1690 | + |
|---|
| 1691 | + ret = ((le16_to_cpu(ndp32->wLength) - |
|---|
| 1692 | + sizeof(struct usb_cdc_ncm_ndp32)) / |
|---|
| 1693 | + sizeof(struct usb_cdc_ncm_dpe32)); |
|---|
| 1694 | + ret--; /* we process NDP entries except for the last one */ |
|---|
| 1695 | + |
|---|
| 1696 | + if ((sizeof(struct usb_cdc_ncm_ndp32) + |
|---|
| 1697 | + ret * (sizeof(struct usb_cdc_ncm_dpe32))) > skb_in->len) { |
|---|
| 1698 | + netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret); |
|---|
| 1699 | + ret = -EINVAL; |
|---|
| 1700 | + } |
|---|
| 1701 | + |
|---|
| 1702 | +error: |
|---|
| 1703 | + return ret; |
|---|
| 1704 | +} |
|---|
| 1705 | +EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp32); |
|---|
| 1706 | + |
|---|
| 1505 | 1707 | int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in) |
|---|
| 1506 | 1708 | { |
|---|
| 1507 | 1709 | struct sk_buff *skb; |
|---|
| 1508 | 1710 | struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; |
|---|
| 1509 | | - int len; |
|---|
| 1711 | + unsigned int len; |
|---|
| 1510 | 1712 | int nframes; |
|---|
| 1511 | 1713 | int x; |
|---|
| 1512 | | - int offset; |
|---|
| 1513 | | - struct usb_cdc_ncm_ndp16 *ndp16; |
|---|
| 1514 | | - struct usb_cdc_ncm_dpe16 *dpe16; |
|---|
| 1714 | + unsigned int offset; |
|---|
| 1715 | + union { |
|---|
| 1716 | + struct usb_cdc_ncm_ndp16 *ndp16; |
|---|
| 1717 | + struct usb_cdc_ncm_ndp32 *ndp32; |
|---|
| 1718 | + } ndp; |
|---|
| 1719 | + union { |
|---|
| 1720 | + struct usb_cdc_ncm_dpe16 *dpe16; |
|---|
| 1721 | + struct usb_cdc_ncm_dpe32 *dpe32; |
|---|
| 1722 | + } dpe; |
|---|
| 1723 | + |
|---|
| 1515 | 1724 | int ndpoffset; |
|---|
| 1516 | 1725 | int loopcount = 50; /* arbitrary max preventing infinite loop */ |
|---|
| 1517 | 1726 | u32 payload = 0; |
|---|
| 1518 | 1727 | |
|---|
| 1519 | | - ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in); |
|---|
| 1728 | + if (ctx->is_ndp16) |
|---|
| 1729 | + ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in); |
|---|
| 1730 | + else |
|---|
| 1731 | + ndpoffset = cdc_ncm_rx_verify_nth32(ctx, skb_in); |
|---|
| 1732 | + |
|---|
| 1520 | 1733 | if (ndpoffset < 0) |
|---|
| 1521 | 1734 | goto error; |
|---|
| 1522 | 1735 | |
|---|
| 1523 | 1736 | next_ndp: |
|---|
| 1524 | | - nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset); |
|---|
| 1525 | | - if (nframes < 0) |
|---|
| 1526 | | - goto error; |
|---|
| 1737 | + if (ctx->is_ndp16) { |
|---|
| 1738 | + nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset); |
|---|
| 1739 | + if (nframes < 0) |
|---|
| 1740 | + goto error; |
|---|
| 1527 | 1741 | |
|---|
| 1528 | | - ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset); |
|---|
| 1742 | + ndp.ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset); |
|---|
| 1529 | 1743 | |
|---|
| 1530 | | - if (ndp16->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN)) { |
|---|
| 1531 | | - netif_dbg(dev, rx_err, dev->net, |
|---|
| 1532 | | - "invalid DPT16 signature <%#010x>\n", |
|---|
| 1533 | | - le32_to_cpu(ndp16->dwSignature)); |
|---|
| 1534 | | - goto err_ndp; |
|---|
| 1744 | + if (ndp.ndp16->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN)) { |
|---|
| 1745 | + netif_dbg(dev, rx_err, dev->net, |
|---|
| 1746 | + "invalid DPT16 signature <%#010x>\n", |
|---|
| 1747 | + le32_to_cpu(ndp.ndp16->dwSignature)); |
|---|
| 1748 | + goto err_ndp; |
|---|
| 1749 | + } |
|---|
| 1750 | + dpe.dpe16 = ndp.ndp16->dpe16; |
|---|
| 1751 | + } else { |
|---|
| 1752 | + nframes = cdc_ncm_rx_verify_ndp32(skb_in, ndpoffset); |
|---|
| 1753 | + if (nframes < 0) |
|---|
| 1754 | + goto error; |
|---|
| 1755 | + |
|---|
| 1756 | + ndp.ndp32 = (struct usb_cdc_ncm_ndp32 *)(skb_in->data + ndpoffset); |
|---|
| 1757 | + |
|---|
| 1758 | + if (ndp.ndp32->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP32_NOCRC_SIGN)) { |
|---|
| 1759 | + netif_dbg(dev, rx_err, dev->net, |
|---|
| 1760 | + "invalid DPT32 signature <%#010x>\n", |
|---|
| 1761 | + le32_to_cpu(ndp.ndp32->dwSignature)); |
|---|
| 1762 | + goto err_ndp; |
|---|
| 1763 | + } |
|---|
| 1764 | + dpe.dpe32 = ndp.ndp32->dpe32; |
|---|
| 1535 | 1765 | } |
|---|
| 1536 | | - dpe16 = ndp16->dpe16; |
|---|
| 1537 | 1766 | |
|---|
| 1538 | | - for (x = 0; x < nframes; x++, dpe16++) { |
|---|
| 1539 | | - offset = le16_to_cpu(dpe16->wDatagramIndex); |
|---|
| 1540 | | - len = le16_to_cpu(dpe16->wDatagramLength); |
|---|
| 1767 | + for (x = 0; x < nframes; x++) { |
|---|
| 1768 | + if (ctx->is_ndp16) { |
|---|
| 1769 | + offset = le16_to_cpu(dpe.dpe16->wDatagramIndex); |
|---|
| 1770 | + len = le16_to_cpu(dpe.dpe16->wDatagramLength); |
|---|
| 1771 | + } else { |
|---|
| 1772 | + offset = le32_to_cpu(dpe.dpe32->dwDatagramIndex); |
|---|
| 1773 | + len = le32_to_cpu(dpe.dpe32->dwDatagramLength); |
|---|
| 1774 | + } |
|---|
| 1541 | 1775 | |
|---|
| 1542 | 1776 | /* |
|---|
| 1543 | 1777 | * CDC NCM ch. 3.7 |
|---|
| .. | .. |
|---|
| 1549 | 1783 | break; |
|---|
| 1550 | 1784 | } |
|---|
| 1551 | 1785 | |
|---|
| 1552 | | - /* sanity checking */ |
|---|
| 1553 | | - if (((offset + len) > skb_in->len) || |
|---|
| 1786 | + /* sanity checking - watch out for integer wrap*/ |
|---|
| 1787 | + if ((offset > skb_in->len) || (len > skb_in->len - offset) || |
|---|
| 1554 | 1788 | (len > ctx->rx_max) || (len < ETH_HLEN)) { |
|---|
| 1555 | 1789 | netif_dbg(dev, rx_err, dev->net, |
|---|
| 1556 | 1790 | "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n", |
|---|
| .. | .. |
|---|
| 1568 | 1802 | usbnet_skb_return(dev, skb); |
|---|
| 1569 | 1803 | payload += len; /* count payload bytes in this NTB */ |
|---|
| 1570 | 1804 | } |
|---|
| 1805 | + |
|---|
| 1806 | + if (ctx->is_ndp16) |
|---|
| 1807 | + dpe.dpe16++; |
|---|
| 1808 | + else |
|---|
| 1809 | + dpe.dpe32++; |
|---|
| 1571 | 1810 | } |
|---|
| 1572 | 1811 | err_ndp: |
|---|
| 1573 | 1812 | /* are there more NDPs to process? */ |
|---|
| 1574 | | - ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex); |
|---|
| 1813 | + if (ctx->is_ndp16) |
|---|
| 1814 | + ndpoffset = le16_to_cpu(ndp.ndp16->wNextNdpIndex); |
|---|
| 1815 | + else |
|---|
| 1816 | + ndpoffset = le32_to_cpu(ndp.ndp32->dwNextNdpIndex); |
|---|
| 1817 | + |
|---|
| 1575 | 1818 | if (ndpoffset && loopcount--) |
|---|
| 1576 | 1819 | goto next_ndp; |
|---|
| 1577 | 1820 | |
|---|
| .. | .. |
|---|
| 1592 | 1835 | uint32_t rx_speed = le32_to_cpu(data->DLBitRRate); |
|---|
| 1593 | 1836 | uint32_t tx_speed = le32_to_cpu(data->ULBitRate); |
|---|
| 1594 | 1837 | |
|---|
| 1595 | | - /* if the speed hasn't changed, don't report it. |
|---|
| 1596 | | - * RTL8156 shipped before 2021 sends notification about every 32ms. |
|---|
| 1597 | | - */ |
|---|
| 1598 | | - if (dev->rx_speed == rx_speed && dev->tx_speed == tx_speed) |
|---|
| 1599 | | - return; |
|---|
| 1600 | | - |
|---|
| 1601 | | - dev->rx_speed = rx_speed; |
|---|
| 1602 | | - dev->tx_speed = tx_speed; |
|---|
| 1603 | | - |
|---|
| 1604 | 1838 | /* |
|---|
| 1605 | 1839 | * Currently the USB-NET API does not support reporting the actual |
|---|
| 1606 | 1840 | * device speed. Do print it instead. |
|---|
| .. | .. |
|---|
| 1620 | 1854 | |
|---|
| 1621 | 1855 | static void cdc_ncm_status(struct usbnet *dev, struct urb *urb) |
|---|
| 1622 | 1856 | { |
|---|
| 1623 | | - struct cdc_ncm_ctx *ctx; |
|---|
| 1624 | 1857 | struct usb_cdc_notification *event; |
|---|
| 1625 | | - |
|---|
| 1626 | | - ctx = (struct cdc_ncm_ctx *)dev->data[0]; |
|---|
| 1627 | 1858 | |
|---|
| 1628 | 1859 | if (urb->actual_length < sizeof(*event)) |
|---|
| 1629 | 1860 | return; |
|---|
| .. | .. |
|---|
| 1644 | 1875 | * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be |
|---|
| 1645 | 1876 | * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE. |
|---|
| 1646 | 1877 | */ |
|---|
| 1647 | | - if (netif_carrier_ok(dev->net) != !!event->wValue) |
|---|
| 1648 | | - usbnet_link_change(dev, !!event->wValue, 0); |
|---|
| 1878 | + usbnet_link_change(dev, !!event->wValue, 0); |
|---|
| 1649 | 1879 | break; |
|---|
| 1650 | 1880 | |
|---|
| 1651 | 1881 | case USB_CDC_NOTIFY_SPEED_CHANGE: |
|---|
| .. | .. |
|---|
| 1675 | 1905 | .status = cdc_ncm_status, |
|---|
| 1676 | 1906 | .rx_fixup = cdc_ncm_rx_fixup, |
|---|
| 1677 | 1907 | .tx_fixup = cdc_ncm_tx_fixup, |
|---|
| 1908 | + .set_rx_mode = usbnet_cdc_update_filter, |
|---|
| 1678 | 1909 | }; |
|---|
| 1679 | 1910 | |
|---|
| 1680 | 1911 | /* Same as cdc_ncm_info, but with FLAG_WWAN */ |
|---|
| .. | .. |
|---|
| 1688 | 1919 | .status = cdc_ncm_status, |
|---|
| 1689 | 1920 | .rx_fixup = cdc_ncm_rx_fixup, |
|---|
| 1690 | 1921 | .tx_fixup = cdc_ncm_tx_fixup, |
|---|
| 1922 | + .set_rx_mode = usbnet_cdc_update_filter, |
|---|
| 1691 | 1923 | }; |
|---|
| 1692 | 1924 | |
|---|
| 1693 | 1925 | /* Same as wwan_info, but with FLAG_NOARP */ |
|---|
| .. | .. |
|---|
| 1701 | 1933 | .status = cdc_ncm_status, |
|---|
| 1702 | 1934 | .rx_fixup = cdc_ncm_rx_fixup, |
|---|
| 1703 | 1935 | .tx_fixup = cdc_ncm_tx_fixup, |
|---|
| 1936 | + .set_rx_mode = usbnet_cdc_update_filter, |
|---|
| 1704 | 1937 | }; |
|---|
| 1705 | 1938 | |
|---|
| 1706 | 1939 | static const struct usb_device_id cdc_devs[] = { |
|---|