net: cdc_ncm: add "ndp_to_end" sysfs attribute
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 <mrkiko.rs@gmail.com> Signed-off-by: Bjørn Mork <bjorn@mork.no> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0fe3e20416
commit
404814af69
2 changed files with 62 additions and 0 deletions
|
@ -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 <bjorn@mork.no>
|
||||
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
|
||||
|
|
|
@ -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) \
|
||||
{ \
|
||||
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue