Commit 0fa81b30 authored by Alexander Bersenev's avatar Alexander Bersenev Committed by David S. Miller

cdc_ncm: Implement the 32-bit version of NCM Transfer Block

The NCM specification defines two formats of transfer blocks: with 16-bit
fields (NTB-16) and with 32-bit fields (NTB-32). Currently only NTB-16 is
implemented.

This patch adds the support of NTB-32. The motivation behind this is that
some devices such as E5785 or E5885 from the current generation of Huawei
LTE routers do not support NTB-16. The previous generations of Huawei
devices are also use NTB-32 by default.

Also this patch enables NTB-32 by default for Huawei devices.

During the 2019 ValdikSS made five attempts to contact Huawei to add the
NTB-16 support to their router firmware, but they were unsuccessful.
Signed-off-by: default avatarAlexander Bersenev <bay@hackerdom.ru>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 81f954a4
This diff is collapsed.
...@@ -77,11 +77,11 @@ static int huawei_cdc_ncm_bind(struct usbnet *usbnet_dev, ...@@ -77,11 +77,11 @@ static int huawei_cdc_ncm_bind(struct usbnet *usbnet_dev,
*/ */
drvflags |= CDC_NCM_FLAG_NDP_TO_END; drvflags |= CDC_NCM_FLAG_NDP_TO_END;
/* Additionally, it has been reported that some Huawei E3372H devices, with /* For many Huawei devices the NTB32 mode is the default and the best mode
* firmware version 21.318.01.00.541, come out of reset in NTB32 format mode, hence * they work with. Huawei E5785 and E5885 devices refuse to work in NTB16 mode at all.
* needing to be set to the NTB16 one again.
*/ */
drvflags |= CDC_NCM_FLAG_RESET_NTB16; drvflags |= CDC_NCM_FLAG_PREFER_NTB32;
ret = cdc_ncm_bind_common(usbnet_dev, intf, 1, drvflags); ret = cdc_ncm_bind_common(usbnet_dev, intf, 1, drvflags);
if (ret) if (ret)
goto err; goto err;
......
...@@ -46,9 +46,12 @@ ...@@ -46,9 +46,12 @@
#define CDC_NCM_DATA_ALTSETTING_NCM 1 #define CDC_NCM_DATA_ALTSETTING_NCM 1
#define CDC_NCM_DATA_ALTSETTING_MBIM 2 #define CDC_NCM_DATA_ALTSETTING_MBIM 2
/* CDC NCM subclass 3.2.1 */ /* CDC NCM subclass 3.3.1 */
#define USB_CDC_NCM_NDP16_LENGTH_MIN 0x10 #define USB_CDC_NCM_NDP16_LENGTH_MIN 0x10
/* CDC NCM subclass 3.3.2 */
#define USB_CDC_NCM_NDP32_LENGTH_MIN 0x20
/* Maximum NTB length */ /* Maximum NTB length */
#define CDC_NCM_NTB_MAX_SIZE_TX 32768 /* bytes */ #define CDC_NCM_NTB_MAX_SIZE_TX 32768 /* bytes */
#define CDC_NCM_NTB_MAX_SIZE_RX 32768 /* bytes */ #define CDC_NCM_NTB_MAX_SIZE_RX 32768 /* bytes */
...@@ -84,7 +87,7 @@ ...@@ -84,7 +87,7 @@
/* Driver flags */ /* Driver flags */
#define CDC_NCM_FLAG_NDP_TO_END 0x02 /* NDP is placed at end of frame */ #define CDC_NCM_FLAG_NDP_TO_END 0x02 /* NDP is placed at end of frame */
#define CDC_MBIM_FLAG_AVOID_ALTSETTING_TOGGLE 0x04 /* Avoid altsetting toggle during init */ #define CDC_MBIM_FLAG_AVOID_ALTSETTING_TOGGLE 0x04 /* Avoid altsetting toggle during init */
#define CDC_NCM_FLAG_RESET_NTB16 0x08 /* set NDP16 one more time after altsetting switch */ #define CDC_NCM_FLAG_PREFER_NTB32 0x08 /* prefer NDP32 over NDP16 */
#define cdc_ncm_comm_intf_is_mbim(x) ((x)->desc.bInterfaceSubClass == USB_CDC_SUBCLASS_MBIM && \ #define cdc_ncm_comm_intf_is_mbim(x) ((x)->desc.bInterfaceSubClass == USB_CDC_SUBCLASS_MBIM && \
(x)->desc.bInterfaceProtocol == USB_CDC_PROTO_NONE) (x)->desc.bInterfaceProtocol == USB_CDC_PROTO_NONE)
...@@ -113,7 +116,11 @@ struct cdc_ncm_ctx { ...@@ -113,7 +116,11 @@ struct cdc_ncm_ctx {
u32 timer_interval; u32 timer_interval;
u32 max_ndp_size; u32 max_ndp_size;
struct usb_cdc_ncm_ndp16 *delayed_ndp16; u8 is_ndp16;
union {
struct usb_cdc_ncm_ndp16 *delayed_ndp16;
struct usb_cdc_ncm_ndp32 *delayed_ndp32;
};
u32 tx_timer_pending; u32 tx_timer_pending;
u32 tx_curr_frame_num; u32 tx_curr_frame_num;
...@@ -150,6 +157,8 @@ void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf); ...@@ -150,6 +157,8 @@ void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
struct sk_buff *cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign); struct sk_buff *cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign);
int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in); int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in);
int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset); int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset);
int cdc_ncm_rx_verify_nth32(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in);
int cdc_ncm_rx_verify_ndp32(struct sk_buff *skb_in, int ndpoffset);
struct sk_buff * struct sk_buff *
cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags); cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags);
int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in); int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment