Commit 33fcc5e0 authored by David S. Miller's avatar David S. Miller

Merge branch 'cdc_ncm-coalesce'

Bjørn Mork says:

====================
cdc_ncm: add buffer tuning and stats using ethtool

Quoting the previous description of this series (skip to the
changelog below if you only want a summary of the changes):

"I have got quite a few reports from frustrated users of OpenWRT
hosts trying to use some powerful LTE modem, but not achieving
full speed.  This is typically caused by a combination of
big buffers and little memory, giving in allocation errors and
bad performance as a result.

This series is an attempt to let users adjust the size of these
buffers without having to rebuild the driver.

Patches 1 - 4 are mostly rearranging existing code, in preparing
for the dynamic buffer size changes.

Patch 5 adds userspace control (ab)using the ethtool coalescing
API. This isn't a perfect match, which is the main reason why I
post this series as a RFC.

Patch 6 is an unrelated framing optimization, reducing the
overhead quite a bit and allowing for better use of smaller
buffers.

Patch 7 changes the way we calculate frame padding cutoff. The
problem with big buffers is made much worse by the current padding
strategy where zero padding often can account for more than 90% of
the frames.

Patch 8 add some counters giving some insight into how well the
NCM/MBIM protocol works, supporting further tuning.

Patch 9 reduce the initial maximum buffer size from 32kB to 16kB
in an attempt to make the default better suit all. It is still
possible to tune this up again to the old fixed max, using the
new tuning knobs.

I must admit that I had higher hopes for this series before I
tested it on my own modems.  One really unexpected result was
that one of the MBIM modems accepted the new rx buffer size we
set, but happily continued sending buffers of the same size as
before.  Needless to say:  This did not work very well...

So don't really expect to be able to use any values with any
given device. Firmware implementations are still... I don't
think I have words suitable for a public mailing list.

But I am hoping this will help the many users who have had success
rebuilding the driver with lower fixed limits.

Please test and/or comment!"

Changes:

** RFC -> v1 **

Patch 10 - a follow-up to a comment Joe Perches made in November
           2013.  I don't always forget :-)
Patch 11 - removes the redundant "connected" driver state, and the
           associated .check_connect callbacks.

** v1 -> v2 **

Patch 1  - Better handling of minium rx buffer size, based on feedback
           from Oliver Neukum and Enrico Mioso
Patch 5  - fixed locking around timer interval update
Patch 9  - fixed whitespace error
Patch 12 - new fix related to the tuneable tx timer

