Skip to content

Commit

Permalink
net: cdc_ncm: add "ndp_to_end" sysfs attribute
Browse files Browse the repository at this point in the history
Adding a writable sysfs attribute for the "NDP to end"
quirk flag.

This makes it easier for end users to test new devices for
this firmware bug.  We've been lucky so far, but we should
not depend on reporters capable of rebuilding the driver.

Cc: Enrico Mioso <[email protected]>
Signed-off-by: Bjørn Mork <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
bmork authored and davem330 committed Dec 7, 2015
1 parent 0fe3e20 commit 404814a
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
19 changes: 19 additions & 0 deletions Documentation/ABI/testing/sysfs-class-net-cdc_ncm
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,25 @@ Description:
Set to 0 to pad all frames. Set greater than tx_max to
disable all padding.

What: /sys/class/net/<iface>/cdc_ncm/ndp_to_end
Date: Dec 2015
KernelVersion: 4.5
Contact: Bjørn Mork <[email protected]>
Description:
Boolean attribute showing the status of the "NDP to
end" quirk. Defaults to 'N', except for devices
already known to need it enabled.

The "NDP to end" quirk makes the driver place the NDP
(the packet index table) after the payload. The NCM
specification does not mandate this, but some devices
are known to be more restrictive. Write 'Y' to this
attribute for temporary testing of a suspect device
failing to work with the default driver settings.

A device entry should be added to the driver if this
quirk is found to be required.

What: /sys/class/net/<iface>/cdc_ncm/rx_max
Date: May 2014
KernelVersion: 3.16
Expand Down
43 changes: 43 additions & 0 deletions drivers/net/usb/cdc_ncm.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,48 @@ static DEVICE_ATTR(rx_max, S_IRUGO | S_IWUSR, cdc_ncm_show_rx_max, cdc_ncm_store
static DEVICE_ATTR(tx_max, S_IRUGO | S_IWUSR, cdc_ncm_show_tx_max, cdc_ncm_store_tx_max);
static DEVICE_ATTR(tx_timer_usecs, S_IRUGO | S_IWUSR, cdc_ncm_show_tx_timer_usecs, cdc_ncm_store_tx_timer_usecs);

static ssize_t ndp_to_end_show(struct device *d, struct device_attribute *attr, char *buf)
{
struct usbnet *dev = netdev_priv(to_net_dev(d));
struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];

return sprintf(buf, "%c\n", ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END ? 'Y' : 'N');
}

static ssize_t ndp_to_end_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len)
{
struct usbnet *dev = netdev_priv(to_net_dev(d));
struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
bool enable;

if (strtobool(buf, &enable))
return -EINVAL;

/* no change? */
if (enable == (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END))
return len;

if (enable && !ctx->delayed_ndp16) {
ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL);
if (!ctx->delayed_ndp16)
return -ENOMEM;
}

/* flush pending data before changing flag */
netif_tx_lock_bh(dev->net);
usbnet_start_xmit(NULL, dev->net);
spin_lock_bh(&ctx->mtx);
if (enable)
ctx->drvflags |= CDC_NCM_FLAG_NDP_TO_END;
else
ctx->drvflags &= ~CDC_NCM_FLAG_NDP_TO_END;
spin_unlock_bh(&ctx->mtx);
netif_tx_unlock_bh(dev->net);

return len;
}
static DEVICE_ATTR_RW(ndp_to_end);

#define NCM_PARM_ATTR(name, format, tocpu) \
static ssize_t cdc_ncm_show_##name(struct device *d, struct device_attribute *attr, char *buf) \
{ \
Expand All @@ -305,6 +347,7 @@ NCM_PARM_ATTR(wNtbOutMaxDatagrams, "%u", le16_to_cpu);

static struct attribute *cdc_ncm_sysfs_attrs[] = {
&dev_attr_min_tx_pkt.attr,
&dev_attr_ndp_to_end.attr,
&dev_attr_rx_max.attr,
&dev_attr_tx_max.attr,
&dev_attr_tx_timer_usecs.attr,
Expand Down

0 comments on commit 404814a

Please sign in to comment.