net: cdc_ncm: add "ndp_to_end" sysfs attribute
[cascardo/linux.git] / drivers / net / usb / cdc_ncm.c
index 3b1ba82..b45e5ca 100644 (file)
@@ -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,