diff options
| author | David S. Miller <davem@davemloft.net> | 2013-11-02 02:02:19 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2013-11-02 02:02:19 -0400 |
| commit | f99f4f8b094065601f87953b6d372d1e082bdf8b (patch) | |
| tree | b5bd37a8edb1e3ff5f0c261daddd8b3362824d9f | |
| parent | c1a2e95435976cb040db1f6c0afbe4287c3d2e28 (diff) | |
| parent | a6fe67087d7cb916e41b4ad1b3a57c91150edb88 (diff) | |
Merge branch 'cdc_ncm'
Bjørn Mork says:
====================
cdc_ncm: many small and mostly trivial fixes
This series ended up longer than expected, and it is still not
complete. There is more to come when time allows...
Most changes are trivial. Notable non-trivial changes are
- removed filtering of identical speed notifications
- tx_max calulation is changed to count the pad byte if
necessary, and respect the device limit as an absolute
upper limit even if it is too low according to the spec
- remove the bug preventing SET_MAX_DATAGRAM_SIZE from having
any effect
- drop the pad-to-max if ZLPs are enabled
- the driver specific VERSION is dropped
- dev->hard_mtu is set to tx_max instead of max_datagram_size
causing usbnet to calculate the qlen based on the real max
size of tx skbs
This series has been tested, along with the previously posted
cdc_mbim series, on the NCM and MBIM devices I have:
- Ericsson F5521gw (NCM)
- Huawei E367 (MBIM)
- D-Link DWM-156 A7 (MBIM w/ too low dwNtb{In,Out}MaxSize bug)
- Sierra Wireless MC7710 (MBIM w/ ZLP and CDC Union bugs)
Apart from the D-Link modem dropping a lot less oversized
frames with the fix dedicated to it, there are no end user
noticable functional changes as a result of this series. But
all the non-trivial changes I listed above are of course
detectable by users looking at that specific area (except maybe
the removed speed notification, which requires a device sending
duplicates to be noticable - I don't have any such device).
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/usb/cdc_mbim.c | 2 | ||||
| -rw-r--r-- | drivers/net/usb/cdc_ncm.c | 490 | ||||
| -rw-r--r-- | include/linux/usb/cdc_ncm.h | 30 |
3 files changed, 233 insertions, 289 deletions
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 253472a8a983..af76aaf08b6b 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c | |||
| @@ -175,7 +175,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb | |||
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | spin_lock_bh(&ctx->mtx); | 177 | spin_lock_bh(&ctx->mtx); |
| 178 | skb_out = cdc_ncm_fill_tx_frame(ctx, skb, sign); | 178 | skb_out = cdc_ncm_fill_tx_frame(dev, skb, sign); |
| 179 | spin_unlock_bh(&ctx->mtx); | 179 | spin_unlock_bh(&ctx->mtx); |
| 180 | return skb_out; | 180 | return skb_out; |
| 181 | 181 | ||
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 43afde8f48d2..11c703337577 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c | |||
| @@ -53,8 +53,6 @@ | |||
| 53 | #include <linux/usb/cdc.h> | 53 | #include <linux/usb/cdc.h> |
| 54 | #include <linux/usb/cdc_ncm.h> | 54 | #include <linux/usb/cdc_ncm.h> |
| 55 | 55 | ||
| 56 | #define DRIVER_VERSION "14-Mar-2012" | ||
| 57 | |||
| 58 | #if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM) | 56 | #if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM) |
| 59 | static bool prefer_mbim = true; | 57 | static bool prefer_mbim = true; |
| 60 | #else | 58 | #else |
| @@ -68,71 +66,67 @@ static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx); | |||
| 68 | static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer); | 66 | static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer); |
| 69 | static struct usb_driver cdc_ncm_driver; | 67 | static struct usb_driver cdc_ncm_driver; |
| 70 | 68 | ||
| 71 | static void | 69 | static u8 cdc_ncm_setup(struct usbnet *dev) |
| 72 | cdc_ncm_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) | ||
| 73 | { | ||
| 74 | struct usbnet *dev = netdev_priv(net); | ||
| 75 | |||
| 76 | strlcpy(info->driver, dev->driver_name, sizeof(info->driver)); | ||
| 77 | strlcpy(info->version, DRIVER_VERSION, sizeof(info->version)); | ||
| 78 | strlcpy(info->fw_version, dev->driver_info->description, | ||
| 79 | sizeof(info->fw_version)); | ||
| 80 | usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info)); | ||
| 81 | } | ||
| 82 | |||
| 83 | static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) | ||
| 84 | { | 70 | { |
| 71 | struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; | ||
| 72 | struct usb_cdc_ncm_ntb_parameters ncm_parm; | ||
| 85 | u32 val; | 73 | u32 val; |
| 86 | u8 flags; | 74 | u8 flags; |
| 87 | u8 iface_no; | 75 | u8 iface_no; |
| 88 | int err; | 76 | int err; |
| 89 | int eth_hlen; | 77 | int eth_hlen; |
| 90 | u16 ntb_fmt_supported; | 78 | u16 ntb_fmt_supported; |
| 91 | u32 min_dgram_size; | 79 | __le16 max_datagram_size; |
| 92 | u32 min_hdr_size; | ||
| 93 | struct usbnet *dev = netdev_priv(ctx->netdev); | ||
| 94 | 80 | ||
| 95 | iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber; | 81 | iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber; |
| 96 | 82 | ||
| 97 | err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_PARAMETERS, | 83 | err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_PARAMETERS, |
| 98 | USB_TYPE_CLASS | USB_DIR_IN | 84 | USB_TYPE_CLASS | USB_DIR_IN |
| 99 | |USB_RECIP_INTERFACE, | 85 | |USB_RECIP_INTERFACE, |
| 100 | 0, iface_no, &ctx->ncm_parm, | 86 | 0, iface_no, &ncm_parm, |
| 101 | sizeof(ctx->ncm_parm)); | 87 | sizeof(ncm_parm)); |
| 102 | if (err < 0) { | 88 | if (err < 0) { |
| 103 | pr_debug("failed GET_NTB_PARAMETERS\n"); | 89 | dev_err(&dev->intf->dev, "failed GET_NTB_PARAMETERS\n"); |
| 104 | return 1; | 90 | return err; /* GET_NTB_PARAMETERS is required */ |
| 105 | } | 91 | } |
| 106 | 92 | ||
| 107 | /* read correct set of parameters according to device mode */ | 93 | /* read correct set of parameters according to device mode */ |
| 108 | ctx->rx_max = le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize); | 94 | ctx->rx_max = le32_to_cpu(ncm_parm.dwNtbInMaxSize); |
| 109 | ctx->tx_max = le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize); | 95 | ctx->tx_max = le32_to_cpu(ncm_parm.dwNtbOutMaxSize); |
| 110 | ctx->tx_remainder = le16_to_cpu(ctx->ncm_parm.wNdpOutPayloadRemainder); | 96 | ctx->tx_remainder = le16_to_cpu(ncm_parm.wNdpOutPayloadRemainder); |
| 111 | ctx->tx_modulus = le16_to_cpu(ctx->ncm_parm.wNdpOutDivisor); | 97 | ctx->tx_modulus = le16_to_cpu(ncm_parm.wNdpOutDivisor); |
| 112 | ctx->tx_ndp_modulus = le16_to_cpu(ctx->ncm_parm.wNdpOutAlignment); | 98 | ctx->tx_ndp_modulus = le16_to_cpu(ncm_parm.wNdpOutAlignment); |
| 113 | /* devices prior to NCM Errata shall set this field to zero */ | 99 | /* devices prior to NCM Errata shall set this field to zero */ |
| 114 | ctx->tx_max_datagrams = le16_to_cpu(ctx->ncm_parm.wNtbOutMaxDatagrams); | 100 | ctx->tx_max_datagrams = le16_to_cpu(ncm_parm.wNtbOutMaxDatagrams); |
| 115 | ntb_fmt_supported = le16_to_cpu(ctx->ncm_parm.bmNtbFormatsSupported); | 101 | ntb_fmt_supported = le16_to_cpu(ncm_parm.bmNtbFormatsSupported); |
| 116 | 102 | ||
| 117 | eth_hlen = ETH_HLEN; | 103 | /* there are some minor differences in NCM and MBIM defaults */ |
| 118 | min_dgram_size = CDC_NCM_MIN_DATAGRAM_SIZE; | 104 | if (cdc_ncm_comm_intf_is_mbim(ctx->control->cur_altsetting)) { |
| 119 | min_hdr_size = CDC_NCM_MIN_HDR_SIZE; | 105 | if (!ctx->mbim_desc) |
| 120 | if (ctx->mbim_desc != NULL) { | 106 | return -EINVAL; |
| 121 | flags = ctx->mbim_desc->bmNetworkCapabilities; | ||
| 122 | eth_hlen = 0; | 107 | eth_hlen = 0; |
| 123 | min_dgram_size = CDC_MBIM_MIN_DATAGRAM_SIZE; | 108 | flags = ctx->mbim_desc->bmNetworkCapabilities; |
| 124 | min_hdr_size = 0; | 109 | ctx->max_datagram_size = le16_to_cpu(ctx->mbim_desc->wMaxSegmentSize); |
| 125 | } else if (ctx->func_desc != NULL) { | 110 | if (ctx->max_datagram_size < CDC_MBIM_MIN_DATAGRAM_SIZE) |
| 126 | flags = ctx->func_desc->bmNetworkCapabilities; | 111 | ctx->max_datagram_size = CDC_MBIM_MIN_DATAGRAM_SIZE; |
| 127 | } else { | 112 | } else { |
| 128 | flags = 0; | 113 | if (!ctx->func_desc) |
| 114 | return -EINVAL; | ||
| 115 | eth_hlen = ETH_HLEN; | ||
| 116 | flags = ctx->func_desc->bmNetworkCapabilities; | ||
| 117 | ctx->max_datagram_size = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize); | ||
| 118 | if (ctx->max_datagram_size < CDC_NCM_MIN_DATAGRAM_SIZE) | ||
| 119 | ctx->max_datagram_size = CDC_NCM_MIN_DATAGRAM_SIZE; | ||
| 129 | } | 120 | } |
| 130 | 121 | ||
| 131 | pr_debug("dwNtbInMaxSize=%u dwNtbOutMaxSize=%u " | 122 | /* common absolute max for NCM and MBIM */ |
| 132 | "wNdpOutPayloadRemainder=%u wNdpOutDivisor=%u " | 123 | if (ctx->max_datagram_size > CDC_NCM_MAX_DATAGRAM_SIZE) |
| 133 | "wNdpOutAlignment=%u wNtbOutMaxDatagrams=%u flags=0x%x\n", | 124 | ctx->max_datagram_size = CDC_NCM_MAX_DATAGRAM_SIZE; |
| 134 | ctx->rx_max, ctx->tx_max, ctx->tx_remainder, ctx->tx_modulus, | 125 | |
| 135 | ctx->tx_ndp_modulus, ctx->tx_max_datagrams, flags); | 126 | dev_dbg(&dev->intf->dev, |
| 127 | "dwNtbInMaxSize=%u dwNtbOutMaxSize=%u wNdpOutPayloadRemainder=%u wNdpOutDivisor=%u wNdpOutAlignment=%u wNtbOutMaxDatagrams=%u flags=0x%x\n", | ||
| 128 | ctx->rx_max, ctx->tx_max, ctx->tx_remainder, ctx->tx_modulus, | ||
| 129 | ctx->tx_ndp_modulus, ctx->tx_max_datagrams, flags); | ||
| 136 | 130 | ||
| 137 | /* max count of tx datagrams */ | 131 | /* max count of tx datagrams */ |
| 138 | if ((ctx->tx_max_datagrams == 0) || | 132 | if ((ctx->tx_max_datagrams == 0) || |
| @@ -141,19 +135,19 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) | |||
| 141 | 135 | ||
| 142 | /* verify maximum size of received NTB in bytes */ | 136 | /* verify maximum size of received NTB in bytes */ |
| 143 | if (ctx->rx_max < USB_CDC_NCM_NTB_MIN_IN_SIZE) { | 137 | if (ctx->rx_max < USB_CDC_NCM_NTB_MIN_IN_SIZE) { |
| 144 | pr_debug("Using min receive length=%d\n", | 138 | dev_dbg(&dev->intf->dev, "Using min receive length=%d\n", |
| 145 | USB_CDC_NCM_NTB_MIN_IN_SIZE); | 139 | USB_CDC_NCM_NTB_MIN_IN_SIZE); |
| 146 | ctx->rx_max = USB_CDC_NCM_NTB_MIN_IN_SIZE; | 140 | ctx->rx_max = USB_CDC_NCM_NTB_MIN_IN_SIZE; |
| 147 | } | 141 | } |
| 148 | 142 | ||
| 149 | if (ctx->rx_max > CDC_NCM_NTB_MAX_SIZE_RX) { | 143 | if (ctx->rx_max > CDC_NCM_NTB_MAX_SIZE_RX) { |
| 150 | pr_debug("Using default maximum receive length=%d\n", | 144 | dev_dbg(&dev->intf->dev, "Using default maximum receive length=%d\n", |
| 151 | CDC_NCM_NTB_MAX_SIZE_RX); | 145 | CDC_NCM_NTB_MAX_SIZE_RX); |
| 152 | ctx->rx_max = CDC_NCM_NTB_MAX_SIZE_RX; | 146 | ctx->rx_max = CDC_NCM_NTB_MAX_SIZE_RX; |
| 153 | } | 147 | } |
| 154 | 148 | ||
| 155 | /* inform device about NTB input size changes */ | 149 | /* inform device about NTB input size changes */ |
| 156 | if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) { | 150 | if (ctx->rx_max != le32_to_cpu(ncm_parm.dwNtbInMaxSize)) { |
| 157 | __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); | 151 | __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); |
| 158 | 152 | ||
| 159 | err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_INPUT_SIZE, | 153 | err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_INPUT_SIZE, |
| @@ -161,16 +155,22 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) | |||
