[PATCH 04/10] net-sysfs.c changes.
From: Krishna Kumar <hidden>
Date: 2007-07-20 06:34:34
Support to turn on/off batching from /sys. Signed-off-by: Krishna Kumar <redacted> --- net-sysfs.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 70 insertions(+) diff -ruNp org/net/core/net-sysfs.c new/net/core/net-sysfs.c
--- org/net/core/net-sysfs.c 2007-07-20 07:49:28.000000000 +0530
+++ new/net/core/net-sysfs.c 2007-07-20 08:34:45.000000000 +0530@@ -230,6 +230,74 @@ static ssize_t store_weight(struct devic return netdev_store(dev, attr, buf, len, change_weight); } +static ssize_t show_tx_batch_skbs(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct net_device *netdev = to_net_dev(dev); + + return sprintf(buf, fmt_dec, netdev->skb_blist ? 1 : 0); +} + +static int change_tx_batch_skbs(struct net_device *net, + unsigned long new_tx_batch_skbs) +{ + int ret = 0; + struct sk_buff_head *blist; + + if (!(net->features & NETIF_F_BATCH_SKBS) || + (new_tx_batch_skbs && net->tx_queue_len < MIN_QUEUE_LEN_BATCH)) { + /* + * Driver doesn't support batching SKBS, or the queue len + * is insufficient. TODO: Add similar check to disable + * batching in change_tx_queue_len() if queue_len becomes + * smaller than MIN_QUEUE_LEN_BATCH. + */ + ret = -ENOTSUPP; + goto out; + } + + /* Handle invalid argument */ + if (new_tx_batch_skbs < 0) { + ret = -EINVAL; + goto out; + } + + /* Check if new value is same as the current */ + new_tx_batch_skbs = !!new_tx_batch_skbs; + if (!!net->skb_blist == new_tx_batch_skbs) + goto out; + + if (new_tx_batch_skbs && + (blist = kmalloc(sizeof *blist, GFP_KERNEL)) == NULL) { + ret = -ENOMEM; + goto out; + } + + spin_lock(&net->queue_lock); + if (new_tx_batch_skbs) { + skb_queue_head_init(blist); + net->skb_blist = blist; + net->tx_queue_len >>= 1; + } else { + if (!skb_queue_empty(net->skb_blist)) + skb_queue_purge(net->skb_blist); + kfree(net->skb_blist); + net->skb_blist = NULL; + net->tx_queue_len <<= 1; + } + spin_unlock(&net->queue_lock); + +out: + return ret; +} + +static ssize_t store_tx_batch_skbs(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return netdev_store(dev, attr, buf, len, change_tx_batch_skbs); +} + static struct device_attribute net_class_attributes[] = { __ATTR(addr_len, S_IRUGO, show_addr_len, NULL), __ATTR(iflink, S_IRUGO, show_iflink, NULL),
@@ -246,6 +314,8 @@ static struct device_attribute net_class __ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags), __ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len, store_tx_queue_len), + __ATTR(tx_batch_skbs, S_IRUGO | S_IWUSR, show_tx_batch_skbs, + store_tx_batch_skbs), __ATTR(weight, S_IRUGO | S_IWUSR, show_weight, store_weight), {} };