...and spelling fixes all over the commit messages.  I have finally
added a spelling hook, which I'm sure may of you will appreciate :-)
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 97dc48e2 046c6594
...@@ -420,6 +420,7 @@ static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in) ...@@ -420,6 +420,7 @@ static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
struct usb_cdc_ncm_dpe16 *dpe16; struct usb_cdc_ncm_dpe16 *dpe16;
int ndpoffset; int ndpoffset;
int loopcount = 50; /* arbitrary max preventing infinite loop */ int loopcount = 50; /* arbitrary max preventing infinite loop */
u32 payload = 0;
u8 *c; u8 *c;
u16 tci; u16 tci;
...@@ -482,6 +483,7 @@ static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in) ...@@ -482,6 +483,7 @@ static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
if (!skb) if (!skb)
goto error; goto error;
usbnet_skb_return(dev, skb); usbnet_skb_return(dev, skb);
payload += len; /* count payload bytes in this NTB */
} }
} }
err_ndp: err_ndp:
...@@ -490,6 +492,10 @@ static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in) ...@@ -490,6 +492,10 @@ static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
if (ndpoffset && loopcount--) if (ndpoffset && loopcount--)
goto next_ndp; goto next_ndp;
/* update stats */
ctx->rx_overhead += skb_in->len - payload;
ctx->rx_ntbs++;
return 1; return 1;
error: error:
return 0; return 0;
......
This diff is collapsed.
...@@ -172,24 +172,11 @@ static int huawei_cdc_ncm_resume(struct usb_interface *intf) ...@@ -172,24 +172,11 @@ static int huawei_cdc_ncm_resume(struct usb_interface *intf)
return ret; return ret;
} }
static int huawei_cdc_ncm_check_connect(struct usbnet *usbnet_dev)
{
struct cdc_ncm_ctx *ctx;
ctx = (struct cdc_ncm_ctx *)usbnet_dev->data[0];
if (ctx == NULL)
return 1; /* disconnected */
return !ctx->connected;
}
static const struct driver_info huawei_cdc_ncm_info = { static const struct driver_info huawei_cdc_ncm_info = {
.description = "Huawei CDC NCM device", .description = "Huawei CDC NCM device",
.flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN, .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN,
.bind = huawei_cdc_ncm_bind, .bind = huawei_cdc_ncm_bind,
.unbind = huawei_cdc_ncm_unbind, .unbind = huawei_cdc_ncm_unbind,
.check_connect = huawei_cdc_ncm_check_connect,
.manage_power = huawei_cdc_ncm_manage_power, .manage_power = huawei_cdc_ncm_manage_power,
.rx_fixup = cdc_ncm_rx_fixup, .rx_fixup = cdc_ncm_rx_fixup,
.tx_fixup = cdc_ncm_tx_fixup, .tx_fixup = cdc_ncm_tx_fixup,
......
...@@ -52,6 +52,10 @@ ...@@ -52,6 +52,10 @@
#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 */
/* Initial NTB length */
#define CDC_NCM_NTB_DEF_SIZE_TX 16384 /* bytes */
#define CDC_NCM_NTB_DEF_SIZE_RX 16384 /* bytes */
/* Minimum value for MaxDatagramSize, ch. 6.2.9 */ /* Minimum value for MaxDatagramSize, ch. 6.2.9 */
#define CDC_NCM_MIN_DATAGRAM_SIZE 1514 /* bytes */ #define CDC_NCM_MIN_DATAGRAM_SIZE 1514 /* bytes */
...@@ -72,16 +76,9 @@ ...@@ -72,16 +76,9 @@
/* Restart the timer, if amount of datagrams is less than given value */ /* Restart the timer, if amount of datagrams is less than given value */
#define CDC_NCM_RESTART_TIMER_DATAGRAM_CNT 3 #define CDC_NCM_RESTART_TIMER_DATAGRAM_CNT 3
#define CDC_NCM_TIMER_PENDING_CNT 2 #define CDC_NCM_TIMER_PENDING_CNT 2
#define CDC_NCM_TIMER_INTERVAL (400UL * NSEC_PER_USEC) #define CDC_NCM_TIMER_INTERVAL_USEC 400UL
#define CDC_NCM_TIMER_INTERVAL_MIN 5UL
/* The following macro defines the minimum header space */ #define CDC_NCM_TIMER_INTERVAL_MAX (15UL * USEC_PER_SEC)
#define CDC_NCM_MIN_HDR_SIZE \
(sizeof(struct usb_cdc_ncm_nth16) + sizeof(struct usb_cdc_ncm_ndp16) + \
(CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
#define CDC_NCM_NDP_SIZE \
(sizeof(struct usb_cdc_ncm_ndp16) + \
(CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
#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)
...@@ -107,6 +104,9 @@ struct cdc_ncm_ctx { ...@@ -107,6 +104,9 @@ struct cdc_ncm_ctx {
spinlock_t mtx; spinlock_t mtx;
atomic_t stop; atomic_t stop;
u64 timer_interval;
u32 max_ndp_size;
u32 tx_timer_pending; u32 tx_timer_pending;
u32 tx_curr_frame_num; u32 tx_curr_frame_num;
u32 rx_max; u32 rx_max;
...@@ -118,7 +118,18 @@ struct cdc_ncm_ctx { ...@@ -118,7 +118,18 @@ struct cdc_ncm_ctx {
u16 tx_ndp_modulus; u16 tx_ndp_modulus;
u16 tx_seq; u16 tx_seq;
u16 rx_seq; u16 rx_seq;
u16 connected; u16 min_tx_pkt;
/* statistics */
u32 tx_curr_frame_payload;
u32 tx_reason_ntb_full;
u32 tx_reason_ndp_full;
u32 tx_reason_timeout;
u32 tx_reason_max_datagram;
u64 tx_overhead;
u64 tx_ntbs;
u64 rx_overhead;
u64 rx_ntbs;
}; };
u8 cdc_ncm_select_altsetting(struct usb_interface *intf); u8 cdc_ncm_select_altsetting(struct usb_interface *intf);
......
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