aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Suarez <gpsuarez2512@gmail.com>2012-10-08 16:30:38 +0200
committerBjørn Mork <bjorn@mork.no>2012-10-09 13:48:37 +0200
commit60065e5ea455d931a008272225ce2a30fe11751c (patch)
tree7f7b8a93bf00c078a8735c292658691bd5b55f7d
parent8ff5a5b76ce99495bb10499cb40f94035ff6e89e (diff)
net: cdc_ncm: adding MBIM support to ncm_setup
MBIM and NCM are very similar, so we can reuse most of the setup and bind logic in cdc_ncm for CDC MBIM devices. Handle a few minor differences in ncm_setup. Signed-off-by: Bjørn Mork <bjorn@mork.no>
-rw-r--r--drivers/net/usb/cdc_ncm.c48
1 files changed, 33 insertions, 15 deletions
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 6a65662aa9d..1b0f34feaf8 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -64,6 +64,9 @@
/* Minimum value for MaxDatagramSize, ch. 6.2.9 */
#define CDC_NCM_MIN_DATAGRAM_SIZE 1514 /* bytes */
+/* Minimum value for MaxDatagramSize, ch. 8.1.3 */
+#define CDC_MBIM_MIN_DATAGRAM_SIZE 2048 /* bytes */
+
#define CDC_NCM_MIN_TX_PKT 512 /* bytes */
/* Default value for MaxDatagramSize */
@@ -98,6 +101,7 @@ struct cdc_ncm_ctx {
struct tasklet_struct bh;
const struct usb_cdc_ncm_desc *func_desc;
+ const struct usb_cdc_mbim_desc *mbim_desc;
const struct usb_cdc_header_desc *header_desc;
const struct usb_cdc_union_desc *union_desc;
const struct usb_cdc_ether_desc *ether_desc;
@@ -158,7 +162,9 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
u8 flags;
u8 iface_no;
int err;
+ int eth_hlen;
u16 ntb_fmt_supported;
+ u32 min_dgram_size;
iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber;
@@ -184,10 +190,17 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
ctx->tx_max_datagrams = le16_to_cpu(ctx->ncm_parm.wNtbOutMaxDatagrams);
ntb_fmt_supported = le16_to_cpu(ctx->ncm_parm.bmNtbFormatsSupported);
- if (ctx->func_desc != NULL)
+ eth_hlen = ETH_HLEN;
+ min_dgram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
+ if (ctx->mbim_desc != NULL) {
+ flags = ctx->mbim_desc->bmNetworkCapabilities;
+ eth_hlen = 0;
+ min_dgram_size = CDC_MBIM_MIN_DATAGRAM_SIZE;
+ } else if (ctx->func_desc != NULL) {
flags = ctx->func_desc->bmNetworkCapabilities;
- else
+ } else {
flags = 0;
+ }
pr_debug("dwNtbInMaxSize=%u dwNtbOutMaxSize=%u "
"wNdpOutPayloadRemainder=%u wNdpOutDivisor=%u "
@@ -224,6 +237,7 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
err = -ENOMEM;
goto size_err;
}
+ ndp_in_sz->dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
err = usb_control_msg(ctx->udev,
usb_sndctrlpipe(ctx->udev, 0),
@@ -260,7 +274,7 @@ size_err:
/* verify maximum size of transmitted NTB in bytes */
if ((ctx->tx_max <
- (CDC_NCM_MIN_HDR_SIZE + CDC_NCM_MIN_DATAGRAM_SIZE)) ||
+ (CDC_NCM_MIN_HDR_SIZE + min_dgram_size)) ||
(ctx->tx_max > CDC_NCM_NTB_MAX_SIZE_TX)) {
pr_debug("Using default maximum transmit length=%d\n",
CDC_NCM_NTB_MAX_SIZE_TX);
@@ -302,8 +316,8 @@ size_err:
}
/* adjust TX-remainder according to NCM specification. */
- ctx->tx_remainder = ((ctx->tx_remainder - ETH_HLEN) &
- (ctx->tx_modulus - 1));
+ ctx->tx_remainder = ((ctx->tx_remainder - eth_hlen) &
+ (ctx->tx_modulus - 1));
/* additional configuration */
@@ -330,12 +344,18 @@ size_err:
pr_debug("Setting NTB format to 16-bit failed\n");
}
- ctx->max_datagram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
+ ctx->max_datagram_size = min_dgram_size;
/* set Max Datagram Size (MTU) */
if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) {
__le16 *max_datagram_size;
- u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
+ u16 eth_max_sz;
+ if (ctx->ether_desc != NULL)
+ eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
+ else if (ctx->mbim_desc != NULL)
+ eth_max_sz = le16_to_cpu(ctx->mbim_desc->wMaxSegmentSize);
+ else
+ goto max_dgram_err;
max_datagram_size = kzalloc(sizeof(*max_datagram_size),
GFP_KERNEL);
@@ -352,7 +372,7 @@ size_err:
2, 1000);
if (err < 0) {
pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n",
- CDC_NCM_MIN_DATAGRAM_SIZE);
+ min_dgram_size);
} else {
ctx->max_datagram_size =
le16_to_cpu(*max_datagram_size);
@@ -361,12 +381,10 @@ size_err:
ctx->max_datagram_size = eth_max_sz;
if (ctx->max_datagram_size > CDC_NCM_MAX_DATAGRAM_SIZE)
- ctx->max_datagram_size =
- CDC_NCM_MAX_DATAGRAM_SIZE;
+ ctx->max_datagram_size = CDC_NCM_MAX_DATAGRAM_SIZE;
- if (ctx->max_datagram_size < CDC_NCM_MIN_DATAGRAM_SIZE)
- ctx->max_datagram_size =
- CDC_NCM_MIN_DATAGRAM_SIZE;
+ if (ctx->max_datagram_size < min_dgram_size)
+ ctx->max_datagram_size = min_dgram_size;
/* if value changed, update device */
if (ctx->max_datagram_size !=
@@ -387,8 +405,8 @@ size_err:
}
max_dgram_err:
- if (ctx->netdev->mtu != (ctx->max_datagram_size - ETH_HLEN))
- ctx->netdev->mtu = ctx->max_datagram_size - ETH_HLEN;
+ if (ctx->netdev->mtu != (ctx->max_datagram_size - eth_hlen))
+ ctx->netdev->mtu = ctx->max_datagram_size - eth_hlen;
return 0;
}