Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 3/3] sky2: Remove failure cases for sky2_rx_start
From: Mike McCormack @ 2010-01-27 22:30 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20100127091024.2ac97d81@nehalam>

2010/1/28 Stephen Hemminger <shemminger@vyatta.com>:
> On Thu, 28 Jan 2010 00:05:54 +0900
> Mike McCormack <mikem@ring3k.org> wrote:
>
>> sky2_rx_start() can no longer fail, so remove redundant code pathes.
>>
>> Signed-off-by: Mike McCormack <mikem@ring3k.org>
>
> This can't work right if MTU is increased. The buffers need to be reallocated
> in change_mtu(); and yes it could fail when getting the new buffers.

Thanks for the feedback.  I will rework the patches.

Mike

^ permalink raw reply

* Re: [PATCH 0/3 v3] macvtap driver
From: Arnd Bergmann @ 2010-01-27 21:59 UTC (permalink / raw)
  To: David Miller
  Cc: Stephen Hemminger, Patrick McHardy, Michael S. Tsirkin,
	Herbert Xu, Or Gerlitz, netdev, bridge, linux-kernel
In-Reply-To: <201001271104.20607.arnd@arndb.de>

On Wednesday 27 January 2010, Arnd Bergmann wrote:
> There are still known problems, but unless there
> are fundamental concerns, I'd like this to go
> into net-next as an experimental driver,
> fixing up the remaining problems by 2.6.34-rc1.

I should have been more specific here. The one
really annoying problem is a reference counting
problem I introduced in one of the last changes
that prevents you from destroying a device after
it has been used.

Unfortunately, I'm still traveling after LCA,
and haven't had a chance to look into this before
sending out the patches as I had originally
planned. I've also seen crashes that are not
fully reproducible, any bug reports on those
are appreciated.

	Arnd

^ permalink raw reply

* [PATCH 3/3] net: macvtap driver
From: Arnd Bergmann @ 2010-01-27 21:09 UTC (permalink / raw)
  To: David Miller
  Cc: Stephen Hemminger, Patrick McHardy, Michael S. Tsirkin,
	Herbert Xu, Or Gerlitz, netdev, bridge, linux-kernel
In-Reply-To: <201001271104.20607.arnd@arndb.de>

In order to use macvlan with qemu and other tools that require
a tap file descriptor, the macvtap driver adds a small backend
with a character device with the same interface as the tun
driver, with a minimum set of features.

Macvtap interfaces are created in the same way as macvlan
interfaces using ip link, but the netif is just used as a
handle for configuration and accounting, while the data
goes through the chardev. Each macvtap interface has its
own character device, simplifying permission management
significantly over the generic tun/tap driver.

Cc: Patrick McHardy <kaber@trash.net>
Cc: Stephen Hemminger <shemminger@linux-foundation.org>
Cc: David S. Miller" <davem@davemloft.net>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Or Gerlitz <ogerlitz@voltaire.com>
Cc: netdev@vger.kernel.org
Cc: bridge@lists.linux-foundation.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/net/Kconfig        |   12 +
 drivers/net/Makefile       |    1 +
 drivers/net/macvtap.c      |  572 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/if_macvlan.h |    1 +
 4 files changed, 586 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/macvtap.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index cb0e534..411e207 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -90,6 +90,18 @@ config MACVLAN
 	  To compile this driver as a module, choose M here: the module
 	  will be called macvlan.
 
+config MACVTAP
+	tristate "MAC-VLAN based tap driver (EXPERIMENTAL)"
+	depends on MACVLAN
+	help
+	  This adds a specialized tap character device driver that is based
+	  on the MAC-VLAN network interface, called macvtap. A macvtap device
+	  can be added in the same way as a macvlan device, using 'type
+	  macvlan', and then be accessed through the tap user space interface.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called macvtap.
+
 config EQUALIZER
 	tristate "EQL (serial line load balancing) support"
 	---help---
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 0b763cb..9595803 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -169,6 +169,7 @@ obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
 obj-$(CONFIG_DUMMY) += dummy.o
 obj-$(CONFIG_IFB) += ifb.o
 obj-$(CONFIG_MACVLAN) += macvlan.o
+obj-$(CONFIG_MACVTAP) += macvtap.o
 obj-$(CONFIG_DE600) += de600.o
 obj-$(CONFIG_DE620) += de620.o
 obj-$(CONFIG_LANCE) += lance.o
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
new file mode 100644
index 0000000..2916202
--- /dev/null
+++ b/drivers/net/macvtap.c
@@ -0,0 +1,572 @@
+#include <linux/etherdevice.h>
+#include <linux/if_macvlan.h>
+#include <linux/interrupt.h>
+#include <linux/nsproxy.h>
+#include <linux/compat.h>
+#include <linux/if_tun.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/cache.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+
+#include <net/net_namespace.h>
+#include <net/rtnetlink.h>
+#include <net/sock.h>
+
+/*
+ * A macvtap queue is the central object of this driver, it connects
+ * an open character device to a macvlan interface. There can be
+ * multiple queues on one interface, which map back to queues
+ * implemented in hardware on the underlying device.
+ *
+ * macvtap_proto is used to allocate queues through the sock allocation
+ * mechanism.
+ *
+ * TODO: multiqueue support is currently not implemented, even though
+ * macvtap is basically prepared for that. We will need to add this
+ * here as well as in virtio-net and qemu to get line rate on 10gbit
+ * adapters from a guest.
+ */
+struct macvtap_queue {
+	struct sock sk;
+	struct socket sock;
+	struct macvlan_dev *vlan;
+	struct file *file;
+};
+
+static struct proto macvtap_proto = {
+	.name = "macvtap",
+	.owner = THIS_MODULE,
+	.obj_size = sizeof (struct macvtap_queue),
+};
+
+/*
+ * Minor number matches netdev->ifindex, so need a potentially
+ * large value. This also makes it possible to split the
+ * tap functionality out again in the future by offering it
+ * from other drivers besides macvtap. As long as every device
+ * only has one tap, the interface numbers assure that the
+ * device nodes are unique.
+ */
+static unsigned int macvtap_major;
+#define MACVTAP_NUM_DEVS 65536
+static struct class *macvtap_class;
+static struct cdev macvtap_cdev;
+
+/*
+ * RCU usage:
+ * The macvtap_queue is referenced both from the chardev struct file
+ * and from the struct macvlan_dev using rcu_read_lock.
+ *
+ * We never actually update the contents of a macvtap_queue atomically
+ * with RCU but it is used for race-free destruction of a queue when
+ * either the file or the macvlan_dev goes away. Pointers back to
+ * the dev and the file are implicitly valid as long as the queue
+ * exists.
+ *
+ * The callbacks from macvlan are always done with rcu_read_lock held
+ * already, while in the file_operations, we get it ourselves.
+ *
+ * When destroying a queue, we remove the pointers from the file and
+ * from the dev and then synchronize_rcu to make sure no thread is
+ * still using the queue. There may still be references to the struct
+ * sock inside of the queue from outbound SKBs, but these never
+ * reference back to the file or the dev. The data structure is freed
+ * through __sk_free when both our references and any pending SKBs
+ * are gone.
+ *
+ * macvtap_lock is only used to prevent multiple concurrent open()
+ * calls to assign a new vlan->tap pointer. It could be moved into
+ * the macvlan_dev itself but is extremely rarely used.
+ */
+static DEFINE_SPINLOCK(macvtap_lock);
+
+/*
+ * Choose the next free queue, for now there is only one
+ */
+static int macvtap_set_queue(struct net_device *dev, struct file *file,
+				struct macvtap_queue *q)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	int err = -EBUSY;
+
+	spin_lock(&macvtap_lock);
+	if (rcu_dereference(vlan->tap))
+		goto out;
+
+	err = 0;
+	q->vlan = vlan;
+	rcu_assign_pointer(vlan->tap, q);
+
+	q->file = file;
+	rcu_assign_pointer(file->private_data, q);
+
+out:
+	spin_unlock(&macvtap_lock);
+	return err;
+}
+
+/*
+ * We must destroy each queue exactly once, when either
+ * the netdev or the file go away.
+ *
+ * Using the spinlock makes sure that we don't get
+ * to the queue again after destroying it.
+ *
+ * synchronize_rcu serializes with the packet flow
+ * that uses rcu_read_lock.
+ */
+static void macvtap_del_queue(struct macvtap_queue **qp)
+{
+	struct macvtap_queue *q;
+
+	spin_lock(&macvtap_lock);
+	q = rcu_dereference(*qp);
+	if (!q) {
+		spin_unlock(&macvtap_lock);
+		return;
+	}
+
+	rcu_assign_pointer(q->vlan->tap, NULL);
+	rcu_assign_pointer(q->file->private_data, NULL);
+	spin_unlock(&macvtap_lock);
+
+	synchronize_rcu();
+	sock_put(&q->sk);
+}
+
+/*
+ * Since we only support one queue, just dereference the pointer.
+ */
+static struct macvtap_queue *macvtap_get_queue(struct net_device *dev,
+					       struct sk_buff *skb)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+
+	return rcu_dereference(vlan->tap);
+}
+
+static void macvtap_del_queues(struct net_device *dev)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	macvtap_del_queue(&vlan->tap);
+}
+
+static inline struct macvtap_queue *macvtap_file_get_queue(struct file *file)
+{
+	rcu_read_lock_bh();
+	return rcu_dereference(file->private_data);
+}
+
+static inline void macvtap_file_put_queue(void)
+{
+	rcu_read_unlock_bh();
+}
+
+/*
+ * Forward happens for data that gets sent from one macvlan
+ * endpoint to another one in bridge mode. We just take
+ * the skb and put it into the receive queue.
+ */
+static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
+{
+	struct macvtap_queue *q = macvtap_get_queue(dev, skb);
+	if (!q)
+		return -ENOLINK;
+
+	skb_queue_tail(&q->sk.sk_receive_queue, skb);
+	wake_up(q->sk.sk_sleep);
+	return 0;
+}
+
+/*
+ * Receive is for data from the external interface (lowerdev),
+ * in case of macvtap, we can treat that the same way as
+ * forward, which macvlan cannot.
+ */
+static int macvtap_receive(struct sk_buff *skb)
+{
+	skb_push(skb, ETH_HLEN);
+	return macvtap_forward(skb->dev, skb);
+}
+
+static int macvtap_newlink(struct net *src_net,
+			   struct net_device *dev,
+			   struct nlattr *tb[],
+			   struct nlattr *data[])
+{
+	struct device *classdev;
+	dev_t devt;
+	int err;
+
+	err = macvlan_common_newlink(src_net, dev, tb, data,
+				     macvtap_receive, macvtap_forward);
+	if (err)
+		goto out;
+
+	devt = MKDEV(MAJOR(macvtap_major), dev->ifindex);
+
+	classdev = device_create(macvtap_class, &dev->dev, devt,
+				 dev, "tap%d", dev->ifindex);
+	if (IS_ERR(classdev)) {
+		err = PTR_ERR(classdev);
+		macvtap_del_queues(dev);
+	}
+
+out:
+	return err;
+}
+
+static void macvtap_dellink(struct net_device *dev,
+			    struct list_head *head)
+{
+	device_destroy(macvtap_class,
+		       MKDEV(MAJOR(macvtap_major), dev->ifindex));
+
+	macvtap_del_queues(dev);
+	macvlan_dellink(dev, head);
+}
+
+static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
+	.kind		= "macvtap",
+	.newlink	= macvtap_newlink,
+	.dellink	= macvtap_dellink,
+};
+
+
+static void macvtap_sock_write_space(struct sock *sk)
+{
+	if (!sock_writeable(sk) ||
+	    !test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags))
+		return;
+
+	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+		wake_up_interruptible_sync(sk->sk_sleep);
+}
+
+static int macvtap_open(struct inode *inode, struct file *file)
+{
+	struct net *net = current->nsproxy->net_ns;
+	struct net_device *dev = dev_get_by_index(net, iminor(inode));
+	struct macvtap_queue *q;
+	int err;
+
+	err = -ENODEV;
+	if (!dev)
+		goto out;
+
+	/* check if this is a macvtap device */
+	err = -EINVAL;
+	if (dev->rtnl_link_ops != &macvtap_link_ops)
+		goto out;
+
+	err = -ENOMEM;
+	q = (struct macvtap_queue *)sk_alloc(net, AF_UNSPEC, GFP_KERNEL,
+					     &macvtap_proto);
+	if (!q)
+		goto out;
+
+	init_waitqueue_head(&q->sock.wait);
+	q->sock.type = SOCK_RAW;
+	q->sock.state = SS_CONNECTED;
+	sock_init_data(&q->sock, &q->sk);
+	q->sk.sk_allocation = GFP_ATOMIC; /* for now */
+	q->sk.sk_write_space = macvtap_sock_write_space;
+
+	err = macvtap_set_queue(dev, file, q);
+	if (err)
+		sock_put(&q->sk);
+
+out:
+	return err;
+}
+
+static int macvtap_release(struct inode *inode, struct file *file)
+{
+	macvtap_del_queue((struct macvtap_queue **)&file->private_data);
+	return 0;
+}
+
+static unsigned int macvtap_poll(struct file *file, poll_table * wait)
+{
+	struct macvtap_queue *q = macvtap_file_get_queue(file);
+	unsigned int mask = POLLERR;
+
+	if (!q)
+		goto out;
+
+	mask = 0;
+	poll_wait(file, &q->sock.wait, wait);
+
+	if (!skb_queue_empty(&q->sk.sk_receive_queue))
+		mask |= POLLIN | POLLRDNORM;
+
+	if (sock_writeable(&q->sk) ||
+	    (!test_and_set_bit(SOCK_ASYNC_NOSPACE, &q->sock.flags) &&
+	     sock_writeable(&q->sk)))
+		mask |= POLLOUT | POLLWRNORM;
+
+out:
+	macvtap_file_put_queue();
+	return mask;
+}
+
+/* Get packet from user space buffer */
+static ssize_t macvtap_get_user(struct macvtap_queue *q,
+				const struct iovec *iv, size_t count,
+				int noblock)
+{
+	struct sk_buff *skb;
+	size_t len = count;
+	int err;
+
+	if (unlikely(len < ETH_HLEN))
+		return -EINVAL;
+
+	skb = sock_alloc_send_skb(&q->sk, NET_IP_ALIGN + len, noblock, &err);
+
+	if (!skb) {
+		macvlan_count_rx(q->vlan, 0, false, false);
+		return err;
+	}
+
+	skb_reserve(skb, NET_IP_ALIGN);
+	skb_put(skb, count);
+
+	if (skb_copy_datagram_from_iovec(skb, 0, iv, 0, len)) {
+		macvlan_count_rx(q->vlan, 0, false, false);
+		kfree_skb(skb);
+		return -EFAULT;
+	}
+
+	skb_set_network_header(skb, ETH_HLEN);
+
+	macvlan_start_xmit(skb, q->vlan->dev);
+
+	return count;
+}
+
+static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv,
+				 unsigned long count, loff_t pos)
+{
+	struct file *file = iocb->ki_filp;
+	ssize_t result = -ENOLINK;
+	struct macvtap_queue *q = macvtap_file_get_queue(file);
+
+	if (!q)
+		goto out;
+
+	result = macvtap_get_user(q, iv, iov_length(iv, count),
+			      file->f_flags & O_NONBLOCK);
+out:
+	macvtap_file_put_queue();
+	return result;
+}
+
+/* Put packet to the user space buffer */
+static ssize_t macvtap_put_user(struct macvtap_queue *q,
+				const struct sk_buff *skb,
+				const struct iovec *iv, int len)
+{
+	struct macvlan_dev *vlan = q->vlan;
+	int ret;
+
+	len = min_t(int, skb->len, len);
+
+	ret = skb_copy_datagram_const_iovec(skb, 0, iv, 0, len);
+
+	macvlan_count_rx(vlan, len, ret == 0, 0);
+
+	return ret ? ret : len;
+}
+
+static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv,
+				unsigned long count, loff_t pos)
+{
+	struct file *file = iocb->ki_filp;
+	struct macvtap_queue *q = macvtap_file_get_queue(file);
+
+	DECLARE_WAITQUEUE(wait, current);
+	struct sk_buff *skb;
+	ssize_t len, ret = 0;
+
+	if (!q) {
+		ret = -ENOLINK;
+		goto out;
+	}
+
+	len = iov_length(iv, count);
+	if (len < 0) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	add_wait_queue(q->sk.sk_sleep, &wait);
+	while (len) {
+		current->state = TASK_INTERRUPTIBLE;
+
+		/* Read frames from the queue */
+		skb = skb_dequeue(&q->sk.sk_receive_queue);
+		if (!skb) {
+			if (file->f_flags & O_NONBLOCK) {
+				ret = -EAGAIN;
+				break;
+			}
+			if (signal_pending(current)) {
+				ret = -ERESTARTSYS;
+				break;
+			}
+			/* Nothing to read, let's sleep */
+			schedule();
+			continue;
+		}
+		ret = macvtap_put_user(q, skb, iv, len);
+		kfree_skb(skb);
+		break;
+	}
+
+	current->state = TASK_RUNNING;
+	remove_wait_queue(q->sk.sk_sleep, &wait);
+
+out:
+	macvtap_file_put_queue();
+	return ret;
+}
+
+/*
+ * provide compatibility with generic tun/tap interface
+ */
+static long macvtap_ioctl(struct file *file, unsigned int cmd,
+			  unsigned long arg)
+{
+	struct macvtap_queue *q;
+	void __user *argp = (void __user *)arg;
+	struct ifreq __user *ifr = argp;
+	unsigned int __user *up = argp;
+	unsigned int u;
+	int err;
+
+	switch (cmd) {
+	case TUNSETIFF:
+		/* ignore the name, just look at flags */
+		if (get_user(u, &ifr->ifr_flags))
+			return -EFAULT;
+		if (u != (IFF_TAP | IFF_NO_PI))
+			return -EINVAL;
+		return 0;
+
+	case TUNGETIFF:
+		q = macvtap_file_get_queue(file);
+		if (!q)
+			return -ENOLINK;
+		err = 0;
+		if (copy_to_user(&ifr->ifr_name, q->vlan->dev->name, IFNAMSIZ) ||
+		    put_user((TUN_TAP_DEV | TUN_NO_PI), &ifr->ifr_flags))
+			err = -EFAULT;
+		macvtap_file_put_queue();
+		return err;
+
+	case TUNGETFEATURES:
+		if (put_user((IFF_TAP | IFF_NO_PI), up))
+			return -EFAULT;
+		return 0;
+
+	case TUNSETSNDBUF:
+		/* ignore */
+		return 0;
+
+	case TUNSETOFFLOAD:
+		/* let the user check for future flags */
+		if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
+			  TUN_F_TSO_ECN | TUN_F_UFO))
+			return -EINVAL;
+
+		/* TODO: add support for these, so far we don't
+			 support any offload */
+		if (arg & (TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
+			 TUN_F_TSO_ECN | TUN_F_UFO))
+			return -EINVAL;
+
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+#ifdef CONFIG_COMPAT
+static long macvtap_compat_ioctl(struct file *file, unsigned int cmd,
+				 unsigned long arg)
+{
+	return macvtap_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
+
+static const struct file_operations macvtap_fops = {
+	.owner		= THIS_MODULE,
+	.open		= macvtap_open,
+	.release	= macvtap_release,
+	.aio_read	= macvtap_aio_read,
+	.aio_write	= macvtap_aio_write,
+	.poll		= macvtap_poll,
+	.llseek		= no_llseek,
+	.unlocked_ioctl	= macvtap_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= macvtap_compat_ioctl,
+#endif
+};
+
+static int macvtap_init(void)
+{
+	int err;
+
+	err = alloc_chrdev_region(&macvtap_major, 0,
+				MACVTAP_NUM_DEVS, "macvtap");
+	if (err)
+		goto out1;
+
+	cdev_init(&macvtap_cdev, &macvtap_fops);
+	err = cdev_add(&macvtap_cdev, macvtap_major, MACVTAP_NUM_DEVS);
+	if (err)
+		goto out2;
+
+	macvtap_class = class_create(THIS_MODULE, "macvtap");
+	if (IS_ERR(macvtap_class)) {
+		err = PTR_ERR(macvtap_class);
+		goto out3;
+	}
+
+	err = macvlan_link_register(&macvtap_link_ops);
+	if (err)
+		goto out4;
+
+	return 0;
+
+out4:
+	class_unregister(macvtap_class);
+out3:
+	cdev_del(&macvtap_cdev);
+out2:
+	unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
+out1:
+	return err;
+}
+module_init(macvtap_init);
+
+static void macvtap_exit(void)
+{
+	rtnl_link_unregister(&macvtap_link_ops);
+	class_unregister(macvtap_class);
+	cdev_del(&macvtap_cdev);
+	unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
+}
+module_exit(macvtap_exit);
+
+MODULE_ALIAS_RTNL_LINK("macvtap");
+MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index 9a11544..51f1512 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -34,6 +34,7 @@ struct macvlan_dev {
 	enum macvlan_mode	mode;
 	int (*receive)(struct sk_buff *skb);
 	int (*forward)(struct net_device *dev, struct sk_buff *skb);
+	struct macvtap_queue	*tap;
 };
 
 static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
-- 
1.6.3.3


^ permalink raw reply related

* pull request: wireless-2.6 2010-01-27
From: John W. Linville @ 2010-01-27 21:35 UTC (permalink / raw)
  To: davem; +Cc: linux-wireless, netdev, linux-kernel

Dave,

Here is another small collections of fixes intended for 2.6.33.
Included are a NULL pointer dereference fix, a buffer leak fix,
a warning fix, and a correction of an ath9k initialization change
that was improperly limited to only dual-band hardware.

Please let me know if there are problems!

Thanks,

John

---

The following changes since commit c92b544bd5d8e7ed7d81c77bbecab6df2a95aa53:
  Shan Wei (1):
        ipv6: conntrack: Add member of user to nf_ct_frag6_queue structure

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git master

Felix Fietkau (2):
      ath9k: fix beacon slot/buffer leak
      ath9k: fix eeprom INI values override for 2GHz-only cards

Johannes Berg (1):
      iwlwifi: fix pointer signedness warning

Zhu Yi (1):
      mac80211: fix NULL pointer dereference when ftrace is enabled

 drivers/net/wireless/ath/ath9k/hw.c    |    7 +++----
 drivers/net/wireless/ath/ath9k/main.c  |    2 +-
 drivers/net/wireless/iwlwifi/iwl-sta.c |    4 ++--
 net/mac80211/driver-trace.h            |    2 +-
 4 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 2ec61f0..ae37144 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -855,12 +855,11 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
 	}
 }
 
-static void ath9k_hw_init_11a_eeprom_fix(struct ath_hw *ah)
+static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah)
 {
 	u32 i, j;
 
-	if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
-	    test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) {
+	if (ah->hw_version.devid == AR9280_DEVID_PCI) {
 
 		/* EEPROM Fixup */
 		for (i = 0; i < ah->iniModes.ia_rows; i++) {
@@ -980,7 +979,7 @@ int ath9k_hw_init(struct ath_hw *ah)
 	if (r)
 		return r;
 
-	ath9k_hw_init_11a_eeprom_fix(ah);
+	ath9k_hw_init_eeprom_fix(ah);
 
 	r = ath9k_hw_init_macaddr(ah);
 	if (r) {
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 996eb90..643bea3 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -2655,10 +2655,10 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
 	    (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
 		ath9k_ps_wakeup(sc);
 		ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-		ath_beacon_return(sc, avp);
 		ath9k_ps_restore(sc);
 	}
 
+	ath_beacon_return(sc, avp);
 	sc->sc_flags &= ~SC_OP_BEACONS;
 
 	for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index cde09a8..90fbdb2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -297,7 +297,7 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags,
 }
 EXPORT_SYMBOL(iwl_add_station);
 
-static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
+static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const u8 *addr)
 {
 	unsigned long flags;
 	u8 sta_id = iwl_find_station(priv, addr);
@@ -324,7 +324,7 @@ static void iwl_remove_sta_callback(struct iwl_priv *priv,
 {
 	struct iwl_rem_sta_cmd *rm_sta =
 			(struct iwl_rem_sta_cmd *)cmd->cmd.payload;
-	const char *addr = rm_sta->addr;
+	const u8 *addr = rm_sta->addr;
 
 	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
 		IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index ee94ea0..da8497e 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -680,7 +680,7 @@ TRACE_EVENT(drv_ampdu_action,
 		__entry->ret = ret;
 		__entry->action = action;
 		__entry->tid = tid;
-		__entry->ssn = *ssn;
+		__entry->ssn = ssn ? *ssn : 0;
 	),
 
 	TP_printk(
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply related

* Re: 0% cpu usasge after fresh boot or net restart but 10% CPU if kernel flush route cache
From: Eric Dumazet @ 2010-01-27 21:18 UTC (permalink / raw)
  To: cold cold; +Cc: netdev
In-Reply-To: <41ac0f9e1001271153u333a5e2aq6f473ccc6e6d1e23@mail.gmail.com>

Le mercredi 27 janvier 2010 à 21:53 +0200, cold cold a écrit :

> 
> btw atm i have 1k ip on that router but plan to put 10k so route cache
> will grow 10 time fast.
> i try to keep low  rhash_entries but garbage collector  is non stop
> running and eat CPU
> atm i have around 7k  entries per second for second for first minute.
> 
> i think it will be better if i flush cache on secret interval instead
> of giving work to gc.
> i test with 512MB cache and CPU is 0% and flushing entire hash dont take a lot,
> I'm not sure is there some side effects from flushing.

Flush is immediate, it only marks entries as invalid and they are
cleaned up later.

512 MB cache is quite small for your needs, each entry uses 384 bytes
(assuming you use a 64bit kernel)

In my experiments, I found using gc (and no flushing) was the most
reliable way to have an equilibrium.

WHen setting gc_interval to 1,  the garbage collector is fired every
second and handles 1/300 of entries, from a work queue (thus doesnt stop
packets to be handled by irqs), in a smooth way.

You can post "perf top" results to check where cpu is consumed.



^ permalink raw reply

* [PATCH 0/3 v3] macvtap driver
From: Arnd Bergmann @ 2010-01-27 10:04 UTC (permalink / raw)
  To: David Miller
  Cc: Stephen Hemminger, Patrick McHardy, Michael S. Tsirkin,
	Herbert Xu, Or Gerlitz, netdev, bridge, linux-kernel

This is the third version of the macvtap device driver, following another major restructuring and a lot of bug fixes:

* Change macvtap to be based around a struct sock
* macvtap: fix initialization
* return 0 to netlink
* don't use rcu for q->file and q->vlan pointers
* macvtap: checkpatch.pl fixes
* macvtap: fix tun IFF flags
* Use a struct socket to make tx flow control work
* disable BH processing during transmit
* only add an ethernet header for receive not forward
* allocate the SKB using GFP_NOWAIT since we're
  in rcu_read_lock
* use atomic allocation for socket
* fix blocking on send
* do not destroy netdev twice in error path

There are still known problems, but unless there
are fundamental concerns, I'd like this to go
into net-next as an experimental driver,
fixing up the remaining problems by 2.6.34-rc1.

	Arnd

^ permalink raw reply

* [PATCH 2/3] net/macvlan: allow multiple driver backends
From: Arnd Bergmann @ 2010-01-27 10:06 UTC (permalink / raw)
  To: David Miller
  Cc: Stephen Hemminger, Patrick McHardy, Michael S. Tsirkin,
	Herbert Xu, Or Gerlitz, netdev, bridge, linux-kernel
In-Reply-To: <201001271104.20607.arnd@arndb.de>

This makes it possible to hook into the macvlan driver
from another kernel module. In particular, the goal is
to extend it with the macvtap backend that provides
a tun/tap compatible interface directly on the macvlan
device.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/net/macvlan.c      |  113 +++++++++++++++++++-------------------------
 include/linux/if_macvlan.h |   70 +++++++++++++++++++++++++++
 2 files changed, 119 insertions(+), 64 deletions(-)

diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index e0436fd..1517537 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -39,31 +39,6 @@ struct macvlan_port {
 	struct list_head	vlans;
 };
 
-/**
- *	struct macvlan_rx_stats - MACVLAN percpu rx stats
- *	@rx_packets: number of received packets
- *	@rx_bytes: number of received bytes
- *	@multicast: number of received multicast packets
- *	@rx_errors: number of errors
- */
-struct macvlan_rx_stats {
-	unsigned long rx_packets;
-	unsigned long rx_bytes;
-	unsigned long multicast;
-	unsigned long rx_errors;
-};
-
-struct macvlan_dev {
-	struct net_device	*dev;
-	struct list_head	list;
-	struct hlist_node	hlist;
-	struct macvlan_port	*port;
-	struct net_device	*lowerdev;
-	struct macvlan_rx_stats *rx_stats;
-	enum macvlan_mode	mode;
-};
-
-
 static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port,
 					       const unsigned char *addr)
 {
@@ -118,31 +93,17 @@ static int macvlan_addr_busy(const struct macvlan_port *port,
 	return 0;
 }
 
-static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
-				    unsigned int len, bool success,
-				    bool multicast)
-{
-	struct macvlan_rx_stats *rx_stats;
-
-	rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id());
-	if (likely(success)) {
-		rx_stats->rx_packets++;;
-		rx_stats->rx_bytes += len;
-		if (multicast)
-			rx_stats->multicast++;
-	} else {
-		rx_stats->rx_errors++;
-	}
-}
 
-static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev,
+static int macvlan_broadcast_one(struct sk_buff *skb,
+				 const struct macvlan_dev *vlan,
 				 const struct ethhdr *eth, bool local)
 {
+	struct net_device *dev = vlan->dev;
 	if (!skb)
 		return NET_RX_DROP;
 
 	if (local)
-		return dev_forward_skb(dev, skb);
+		return vlan->forward(dev, skb);
 
 	skb->dev = dev;
 	if (!compare_ether_addr_64bits(eth->h_dest,
@@ -151,7 +112,7 @@ static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev,
 	else
 		skb->pkt_type = PACKET_MULTICAST;
 
-	return netif_receive_skb(skb);
+	return vlan->receive(skb);
 }
 
 static void macvlan_broadcast(struct sk_buff *skb,
@@ -175,7 +136,7 @@ static void macvlan_broadcast(struct sk_buff *skb,
 				continue;
 
 			nskb = skb_clone(skb, GFP_ATOMIC);
-			err = macvlan_broadcast_one(nskb, vlan->dev, eth,
+			err = macvlan_broadcast_one(nskb, vlan, eth,
 					 mode == MACVLAN_MODE_BRIDGE);
 			macvlan_count_rx(vlan, skb->len + ETH_HLEN,
 					 err == NET_RX_SUCCESS, 1);
@@ -238,7 +199,7 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
 	skb->dev = dev;
 	skb->pkt_type = PACKET_HOST;
 
-	netif_receive_skb(skb);
+	vlan->receive(skb);
 	return NULL;
 }
 
@@ -260,7 +221,7 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
 		dest = macvlan_hash_lookup(port, eth->h_dest);
 		if (dest && dest->mode == MACVLAN_MODE_BRIDGE) {
 			unsigned int length = skb->len + ETH_HLEN;
-			int ret = dev_forward_skb(dest->dev, skb);
+			int ret = dest->forward(dest->dev, skb);
 			macvlan_count_rx(dest, length,
 					 ret == NET_RX_SUCCESS, 0);
 
@@ -273,8 +234,8 @@ xmit_world:
 	return dev_queue_xmit(skb);
 }
 
-static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
-				      struct net_device *dev)
+netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
+			       struct net_device *dev)
 {
 	int i = skb_get_queue_mapping(skb);
 	struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
@@ -290,6 +251,7 @@ static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(macvlan_start_xmit);
 
 static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
 			       unsigned short type, const void *daddr,
@@ -623,8 +585,11 @@ static int macvlan_get_tx_queues(struct net *net,
 	return 0;
 }
 
-static int macvlan_newlink(struct net *src_net, struct net_device *dev,
-			   struct nlattr *tb[], struct nlattr *data[])
+int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
+			   struct nlattr *tb[], struct nlattr *data[],
+			   int (*receive)(struct sk_buff *skb),
+			   int (*forward)(struct net_device *dev,
+					  struct sk_buff *skb))
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
 	struct macvlan_port *port;
@@ -664,6 +629,8 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev,
 	vlan->lowerdev = lowerdev;
 	vlan->dev      = dev;
 	vlan->port     = port;
+	vlan->receive  = receive;
+	vlan->forward  = forward;
 
 	vlan->mode     = MACVLAN_MODE_VEPA;
 	if (data && data[IFLA_MACVLAN_MODE])
@@ -677,8 +644,17 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev,
 	netif_stacked_transfer_operstate(lowerdev, dev);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(macvlan_common_newlink);
 
-static void macvlan_dellink(struct net_device *dev, struct list_head *head)
+static int macvlan_newlink(struct net *src_net, struct net_device *dev,
+			   struct nlattr *tb[], struct nlattr *data[])
+{
+	return macvlan_common_newlink(src_net, dev, tb, data,
+				      netif_receive_skb,
+				      dev_forward_skb);
+}
+
+void macvlan_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
 	struct macvlan_port *port = vlan->port;
@@ -689,6 +665,7 @@ static void macvlan_dellink(struct net_device *dev, struct list_head *head)
 	if (list_empty(&port->vlans))
 		macvlan_port_destroy(port->dev);
 }
+EXPORT_SYMBOL_GPL(macvlan_dellink);
 
 static int macvlan_changelink(struct net_device *dev,
 		struct nlattr *tb[], struct nlattr *data[])
@@ -720,19 +697,27 @@ static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
 	[IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
 };
 
-static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
+int macvlan_link_register(struct rtnl_link_ops *ops)
+{
+	/* common fields */
+	ops->priv_size		= sizeof(struct macvlan_dev);
+	ops->get_tx_queues	= macvlan_get_tx_queues;
+	ops->setup		= macvlan_setup;
+	ops->validate		= macvlan_validate;
+	ops->maxtype		= IFLA_MACVLAN_MAX;
+	ops->policy		= macvlan_policy;
+	ops->changelink		= macvlan_changelink;
+	ops->get_size		= macvlan_get_size;
+	ops->fill_info		= macvlan_fill_info;
+
+	return rtnl_link_register(ops);
+};
+EXPORT_SYMBOL_GPL(macvlan_link_register);
+
+static struct rtnl_link_ops macvlan_link_ops = {
 	.kind		= "macvlan",
-	.priv_size	= sizeof(struct macvlan_dev),
-	.get_tx_queues  = macvlan_get_tx_queues,
-	.setup		= macvlan_setup,
-	.validate	= macvlan_validate,
 	.newlink	= macvlan_newlink,
 	.dellink	= macvlan_dellink,
-	.maxtype	= IFLA_MACVLAN_MAX,
-	.policy		= macvlan_policy,
-	.changelink	= macvlan_changelink,
-	.get_size	= macvlan_get_size,
-	.fill_info	= macvlan_fill_info,
 };
 
 static int macvlan_device_event(struct notifier_block *unused,
@@ -761,7 +746,7 @@ static int macvlan_device_event(struct notifier_block *unused,
 		break;
 	case NETDEV_UNREGISTER:
 		list_for_each_entry_safe(vlan, next, &port->vlans, list)
-			macvlan_dellink(vlan->dev, NULL);
+			vlan->dev->rtnl_link_ops->dellink(vlan->dev, NULL);
 		break;
 	}
 	return NOTIFY_DONE;
@@ -778,7 +763,7 @@ static int __init macvlan_init_module(void)
 	register_netdevice_notifier(&macvlan_notifier_block);
 	macvlan_handle_frame_hook = macvlan_handle_frame;
 
-	err = rtnl_link_register(&macvlan_link_ops);
+	err = macvlan_link_register(&macvlan_link_ops);
 	if (err < 0)
 		goto err1;
 	return 0;
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index 5f200ba..9a11544 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -1,6 +1,76 @@
 #ifndef _LINUX_IF_MACVLAN_H
 #define _LINUX_IF_MACVLAN_H
 
+#include <linux/if_link.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/netlink.h>
+#include <net/netlink.h>
+
+struct macvlan_port;
+struct macvtap_queue;
+
+/**
+ *	struct macvlan_rx_stats - MACVLAN percpu rx stats
+ *	@rx_packets: number of received packets
+ *	@rx_bytes: number of received bytes
+ *	@multicast: number of received multicast packets
+ *	@rx_errors: number of errors
+ */
+struct macvlan_rx_stats {
+	unsigned long rx_packets;
+	unsigned long rx_bytes;
+	unsigned long multicast;
+	unsigned long rx_errors;
+};
+
+struct macvlan_dev {
+	struct net_device	*dev;
+	struct list_head	list;
+	struct hlist_node	hlist;
+	struct macvlan_port	*port;
+	struct net_device	*lowerdev;
+	struct macvlan_rx_stats *rx_stats;
+	enum macvlan_mode	mode;
+	int (*receive)(struct sk_buff *skb);
+	int (*forward)(struct net_device *dev, struct sk_buff *skb);
+};
+
+static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
+				    unsigned int len, bool success,
+				    bool multicast)
+{
+	struct macvlan_rx_stats *rx_stats;
+
+	rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id());
+	if (likely(success)) {
+		rx_stats->rx_packets++;;
+		rx_stats->rx_bytes += len;
+		if (multicast)
+			rx_stats->multicast++;
+	} else {
+		rx_stats->rx_errors++;
+	}
+}
+
+extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
+				  struct nlattr *tb[], struct nlattr *data[],
+				  int (*receive)(struct sk_buff *skb),
+				  int (*forward)(struct net_device *dev,
+						 struct sk_buff *skb));
+
+extern void macvlan_count_rx(const struct macvlan_dev *vlan,
+			     unsigned int len, bool success,
+			     bool multicast);
+
+extern void macvlan_dellink(struct net_device *dev, struct list_head *head);
+
+extern int macvlan_link_register(struct rtnl_link_ops *ops);
+
+extern netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
+				      struct net_device *dev);
+
+
 extern struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *);
 
 #endif /* _LINUX_IF_MACVLAN_H */
-- 
1.6.3.3




^ permalink raw reply related

* [PATCH] netdev: remove more HAVE_ leftovers
From: Alexey Dobriyan @ 2010-01-27 20:17 UTC (permalink / raw)
  To: David Miller; +Cc: geert, linux-next, netdev, linux-kernel
In-Reply-To: <20100126.163256.196562963.davem@davemloft.net>

On Tue, Jan 26, 2010 at 04:32:56PM -0800, David Miller wrote:
> From: Alexey Dobriyan <adobriyan@gmail.com>
> Date: Tue, 26 Jan 2010 21:17:27 +0200
> 
> > On Tue, Jan 26, 2010 at 05:18:17AM -0800, David Miller wrote:
> >> Alexey, please go through at least drivers/net and look at the
> >> other stale references to these HAVE_* macros.
> > 
> > My apologies.
> > 
> > 
> > [PATCH] netdev: remove HAVE_ leftovers
> > 
> > Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
> 
> What about HAVE_POLL_CONTROLLER and some other remaining stuff?

Ick, I thought I left some compile breakage :^)

> drivers/net/bnx2.c:#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
> drivers/net/bnx2x_main.c:#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
> drivers/net/ixgbevf/ixgbevf_main.c:#ifdef HAVE_TX_MQ
> drivers/net/ixgbevf/ixgbevf_main.c:#ifndef HAVE_NETDEV_NAPI_LIST
> drivers/net/ixgbevf/ixgbevf_main.c:#ifdef HAVE_NET_DEVICE_OPS

As for HAVE_TX_MQ and HAVE_NETDEV_NAPI_LIST, I have no clue what's going on.

[PATCH] netdev: remove more HAVE_ leftovers 

Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---

 drivers/net/bnx2.c                     |    4 ++--
 drivers/net/bnx2x_main.c               |    4 ++--
 drivers/net/cassini.c                  |    2 +-
 drivers/net/ixgbevf/ixgbevf_main.c     |   18 ------------------
 drivers/net/meth.c                     |    3 ---
 drivers/staging/wlags49_h2/wl_netdev.c |    6 ------
 6 files changed, 5 insertions(+), 32 deletions(-)

--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -7668,7 +7668,7 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu)
 	return (bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size));
 }
 
-#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+#ifdef CONFIG_NET_POLL_CONTROLLER
 static void
 poll_bnx2(struct net_device *dev)
 {
@@ -8280,7 +8280,7 @@ static const struct net_device_ops bnx2_netdev_ops = {
 #ifdef BCM_VLAN
 	.ndo_vlan_rx_register	= bnx2_vlan_rx_register,
 #endif
-#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+#ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= poll_bnx2,
 #endif
 };
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -11731,7 +11731,7 @@ static void bnx2x_vlan_rx_register(struct net_device *dev,
 
 #endif
 
-#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+#ifdef CONFIG_NET_POLL_CONTROLLER
 static void poll_bnx2x(struct net_device *dev)
 {
 	struct bnx2x *bp = netdev_priv(dev);
@@ -11755,7 +11755,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
 #ifdef BCM_VLAN
 	.ndo_vlan_rx_register	= bnx2x_vlan_rx_register,
 #endif
-#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+#ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= poll_bnx2x,
 #endif
 };
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -106,7 +106,7 @@
 #define cas_page_unmap(x)    kunmap_atomic((x), KM_SKB_DATA_SOFTIRQ)
 #define CAS_NCPUS            num_online_cpus()
 
-#if defined(CONFIG_CASSINI_NAPI) && defined(HAVE_NETDEV_POLL)
+#ifdef CONFIG_CASSINI_NAPI
 #define USE_NAPI
 #define cas_skb_release(x)  netif_receive_skb(x)
 #else
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -3262,7 +3262,6 @@ static void ixgbevf_shutdown(struct pci_dev *pdev)
 	pci_disable_device(pdev);
 }
 
-#ifdef HAVE_NET_DEVICE_OPS
 static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_open		= &ixgbevf_open,
 	.ndo_stop		= &ixgbevf_close,
@@ -3278,29 +3277,12 @@ static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_vlan_rx_add_vid	= &ixgbevf_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= &ixgbevf_vlan_rx_kill_vid,
 };
-#endif /* HAVE_NET_DEVICE_OPS */
 
 static void ixgbevf_assign_netdev_ops(struct net_device *dev)
 {
 	struct ixgbevf_adapter *adapter;
 	adapter = netdev_priv(dev);
-#ifdef HAVE_NET_DEVICE_OPS
 	dev->netdev_ops = &ixgbe_netdev_ops;
-#else /* HAVE_NET_DEVICE_OPS */
-	dev->open = &ixgbevf_open;
-	dev->stop = &ixgbevf_close;
-
-	dev->hard_start_xmit = &ixgbevf_xmit_frame;
-
-	dev->get_stats = &ixgbevf_get_stats;
-	dev->set_multicast_list = &ixgbevf_set_rx_mode;
-	dev->set_mac_address = &ixgbevf_set_mac;
-	dev->change_mtu = &ixgbevf_change_mtu;
-	dev->tx_timeout = &ixgbevf_tx_timeout;
-	dev->vlan_rx_register = &ixgbevf_vlan_rx_register;
-	dev->vlan_rx_add_vid = &ixgbevf_vlan_rx_add_vid;
-	dev->vlan_rx_kill_vid = &ixgbevf_vlan_rx_kill_vid;
-#endif /* HAVE_NET_DEVICE_OPS */
 	ixgbevf_set_ethtool_ops(dev);
 	dev->watchdog_timeo = 5 * HZ;
 }
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -51,14 +51,11 @@
 
 static const char *meth_str="SGI O2 Fast Ethernet";
 
-#define HAVE_TX_TIMEOUT
 /* The maximum time waited (in jiffies) before assuming a Tx failed. (400ms) */
 #define TX_TIMEOUT (400*HZ/1000)
 
-#ifdef HAVE_TX_TIMEOUT
 static int timeout = TX_TIMEOUT;
 module_param(timeout, int, 0);
-#endif
 
 /*
  * This structure is private to each device. It is used to pass
--- a/drivers/staging/wlags49_h2/wl_netdev.c
+++ b/drivers/staging/wlags49_h2/wl_netdev.c
@@ -1194,9 +1194,7 @@ static const struct net_device_ops wl_netdev_ops =
     .ndo_stop               = &wl_adapter_close,
     .ndo_do_ioctl           = &wl_ioctl,
 
-#ifdef HAVE_TX_TIMEOUT
     .ndo_tx_timeout         = &wl_tx_timeout,
-#endif
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
     .ndo_poll_controller    = wl_poll,
@@ -1270,9 +1268,7 @@ struct net_device * wl_device_alloc( void )
     dev->stop               = &wl_adapter_close;
     dev->do_ioctl           = &wl_ioctl;
 
-#ifdef HAVE_TX_TIMEOUT
     dev->tx_timeout         = &wl_tx_timeout;
-#endif
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
     dev->poll_controller = wl_poll;
@@ -1280,9 +1276,7 @@ struct net_device * wl_device_alloc( void )
 
 #endif // (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30))
 
-#ifdef HAVE_TX_TIMEOUT
     dev->watchdog_timeo     = TX_TIMEOUT;
-#endif
 
     dev->ethtool_ops	    = &wl_ethtool_ops;
 

^ permalink raw reply

* Re: 0% cpu usasge after fresh boot or net restart but 10% CPU if kernel flush route cache
From: cold cold @ 2010-01-27 19:53 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev
In-Reply-To: <1264605976.3197.8.camel@edumazet-laptop>

On Wed, Jan 27, 2010 at 5:26 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Le mardi 26 janvier 2010 à 18:58 +0200, cold cold a écrit :
>> HI,
>>
>>
>> i have expiriance some CPU usage spikes up to 10% on each four cpus
>> after the first kernel route cache flush.
>> After mashine start first 20 min CPU is 0%si  300Mbits/s full duplex
>> and arount 100k pps forwarded traffic, without any firewall, just
>> plain routing.
>>
>> route -n |wc -l
>> 34
>>
>> ip route show cache | wc -l
>> 2140842
>>
>> cat /proc/sys/net/ipv4/route/secret_interval
>> 600
>> cat /proc/sys/net/ipv4/route/max_size
>> 33554432
>>
>> after kernel  flush i got 10% on all CPUs for 5-6 mins.  It's not from
>> rebuilding route cashe becouse after
>> fresh boot or network restrat there is no CPU usage until kernel flush
>> route cache.
>> I try to play with rhash_entries= 300000 to 2000000 same result.
>
> If you have one million dst entries to flush, it takes some time.
>
> You could try to not increase the rhash_entries
> (or keep it low, say 131072)
> but tune /proc/sys/net/ipv4/route settings.
>
> Try to reduce gc_elasticity from 8 to 2
> Try to reduce gc_interval from 60 to 1
>
> Important thing to consider is to irq affinities (so that one cpu
> handles network interrupts, to minimize cache ping poings )
>


btw atm i have 1k ip on that router but plan to put 10k so route cache
will grow 10 time fast.
i try to keep low  rhash_entries but garbage collector  is non stop
running and eat CPU
atm i have around 7k  entries per second for second for first minute.

i think it will be better if i flush cache on secret interval instead
of giving work to gc.
i test with 512MB cache and CPU is 0% and flushing entire hash dont take a lot,
I'm not sure is there some side effects from flushing.

^ permalink raw reply

* Re: [PATCH] cxgb3/iw_cxgb3: doorbell overflow avoidance and recovery.
From: Divy Le Ray @ 2010-01-27 19:46 UTC (permalink / raw)
  To: Roland Dreier
  Cc: Steve Wise, jeff-o2qLIJkoznsdnm+yROfE0A,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	David Miller
In-Reply-To: <adavdenmjkh.fsf-BjVyx320WGW9gfZ95n9DRSW4+XlvGpQz@public.gmane.org>

Roland Dreier wrote:
>
> Looks reasonable at first reading.  I can take this through my tree,
> assuming it's OK with you, Divy?
>
Hi Roland,

it is okay with me.

Cheers,
Divy

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: Hang: 2.6.32.4 sky2/DMAR (was [PATCH] sky2: Fix WARNING: at lib/dma-debug.c:902 check_sync)
From: Jarek Poplawski @ 2010-01-27 19:32 UTC (permalink / raw)
  To: Michael Breuer
  Cc: Stephen Hemminger, David Miller, akpm, flyboy, linux-kernel,
	netdev, Michael Chan, Don Fry, Francois Romieu, Matt Carlson
In-Reply-To: <20100127192312.GA3135@del.dom.local>

On Wed, Jan 27, 2010 at 08:23:12PM +0100, Jarek Poplawski wrote:
> Stephen, I'm not sure this patch can show much after the patch with
> "legal" dma_size == re->data_addr didn't help. It looks like David

Of course: "dma_size == re->data_size".

Jarek P.

^ permalink raw reply

* Re: [PATCH] cxgb3/iw_cxgb3: doorbell overflow avoidance and recovery.
From: Roland Dreier @ 2010-01-27 19:30 UTC (permalink / raw)
  To: Steve Wise
  Cc: jeff-o2qLIJkoznsdnm+yROfE0A, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, divy-ut6Up61K2wZBDgjK7y7TUQ
In-Reply-To: <20100127170333.19854.40039.stgit-T4OLL4TyM9aNDNWfRnPdfg@public.gmane.org>

Looks reasonable at first reading.  I can take this through my tree,
assuming it's OK with you, Divy?
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: Hang: 2.6.32.4 sky2/DMAR (was [PATCH] sky2: Fix WARNING: at lib/dma-debug.c:902 check_sync)
From: Jarek Poplawski @ 2010-01-27 19:23 UTC (permalink / raw)
  To: Michael Breuer
  Cc: Stephen Hemminger, David Miller, akpm, flyboy, linux-kernel,
	netdev, Michael Chan, Don Fry, Francois Romieu, Matt Carlson
In-Reply-To: <4B6089C7.4010803@majjas.com>

On Wed, Jan 27, 2010 at 01:45:27PM -0500, Michael Breuer wrote:
> On 1/27/2010 1:08 PM, Michael Breuer wrote:
> >On 01/27/2010 12:56 PM, Stephen Hemminger wrote:
> >>--- a/drivers/net/sky2.c    2010-01-27 09:46:10.940005248 -0800
> >>+++ b/drivers/net/sky2.c    2010-01-27 09:53:47.141267850 -0800
> >>@@ -2257,13 +2257,16 @@ static struct sk_buff *receive_copy(stru
> >>
> >>      skb = netdev_alloc_skb_ip_align(sky2->netdev, length);
> >>      if (likely(skb)) {
> >>+        unsigned dma_align = dma_get_cache_alignment();
> >>+        unsigned dma_size = ALIGN(length+1, dma_align);
> >>+
> >>          pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->data_addr,
> >>-                        length, PCI_DMA_FROMDEVICE);
> >>+                        dma_size, PCI_DMA_FROMDEVICE);
> >>          skb_copy_from_linear_data(re->skb, skb->data, length);
> >>          skb->ip_summed = re->skb->ip_summed;
> >>          skb->csum = re->skb->csum;
> >>          pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
> >>-                           length, PCI_DMA_FROMDEVICE);
> >>+                           dma_size, PCI_DMA_FROMDEVICE);
> >>          re->skb->ip_summed = CHECKSUM_NONE;
> >>          skb_put(skb, length);
> >>      }
> >This doesn't apply - I'm missing some intermediate patch.
> >
> >I've got (both in 2.6.32.4 and 2.6.33-rc5: pci_unmap_len(re,
> >data_size) vs., "length." I assume that I can just replace the
> >pci_unmap_len with dma_size... but perhaps the intermediate change
> >may have affected this as well?
> >
> Never mind - that was from one of the earlier patches I had been
> trying out. will try the above patch after reestablishing that the
> system still crashes without copybreak=1.
> 

Stephen, I'm not sure this patch can show much after the patch with
"legal" dma_size == re->data_addr didn't help. It looks like David
was right: dma_sync can't affect dmar, because it doesn't use it at
all.

Then I'd rather suggest to test if using copybreak more often, e.g.
with copybreak=1000 or even more can trigger these errors faster.

Jarek P.

^ permalink raw reply

* Re: Hang: 2.6.32.4 sky2/DMAR (was [PATCH] sky2: Fix WARNING: at lib/dma-debug.c:902 check_sync)
From: Michael Breuer @ 2010-01-27 18:45 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jarek Poplawski, David Miller, akpm, flyboy, linux-kernel, netdev,
	Michael Chan, Don Fry, Francois Romieu, Matt Carlson
In-Reply-To: <4B608128.7090607@majjas.com>

On 1/27/2010 1:08 PM, Michael Breuer wrote:
> On 01/27/2010 12:56 PM, Stephen Hemminger wrote:
>> --- a/drivers/net/sky2.c    2010-01-27 09:46:10.940005248 -0800
>> +++ b/drivers/net/sky2.c    2010-01-27 09:53:47.141267850 -0800
>> @@ -2257,13 +2257,16 @@ static struct sk_buff *receive_copy(stru
>>
>>       skb = netdev_alloc_skb_ip_align(sky2->netdev, length);
>>       if (likely(skb)) {
>> +        unsigned dma_align = dma_get_cache_alignment();
>> +        unsigned dma_size = ALIGN(length+1, dma_align);
>> +
>>           pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->data_addr,
>> -                        length, PCI_DMA_FROMDEVICE);
>> +                        dma_size, PCI_DMA_FROMDEVICE);
>>           skb_copy_from_linear_data(re->skb, skb->data, length);
>>           skb->ip_summed = re->skb->ip_summed;
>>           skb->csum = re->skb->csum;
>>           pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
>> -                           length, PCI_DMA_FROMDEVICE);
>> +                           dma_size, PCI_DMA_FROMDEVICE);
>>           re->skb->ip_summed = CHECKSUM_NONE;
>>           skb_put(skb, length);
>>       }
> This doesn't apply - I'm missing some intermediate patch.
>
> I've got (both in 2.6.32.4 and 2.6.33-rc5: pci_unmap_len(re, 
> data_size) vs., "length." I assume that I can just replace the 
> pci_unmap_len with dma_size... but perhaps the intermediate change may 
> have affected this as well?
>
Never mind - that was from one of the earlier patches I had been trying 
out. will try the above patch after reestablishing that the system still 
crashes without copybreak=1.

^ permalink raw reply

* Re: Hang: 2.6.32.4 sky2/DMAR (was [PATCH] sky2: Fix WARNING: at lib/dma-debug.c:902 check_sync)
From: Michael Breuer @ 2010-01-27 18:33 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jarek Poplawski, David Miller, akpm, flyboy, linux-kernel, netdev,
	Michael Chan, Don Fry, Francois Romieu, Matt Carlson
In-Reply-To: <4B607E70.4060402@majjas.com>

On 01/27/2010 12:57 PM, Michael Breuer wrote:
> On 1/27/2010 12:45 PM, Stephen Hemminger wrote:
>> On Wed, 27 Jan 2010 11:57:35 -0500
>> Michael Breuer<mbreuer@majjas.com>  wrote:
>>
>>
> Ah - ok... will poke around there... if you have any suggestions, 
> diagnostics, whatever, let me know. Also, just an FYI - before 
> rebooting with copybreak back to defaults, I tried mtu=9000 again. 
> That hung the server immediately - no diagnostic output - system froze 
> until watchdog rebooted. Don't know right now if the copybreak had 
> anything to do with this, but when I've tried in the past I've had 
> errors on sky2, but never crashed the system like this. Only two 
> things different were copybreak and the length of time the system had 
> been up. I'll try later with copybreak default and copybreak=1 to see 
> if that affects mtu behavior.
>
FYI - just redid this a few times. Looks like it's how long the system 
was up, not copybreak wrt crash on resetting MTU.

That said, while the system seems OK after resetting the MTU, I do get a 
WARNING from netdev watchdog - same warning regardless of copybreak. 
Setting the mtu back to 1500 generates rx errors after which things 
work. Going back to 9000 again does not generate new errors.

Jan 27 13:21:54 mail kernel: ------------[ cut here ]------------
Jan 27 13:21:54 mail kernel: WARNING: at net/sched/sch_generic.c:261 
dev_watchdog+0xf3/0x164()
Jan 27 13:21:54 mail kernel: Hardware name: System Product Name
Jan 27 13:21:54 mail kernel: NETDEV WATCHDOG: eth0 (sky2): transmit 
queue 0 timed out
Jan 27 13:21:54 mail kernel: Modules linked in: microcode(+) 
ip6table_mangle ip6table_filter ip6_tables ipt_MASQUERADE iptable_nat 
nf_nat iptable_mangle iptable_raw bridge stp appletalk psnap llc nfsd 
lockd nfs_acl auth_rpcgss exportfs hwmon_vid coretemp sunrpc 
acpi_cpufreq sit tunnel4 ipt_LOG nf_conntrack_netbios_ns 
nf_conntrack_ftp nf_conntrack_ipv6 xt_multiport xt_DSCP xt_dscp xt_MARK 
ipv6 dm_multipath kvm_intel kvm snd_hda_codec_analog snd_ens1371 
gameport snd_rawmidi snd_ac97_codec snd_hda_intel snd_hda_codec 
snd_hwdep ac97_bus snd_seq gspca_spca505 gspca_main videodev 
snd_seq_device asus_atk0110 v4l1_compat snd_pcm hwmon 
v4l2_compat_ioctl32 pcspkr i2c_i801 firewire_ohci firewire_core 
crc_itu_t snd_timer snd soundcore wmi snd_page_alloc sky2 iTCO_wdt 
iTCO_vendor_support fbcon tileblit font bitblit softcursor raid456 
async_raid6_recov async_pq raid6_pq async_xor xor async_memcpy async_tx 
raid1 ata_generic pata_acpi pata_marvell nouveau ttm drm_kms_helper drm 
agpgart fb i2c_algo_bit cfbcopyarea i2c_core cfb
Jan 27 13:21:54 mail kernel: imgblt cfbfillrect [last unloaded: ip6_tables]
Jan 27 13:21:54 mail kernel: Pid: 0, comm: swapper Tainted: G        W  
2.6.32.4MMAPDMARAF3SKY2PSKBMAYPULL-00912-g914160d-dirty #6
Jan 27 13:21:54 mail kernel: Call Trace:
Jan 27 13:21:54 mail kernel: <IRQ>  [<ffffffff810536ee>] 
warn_slowpath_common+0x7c/0x94
Jan 27 13:21:54 mail kernel: [<ffffffff8105375d>] 
warn_slowpath_fmt+0x41/0x43
Jan 27 13:21:54 mail kernel: [<ffffffff813e3b6b>] ? netif_tx_lock+0x44/0x6c
Jan 27 13:21:54 mail kernel: [<ffffffff813e3cd3>] dev_watchdog+0xf3/0x164
Jan 27 13:21:54 mail kernel: [<ffffffff8106e990>] ? __queue_work+0x3a/0x42
Jan 27 13:21:54 mail kernel: [<ffffffff8106323f>] 
run_timer_softirq+0x1c8/0x270
Jan 27 13:21:54 mail kernel: [<ffffffff8105af0f>] __do_softirq+0xf8/0x1cd
Jan 27 13:21:54 mail kernel: [<ffffffff8107f0ab>] ? 
tick_program_event+0x2a/0x2c
Jan 27 13:21:54 mail kernel: [<ffffffff81012e1c>] call_softirq+0x1c/0x30
Jan 27 13:21:54 mail kernel: [<ffffffff810143a3>] do_softirq+0x4b/0xa6
Jan 27 13:21:54 mail kernel: [<ffffffff8105aaef>] irq_exit+0x4a/0x8c
Jan 27 13:21:54 mail kernel: [<ffffffff81470612>] 
smp_apic_timer_interrupt+0x86/0x94
Jan 27 13:21:54 mail kernel: [<ffffffff810127e3>] 
apic_timer_interrupt+0x13/0x20
Jan 27 13:21:54 mail kernel: <EOI>  [<ffffffff812c729a>] ? 
acpi_idle_enter_bm+0x256/0x28a
Jan 27 13:21:54 mail kernel: [<ffffffff812c7293>] ? 
acpi_idle_enter_bm+0x24f/0x28a
Jan 27 13:21:54 mail kernel: [<ffffffff813a6c3c>] ? 
cpuidle_idle_call+0x9e/0xfa
Jan 27 13:21:54 mail kernel: [<ffffffff81010c90>] ? cpu_idle+0xb4/0xf6
Jan 27 13:21:54 mail kernel: [<ffffffff81465ba5>] ? 
start_secondary+0x201/0x242
Jan 27 13:21:54 mail kernel: ---[ end trace 57f7151f6a5def07 ]---
Jan 27 13:21:54 mail kernel: sky2 eth0: tx timeout
Jan 27 13:21:54 mail kernel: sky2 eth0: transmit ring 51 .. 10 report=51 
done=51
Jan 27 13:21:54 mail kernel: sky2 eth0: disabling interface
Jan 27 13:21:54 mail kernel: sky2 eth0: enabling interface



^ permalink raw reply

* Re: Hang: 2.6.32.4 sky2/DMAR (was [PATCH] sky2: Fix WARNING: at lib/dma-debug.c:902 check_sync)
From: Michael Breuer @ 2010-01-27 18:08 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jarek Poplawski, David Miller, akpm, flyboy, linux-kernel, netdev,
	Michael Chan, Don Fry, Francois Romieu, Matt Carlson
In-Reply-To: <20100127095614.14313677@nehalam>

On 01/27/2010 12:56 PM, Stephen Hemminger wrote:
> --- a/drivers/net/sky2.c	2010-01-27 09:46:10.940005248 -0800
> +++ b/drivers/net/sky2.c	2010-01-27 09:53:47.141267850 -0800
> @@ -2257,13 +2257,16 @@ static struct sk_buff *receive_copy(stru
>
>   	skb = netdev_alloc_skb_ip_align(sky2->netdev, length);
>   	if (likely(skb)) {
> +		unsigned dma_align = dma_get_cache_alignment();
> +		unsigned dma_size = ALIGN(length+1, dma_align);
> +
>   		pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->data_addr,
> -					    length, PCI_DMA_FROMDEVICE);
> +					    dma_size, PCI_DMA_FROMDEVICE);
>   		skb_copy_from_linear_data(re->skb, skb->data, length);
>   		skb->ip_summed = re->skb->ip_summed;
>   		skb->csum = re->skb->csum;
>   		pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
> -					       length, PCI_DMA_FROMDEVICE);
> +					       dma_size, PCI_DMA_FROMDEVICE);
>   		re->skb->ip_summed = CHECKSUM_NONE;
>   		skb_put(skb, length);
>   	}
>    
This doesn't apply - I'm missing some intermediate patch.

I've got (both in 2.6.32.4 and 2.6.33-rc5: pci_unmap_len(re, data_size) 
vs., "length." I assume that I can just replace the pci_unmap_len with 
dma_size... but perhaps the intermediate change may have affected this 
as well?

^ permalink raw reply

* Re: [PATCH net-next-2.6] packet: Add GSO/checksum offload support to af_packet sockets
From: Michael S. Tsirkin @ 2010-01-27 18:02 UTC (permalink / raw)
  To: Sridhar Samudrala; +Cc: David Miller, Rusty Russell, Herbert Xu, netdev
In-Reply-To: <1264614157.20320.16.camel@w-sridhar.beaverton.ibm.com>

On Wed, Jan 27, 2010 at 09:42:37AM -0800, Sridhar Samudrala wrote:
> On Wed, 2010-01-27 at 13:42 +0200, Michael S. Tsirkin wrote: 
> > On Tue, Jan 26, 2010 at 12:30:19PM -0800, Sridhar Samudrala wrote:
> > > This patch adds GSO/checksum offload to af_packet sockets using
> > > virtio_net_hdr. Based on Rusty's patch to add this support to tun.
> > > It allows GSO/checksum offload to be enabled when using raw socket
> > > backend with virtio_net.
> > > Adds PACKET_VNET_HDR socket option to prepend virtio_net_hdr in the
> > > receive path and process/skip virtio_net_hdr in the send path. This
> > > option is only allowed with SOCK_RAW sockets attached to ethernet
> > > type devices.
> > > 
> > > Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
> > 
> > So the main issue with this implemenation is that it silently fails for
> > non-ethernet protocols.  It would be better to detect unsupported
> > protocols and return an error to user. 
> 
> Yes. I could return EINVAL or EOPNOTSUPP when trying to send/receive a
> packet with virtio_net_hdr on non-ethernet devices.

non-ethernet *protocols* are at issue here.

> > This is same issue that was
> > pointed out by DaveM with my earlier attempt to solve a different
> > (related) problem:
> > http://lkml.org/lkml/2010/1/5/474
> > For an incomplete prototype attempting to solve the issue in a generic way:
> > http://lkml.org/lkml/2010/1/6/56
> > 
> > A couple of additional comments below.
> > 
> > > diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h
> > > index 4021d47..aa57a5f 100644
> > > --- a/include/linux/if_packet.h
> > > +++ b/include/linux/if_packet.h
> > > @@ -46,6 +46,7 @@ struct sockaddr_ll {
> > >  #define PACKET_RESERVE			12
> > >  #define PACKET_TX_RING			13
> > >  #define PACKET_LOSS			14
> > > +#define PACKET_VNET_HDR			15
> > >  
> > >  struct tpacket_stats {
> > >  	unsigned int	tp_packets;
> > > diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> > > index 53633c5..36d5360 100644
> > > --- a/net/packet/af_packet.c
> > > +++ b/net/packet/af_packet.c
> > > @@ -80,6 +80,8 @@
> > >  #include <linux/init.h>
> > >  #include <linux/mutex.h>
> > >  #include <linux/if_vlan.h>
> > > +#include <linux/virtio_net.h>
> > > +#include <linux/if_arp.h>
> > >  
> > >  #ifdef CONFIG_INET
> > >  #include <net/inet_common.h>
> > > @@ -193,7 +195,8 @@ struct packet_sock {
> > >  	struct mutex		pg_vec_lock;
> > >  	unsigned int		running:1,	/* prot_hook is attached*/
> > >  				auxdata:1,
> > > -				origdev:1;
> > > +				origdev:1,
> > > +				vnet_hdr:1;
> > >  	int			ifindex;	/* bound device		*/
> > >  	__be16			num;
> > >  	struct packet_mclist	*mclist;
> > > @@ -1056,6 +1059,30 @@ out:
> > >  }
> > >  #endif
> > >  
> > > +static inline struct sk_buff *packet_alloc_skb(struct sock *sk, size_t prepad,
> > > +					       size_t reserve, size_t len,
> > > +					       size_t linear, int noblock,
> > > +					       int *err)
> > > +{
> > > +	struct sk_buff *skb;
> > > +
> > > +	/* Under a page?  Don't bother with paged skb. */
> > > +	if (prepad + len < PAGE_SIZE || !linear)
> > > +		linear = len;
> > > +
> > > +	skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock,
> > > +				   err);
> > > +	if (!skb)
> > > +		return NULL;
> > > +
> > > +	skb_reserve(skb, reserve);
> > > +	skb_put(skb, linear);
> > > +	skb->data_len = len - linear;
> > > +	skb->len += len - linear;
> > > +
> > > +	return skb;
> > > +}
> > > +
> > >  static int packet_snd(struct socket *sock,
> > >  			  struct msghdr *msg, size_t len)
> > >  {
> > > @@ -1066,14 +1093,15 @@ static int packet_snd(struct socket *sock,
> > >  	__be16 proto;
> > >  	unsigned char *addr;
> > >  	int ifindex, err, reserve = 0;
> > > +	struct virtio_net_hdr vnethdr = { 0 };
> > > +	int offset = 0;
> > > +	struct packet_sock *po = pkt_sk(sk);
> > >  
> > >  	/*
> > >  	 *	Get and verify the address.
> > >  	 */
> > >  
> > >  	if (saddr == NULL) {
> > > -		struct packet_sock *po = pkt_sk(sk);
> > > -
> > >  		ifindex	= po->ifindex;
> > >  		proto	= po->num;
> > >  		addr	= NULL;
> > > @@ -1100,25 +1128,52 @@ static int packet_snd(struct socket *sock,
> > >  	if (!(dev->flags & IFF_UP))
> > >  		goto out_unlock;
> > >  
> > > -	err = -EMSGSIZE;
> > > -	if (len > dev->mtu+reserve)
> > > -		goto out_unlock;
> > > +	if (po->vnet_hdr) {
> > > +		err = -EINVAL;
> > > +		if (dev->type != ARPHRD_ETHER)
> > > +			goto out_unlock;
> > > +
> > > +		if (len < sizeof(vnethdr))
> > > +			goto out_unlock;
> > >  
> > > -	skb = sock_alloc_send_skb(sk, len + LL_ALLOCATED_SPACE(dev),
> > > -				msg->msg_flags & MSG_DONTWAIT, &err);
> > > +		len -= sizeof(vnethdr);
> > > +
> > > +		err = -EFAULT;
> > > +		if (memcpy_fromiovec((void *)&vnethdr, msg->msg_iov,
> > > +					sizeof(vnethdr))) 
> > > +			goto out_unlock;
> > > +	
> > > +		if ((vnethdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
> > > +		    (vnethdr.csum_start + vnethdr.csum_offset + 2 >
> > > +		      vnethdr.hdr_len))
> > > +			vnethdr.hdr_len = vnethdr.csum_start +
> > > +						 vnethdr.csum_offset + 2;
> > > +
> > > +		err = -EINVAL;
> > > +		if (vnethdr.hdr_len > len)
> > > +			goto out_unlock;
> > > +	} else {
> > > +		err = -EMSGSIZE;
> > > +		if (len > dev->mtu+reserve)
> > > +			goto out_unlock;
> > 
> > IMO we should always perform the length check if GSO is off.
> OK. I will fix this. 
> > 
> > > +	}
> > > +
> > > +	err = -ENOBUFS;
> > > +	skb = packet_alloc_skb(sk, LL_ALLOCATED_SPACE(dev),
> > > +			       LL_RESERVED_SPACE(dev), len, vnethdr.hdr_len,
> > > +			       msg->msg_flags & MSG_DONTWAIT, &err);
> > >  	if (skb == NULL)
> > >  		goto out_unlock;
> > >  
> > > -	skb_reserve(skb, LL_RESERVED_SPACE(dev));
> > > -	skb_reset_network_header(skb);
> > > +	skb_set_network_header(skb, reserve);
> > 
> > I think the above is wrong for vlans?
> 
> I also thought we need to address vlans here, but even tun doesn't
> handle this in the send routine. I submitted a patch that fixed
> skb_gso_segment() to handle vlan packets. This will address both
> tun and packet sockets.
> http://thread.gmane.org/gmane.linux.network/150198
> 
> With this patch, i tested vlans with both ipv4 and ipv6.

Well, there are more protocols than just vlans :)
BTW, if there are dependencies between patches, you probably
want to put them in a patchset so they can be judged together.


> > 
> > >  
> > >  	err = -EINVAL;
> > >  	if (sock->type == SOCK_DGRAM &&
> > > -	    dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len) < 0)
> > > +	    (offset = dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len)) < 0)
> > >  		goto out_free;
> > >  
> > >  	/* Returns -EFAULT on error */
> > > -	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
> > > +	err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len);
> > >  	if (err)
> > >  		goto out_free;
> > >  
> > > @@ -1127,6 +1182,51 @@ static int packet_snd(struct socket *sock,
> > >  	skb->priority = sk->sk_priority;
> > >  	skb->mark = sk->sk_mark;
> > >  
> > > +	if (po->vnet_hdr) {
> > > +		skb_reset_mac_header(skb);
> > > +		skb->protocol = eth_hdr(skb)->h_proto;
> > > +
> > 
> > Is this also broken for vlans?
> 
> Same as above. 
> > 
> > > +		if (vnethdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
> > > +			if (!skb_partial_csum_set(skb, vnethdr.csum_start,
> > > +						  vnethdr.csum_offset)) {
> > > +				err = -EINVAL;
> > > +				goto out_free;
> > > +			}
> > > +		}
> > > +
> > > +		if (vnethdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
> > > +			switch (vnethdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
> > > +			case VIRTIO_NET_HDR_GSO_TCPV4:
> > > +				skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
> > > +				break;
> > > +			case VIRTIO_NET_HDR_GSO_TCPV6:
> > > +				skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
> > > +				break;
> > > +			case VIRTIO_NET_HDR_GSO_UDP:
> > > +				skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
> > > +				break;
> > > +			default:
> > > +				err = -EINVAL;
> > > +				goto out_free;
> > > +			}
> > > +
> > > +			if (vnethdr.gso_type & VIRTIO_NET_HDR_GSO_ECN)
> > > +				skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
> > > +
> > > +			skb_shinfo(skb)->gso_size = vnethdr.gso_size;
> > > +			if (skb_shinfo(skb)->gso_size == 0) {
> > > +				err = -EINVAL;
> > > +				goto out_free;
> > > +                	}
> > > +
> > > +			/* Header must be checked, and gso_segs computed. */
> > > +			skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
> > > +			skb_shinfo(skb)->gso_segs = 0;
> > > +		}
> > > +
> > > +		len += sizeof(vnethdr);
> > > +	}
> > > +
> > >  	/*
> > >  	 *	Now send it
> > >  	 */
> > > @@ -1420,6 +1520,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
> > >  	struct sk_buff *skb;
> > >  	int copied, err;
> > >  	struct sockaddr_ll *sll;
> > > +	int vnet_hdr_len = 0;
> > >  
> > >  	err = -EINVAL;
> > >  	if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT))
> > > @@ -1451,6 +1552,44 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
> > >  	if (skb == NULL)
> > >  		goto out;
> > >  
> > > +	if (pkt_sk(sk)->vnet_hdr) {
> > > +		struct virtio_net_hdr vnethdr = { 0 };
> > > +
> > > +		vnet_hdr_len = sizeof(vnethdr);
> > > +		if ((len -= vnet_hdr_len) < 0)
> > > +			return -EINVAL;
> > > +
> > > +		if (skb_is_gso(skb)) {
> > > +			struct skb_shared_info *sinfo = skb_shinfo(skb);
> > > +
> > > +			/* This is a hint as to how much should be linear. */
> > > +			vnethdr.hdr_len = skb_headlen(skb);
> > > +			vnethdr.gso_size = sinfo->gso_size;
> > > +			if (sinfo->gso_type & SKB_GSO_TCPV4)
> > > +				vnethdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
> > > +			else if (sinfo->gso_type & SKB_GSO_TCPV6)
> > > +				vnethdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
> > > +			else if (sinfo->gso_type & SKB_GSO_UDP)
> > > +				vnethdr.gso_type = VIRTIO_NET_HDR_GSO_UDP;
> > > +			else
> > > +				BUG();
> > 
> > Is there any chance this can get SKB_GSO_FCOE by binding to
> > an appropriate interface?  Maybe we don't want to BUG().
> I could return -EINVAL in that case.
> 
> > 
> > > +			if (sinfo->gso_type & SKB_GSO_TCP_ECN)
> > > +				vnethdr.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
> > > +		} else
> > > +			vnethdr.gso_type = VIRTIO_NET_HDR_GSO_NONE;
> > > +
> > > +		if (skb->ip_summed == CHECKSUM_PARTIAL) {
> > > +			vnethdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
> > > +			vnethdr.csum_start = skb->csum_start - skb_headroom(skb);
> > > +			vnethdr.csum_offset = skb->csum_offset;
> > > +		} /* else everything is zero */
> > > +
> > > +		if (unlikely(memcpy_toiovec(msg->msg_iov, (void *)&vnethdr,
> > > +					    sizeof(vnethdr)))) {
> > > +			return -EFAULT;
> > > +		}
> > > +	}
> > > +
> > >  	/*
> > >  	 *	If the address length field is there to be filled in, we fill
> > >  	 *	it in now.
> > > @@ -1502,7 +1641,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
> > >  	 *	Free or return the buffer as appropriate. Again this
> > >  	 *	hides all the races and re-entrancy issues from us.
> > >  	 */
> > > -	err = (flags&MSG_TRUNC) ? skb->len : copied;
> > > +	err = vnet_hdr_len + ((flags&MSG_TRUNC) ? skb->len : copied);
> > >  
> > >  out_free:
> > >  	skb_free_datagram(sk, skb);
> > > @@ -1826,6 +1965,22 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
> > >  		po->origdev = !!val;
> > >  		return 0;
> > >  	}
> > > +	case PACKET_VNET_HDR:
> > > +	{
> > > +		int val;
> > > +
> > > +		if (sock->type != SOCK_RAW)
> > > +			return -EINVAL;
> > > +		if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)	
> > > +			return -EBUSY;
> > 
> > Another way to get a broken ring + vnet hdr configuration
> > would be to enable vnet hdr first and mmap second.
> > I think we need to guard against this as well, by checking vnet_hdr
> > when tx/rx ring is enabled.
> 
> OK. i will add a check when setting PACKET_RX_RING/TX_RING socket
> options. 
> > > +		if (optlen < sizeof(val))
> > > +			return -EINVAL;
> > > +		if (copy_from_user(&val, optval, sizeof(val)))
> > > +			return -EFAULT;
> > > +
> > > +		po->vnet_hdr = !!val;
> > > +		return 0;
> > > +	}
> > >  	default:
> > >  		return -ENOPROTOOPT;
> > >  	}
> > > @@ -1876,6 +2031,13 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
> > >  
> > >  		data = &val;
> > >  		break;
> > > +	case PACKET_VNET_HDR:
> > > +		if (len > sizeof(int))
> > > +			len = sizeof(int);
> > > +		val = po->vnet_hdr;
> > > +
> > > +		data = &val;
> > > +		break;
> > >  #ifdef CONFIG_PACKET_MMAP
> > >  	case PACKET_VERSION:
> > >  		if (len > sizeof(int))
> > > 
> > 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: Hang: 2.6.32.4 sky2/DMAR (was [PATCH] sky2: Fix WARNING: at lib/dma-debug.c:902 check_sync)
From: Michael Breuer @ 2010-01-27 17:58 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jarek Poplawski, David Miller, akpm, flyboy, linux-kernel, netdev,
	Michael Chan, Don Fry, Francois Romieu, Matt Carlson
In-Reply-To: <20100127095614.14313677@nehalam>

On 1/27/2010 12:56 PM, Stephen Hemminger wrote:
> On Wed, 27 Jan 2010 11:57:35 -0500
> Michael Breuer<mbreuer@majjas.com>  wrote:
>
>    
>> On 1/27/2010 11:50 AM, Stephen Hemminger wrote:
>>      
>>> On Wed, 27 Jan 2010 10:34:51 -0500
>>> Michael Breuer<mbreuer@majjas.com>   wrote:
>>>
>>>
>>>        
>>>> On 01/23/2010 06:21 PM, Jarek Poplawski wrote:
>>>>
>>>>          
>>>>> On Fri, Jan 22, 2010 at 06:50:21PM -0500, Michael Breuer wrote:
>>>>>
>>>>>
>>>>>            
>>>>>> When the packets were dropped, there was a different sequence in the
>>>>>> log - DISCOVER/OFFER repeated. The "normal" is that the sequence
>>>>>> appeared correct and complete - DISCOVER/OFFER/REQUEST/ACK - or
>>>>>> INFORM/ACK (vs. INFORM repeatedly sans ACK) as the case may be.
>>>>>>
>>>>>>
>>>>>>              
>>>>> Anyway, I'd be intersted if the switch matters here.
>>>>>
>>>>> Plus one more test: could you try to load sky2 with the parameter:
>>>>> "copybreak=1" (the rest as in any recent test, which gave you dmar
>>>>> errors; any switch).
>>>>>
>>>>> Thanks,
>>>>> Jarek P.
>>>>>
>>>>>
>>>>>            
>>>> Ok - now up 80+ hours with copybreak=1. I'm going to redo w/o copybreak
>>>> to confirm that I haven't inadvertently fixed something. However, given
>>>> that it might be copybreak-related, I looked at sky2.c again and I'm
>>>> wondering about the copybreak max size in sky2_rx_start:
>>>>
>>>>      size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
>>>>
>>>>            /* Stopping point for hardware truncation */
>>>>            thresh = (size - 8) / sizeof(u32);
>>>>
>>>>            sky2->rx_nfrags = size>>   PAGE_SHIFT;
>>>>            BUG_ON(sky2->rx_nfrags>   ARRAY_SIZE(re->frag_addr));
>>>>
>>>>            /* Compute residue after pages */
>>>>            size -= sky2->rx_nfrags<<   PAGE_SHIFT;
>>>>
>>>>            /* Optimize to handle small packets and headers */
>>>>            if (size<   copybreak)
>>>>                    size = copybreak;
>>>>            if (size<   ETH_HLEN)
>>>>                    size = ETH_HLEN;
>>>>
>>>>
>>>> Why would increasing size to copybreak be valid here?
>>>>
>>>> Guessing a bit as I'm not sure about rx_nfrags, but if I read this
>>>> correctly, if size is ever less than copybreak it's because there isn't
>>>> enough space left for anything larger. If so, wouldn't increasing size
>>>> potentially corrupt something? I'd further guess that the resulting
>>>> condition manifests sooner (or at least with a more visible effect) when
>>>> using DMAR.
>>>>
>>>> In any event, why "copybreak" as the minimum buffer size? I'd suggest
>>>> that if it isn't possible to allocate at least MTU + overhead that
>>>> sky2_rx_start ought to be delayed until there is room.
>>>>
>>>>          
>>> This code is where driver decides how much data will be received in skb
>>> data area and the remaining data spills over into skb frags.
>>> Copybreak is the threshold so that packets less than size are copied
>>> to a new skb.  The code doing the copying there assumes the data is
>>> totally contained in the skb (not in frags). The size increase there
>>> is to make sure that assumption is always true.  I suppose you
>>> could do something perverse like setting copybreak really huge
>>> and confuse driver, but that is a user error.
>>>
>>>
>>>        
>> Ok - but I'm wondering under what circumstances size would be<
>> copybreak in the first place after computing the residue. If size ends
>> up being unreasonably small, is simply increasing the number to whatever
>> copybreak is correct? Assuming my testing is correct, then the crash
>> I've been experiencing when using dmar (only) seems related to the value
>> of copybreak. I don't think the other use (skb reuse) is the issue (but
>> hey, I could have missed something). The crash occurs when copybreak is
>> the default of 128, didn't happen when I set copybreak to 1.
>>      
> Does this change it? If so the dma code is (not sky2) is buggy and not
> rounding up properly.
>
> --- a/drivers/net/sky2.c	2010-01-27 09:46:10.940005248 -0800
> +++ b/drivers/net/sky2.c	2010-01-27 09:53:47.141267850 -0800
> @@ -2257,13 +2257,16 @@ static struct sk_buff *receive_copy(stru
>
>   	skb = netdev_alloc_skb_ip_align(sky2->netdev, length);
>   	if (likely(skb)) {
> +		unsigned dma_align = dma_get_cache_alignment();
> +		unsigned dma_size = ALIGN(length+1, dma_align);
> +
>   		pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->data_addr,
> -					    length, PCI_DMA_FROMDEVICE);
> +					    dma_size, PCI_DMA_FROMDEVICE);
>   		skb_copy_from_linear_data(re->skb, skb->data, length);
>   		skb->ip_summed = re->skb->ip_summed;
>   		skb->csum = re->skb->csum;
>   		pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
> -					       length, PCI_DMA_FROMDEVICE);
> +					       dma_size, PCI_DMA_FROMDEVICE);
>   		re->skb->ip_summed = CHECKSUM_NONE;
>   		skb_put(skb, length);
>   	}
>    
Ok - will queue this - want to reconfirm that the system still crashes 
w/o this (or copybreak). That should take a few days.

^ permalink raw reply

* Re: Hang: 2.6.32.4 sky2/DMAR (was [PATCH] sky2: Fix WARNING: at lib/dma-debug.c:902 check_sync)
From: Michael Breuer @ 2010-01-27 17:57 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jarek Poplawski, David Miller, akpm, flyboy, linux-kernel, netdev,
	Michael Chan, Don Fry, Francois Romieu, Matt Carlson
In-Reply-To: <20100127094531.53c85aa7@nehalam>

On 1/27/2010 12:45 PM, Stephen Hemminger wrote:
> On Wed, 27 Jan 2010 11:57:35 -0500
> Michael Breuer<mbreuer@majjas.com>  wrote:
>
>    
>> On 1/27/2010 11:50 AM, Stephen Hemminger wrote:
>>      
>>> On Wed, 27 Jan 2010 10:34:51 -0500
>>> Michael Breuer<mbreuer@majjas.com>   wrote:
>>>
>>>
>>>        
>>>> On 01/23/2010 06:21 PM, Jarek Poplawski wrote:
>>>>
>>>>          
>>>>> On Fri, Jan 22, 2010 at 06:50:21PM -0500, Michael Breuer wrote:
>>>>>
>>>>>
>>>>>            
>>>>>> When the packets were dropped, there was a different sequence in the
>>>>>> log - DISCOVER/OFFER repeated. The "normal" is that the sequence
>>>>>> appeared correct and complete - DISCOVER/OFFER/REQUEST/ACK - or
>>>>>> INFORM/ACK (vs. INFORM repeatedly sans ACK) as the case may be.
>>>>>>
>>>>>>
>>>>>>              
>>>>> Anyway, I'd be intersted if the switch matters here.
>>>>>
>>>>> Plus one more test: could you try to load sky2 with the parameter:
>>>>> "copybreak=1" (the rest as in any recent test, which gave you dmar
>>>>> errors; any switch).
>>>>>
>>>>> Thanks,
>>>>> Jarek P.
>>>>>
>>>>>
>>>>>            
>>>> Ok - now up 80+ hours with copybreak=1. I'm going to redo w/o copybreak
>>>> to confirm that I haven't inadvertently fixed something. However, given
>>>> that it might be copybreak-related, I looked at sky2.c again and I'm
>>>> wondering about the copybreak max size in sky2_rx_start:
>>>>
>>>>      size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
>>>>
>>>>            /* Stopping point for hardware truncation */
>>>>            thresh = (size - 8) / sizeof(u32);
>>>>
>>>>            sky2->rx_nfrags = size>>   PAGE_SHIFT;
>>>>            BUG_ON(sky2->rx_nfrags>   ARRAY_SIZE(re->frag_addr));
>>>>
>>>>            /* Compute residue after pages */
>>>>            size -= sky2->rx_nfrags<<   PAGE_SHIFT;
>>>>
>>>>            /* Optimize to handle small packets and headers */
>>>>            if (size<   copybreak)
>>>>                    size = copybreak;
>>>>            if (size<   ETH_HLEN)
>>>>                    size = ETH_HLEN;
>>>>
>>>>
>>>> Why would increasing size to copybreak be valid here?
>>>>
>>>> Guessing a bit as I'm not sure about rx_nfrags, but if I read this
>>>> correctly, if size is ever less than copybreak it's because there isn't
>>>> enough space left for anything larger. If so, wouldn't increasing size
>>>> potentially corrupt something? I'd further guess that the resulting
>>>> condition manifests sooner (or at least with a more visible effect) when
>>>> using DMAR.
>>>>
>>>> In any event, why "copybreak" as the minimum buffer size? I'd suggest
>>>> that if it isn't possible to allocate at least MTU + overhead that
>>>> sky2_rx_start ought to be delayed until there is room.
>>>>
>>>>          
>>> This code is where driver decides how much data will be received in skb
>>> data area and the remaining data spills over into skb frags.
>>> Copybreak is the threshold so that packets less than size are copied
>>> to a new skb.  The code doing the copying there assumes the data is
>>> totally contained in the skb (not in frags). The size increase there
>>> is to make sure that assumption is always true.  I suppose you
>>> could do something perverse like setting copybreak really huge
>>> and confuse driver, but that is a user error.
>>>
>>>
>>>        
>> Ok - but I'm wondering under what circumstances size would be<
>> copybreak in the first place after computing the residue. If size ends
>> up being unreasonably small, is simply increasing the number to whatever
>> copybreak is correct? Assuming my testing is correct, then the crash
>> I've been experiencing when using dmar (only) seems related to the value
>> of copybreak. I don't think the other use (skb reuse) is the issue (but
>> hey, I could have missed something). The crash occurs when copybreak is
>> the default of 128, didn't happen when I set copybreak to 1.
>>
>>      
> Setting it to 1 causes driver to never go through the dma_sync_single/memcpy
> path.  Perhaps the code for DMAR doesn't do dma_sync_single_for_cpu
> properly, or the value passed to sync_single_for_cpu doesn't account for
> all the overhead of padding and/or ether header.
>
>    
Ah - ok... will poke around there... if you have any suggestions, 
diagnostics, whatever, let me know. Also, just an FYI - before rebooting 
with copybreak back to defaults, I tried mtu=9000 again. That hung the 
server immediately - no diagnostic output - system froze until watchdog 
rebooted. Don't know right now if the copybreak had anything to do with 
this, but when I've tried in the past I've had errors on sky2, but never 
crashed the system like this. Only two things different were copybreak 
and the length of time the system had been up. I'll try later with 
copybreak default and copybreak=1 to see if that affects mtu behavior.

^ permalink raw reply

* Re: Hang: 2.6.32.4 sky2/DMAR (was [PATCH] sky2: Fix WARNING: at lib/dma-debug.c:902 check_sync)
From: Stephen Hemminger @ 2010-01-27 17:56 UTC (permalink / raw)
  To: Michael Breuer
  Cc: Jarek Poplawski, David Miller, akpm, flyboy, linux-kernel, netdev,
	Michael Chan, Don Fry, Francois Romieu, Matt Carlson
In-Reply-To: <4B60707F.1000608@majjas.com>

On Wed, 27 Jan 2010 11:57:35 -0500
Michael Breuer <mbreuer@majjas.com> wrote:

> On 1/27/2010 11:50 AM, Stephen Hemminger wrote:
> > On Wed, 27 Jan 2010 10:34:51 -0500
> > Michael Breuer<mbreuer@majjas.com>  wrote:
> >
> >    
> >> On 01/23/2010 06:21 PM, Jarek Poplawski wrote:
> >>      
> >>> On Fri, Jan 22, 2010 at 06:50:21PM -0500, Michael Breuer wrote:
> >>>
> >>>        
> >>>> When the packets were dropped, there was a different sequence in the
> >>>> log - DISCOVER/OFFER repeated. The "normal" is that the sequence
> >>>> appeared correct and complete - DISCOVER/OFFER/REQUEST/ACK - or
> >>>> INFORM/ACK (vs. INFORM repeatedly sans ACK) as the case may be.
> >>>>
> >>>>          
> >>> Anyway, I'd be intersted if the switch matters here.
> >>>
> >>> Plus one more test: could you try to load sky2 with the parameter:
> >>> "copybreak=1" (the rest as in any recent test, which gave you dmar
> >>> errors; any switch).
> >>>
> >>> Thanks,
> >>> Jarek P.
> >>>
> >>>        
> >> Ok - now up 80+ hours with copybreak=1. I'm going to redo w/o copybreak
> >> to confirm that I haven't inadvertently fixed something. However, given
> >> that it might be copybreak-related, I looked at sky2.c again and I'm
> >> wondering about the copybreak max size in sky2_rx_start:
> >>
> >>     size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
> >>
> >>           /* Stopping point for hardware truncation */
> >>           thresh = (size - 8) / sizeof(u32);
> >>
> >>           sky2->rx_nfrags = size>>  PAGE_SHIFT;
> >>           BUG_ON(sky2->rx_nfrags>  ARRAY_SIZE(re->frag_addr));
> >>
> >>           /* Compute residue after pages */
> >>           size -= sky2->rx_nfrags<<  PAGE_SHIFT;
> >>
> >>           /* Optimize to handle small packets and headers */
> >>           if (size<  copybreak)
> >>                   size = copybreak;
> >>           if (size<  ETH_HLEN)
> >>                   size = ETH_HLEN;
> >>
> >>
> >> Why would increasing size to copybreak be valid here?
> >>
> >> Guessing a bit as I'm not sure about rx_nfrags, but if I read this
> >> correctly, if size is ever less than copybreak it's because there isn't
> >> enough space left for anything larger. If so, wouldn't increasing size
> >> potentially corrupt something? I'd further guess that the resulting
> >> condition manifests sooner (or at least with a more visible effect) when
> >> using DMAR.
> >>
> >> In any event, why "copybreak" as the minimum buffer size? I'd suggest
> >> that if it isn't possible to allocate at least MTU + overhead that
> >> sky2_rx_start ought to be delayed until there is room.
> >>      
> > This code is where driver decides how much data will be received in skb
> > data area and the remaining data spills over into skb frags.
> > Copybreak is the threshold so that packets less than size are copied
> > to a new skb.  The code doing the copying there assumes the data is
> > totally contained in the skb (not in frags). The size increase there
> > is to make sure that assumption is always true.  I suppose you
> > could do something perverse like setting copybreak really huge
> > and confuse driver, but that is a user error.
> >
> >    
> Ok - but I'm wondering under what circumstances size would be < 
> copybreak in the first place after computing the residue. If size ends 
> up being unreasonably small, is simply increasing the number to whatever 
> copybreak is correct? Assuming my testing is correct, then the crash 
> I've been experiencing when using dmar (only) seems related to the value 
> of copybreak. I don't think the other use (skb reuse) is the issue (but 
> hey, I could have missed something). The crash occurs when copybreak is 
> the default of 128, didn't happen when I set copybreak to 1.

Does this change it? If so the dma code is (not sky2) is buggy and not
rounding up properly.

--- a/drivers/net/sky2.c	2010-01-27 09:46:10.940005248 -0800
+++ b/drivers/net/sky2.c	2010-01-27 09:53:47.141267850 -0800
@@ -2257,13 +2257,16 @@ static struct sk_buff *receive_copy(stru
 
 	skb = netdev_alloc_skb_ip_align(sky2->netdev, length);
 	if (likely(skb)) {
+		unsigned dma_align = dma_get_cache_alignment();
+		unsigned dma_size = ALIGN(length+1, dma_align);
+
 		pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->data_addr,
-					    length, PCI_DMA_FROMDEVICE);
+					    dma_size, PCI_DMA_FROMDEVICE);
 		skb_copy_from_linear_data(re->skb, skb->data, length);
 		skb->ip_summed = re->skb->ip_summed;
 		skb->csum = re->skb->csum;
 		pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
-					       length, PCI_DMA_FROMDEVICE);
+					       dma_size, PCI_DMA_FROMDEVICE);
 		re->skb->ip_summed = CHECKSUM_NONE;
 		skb_put(skb, length);
 	}

^ permalink raw reply

* Re: Hang: 2.6.32.4 sky2/DMAR (was [PATCH] sky2: Fix WARNING: at lib/dma-debug.c:902 check_sync)
From: Stephen Hemminger @ 2010-01-27 17:45 UTC (permalink / raw)
  To: Michael Breuer
  Cc: Jarek Poplawski, David Miller, akpm, flyboy, linux-kernel, netdev,
	Michael Chan, Don Fry, Francois Romieu, Matt Carlson
In-Reply-To: <4B60707F.1000608@majjas.com>

On Wed, 27 Jan 2010 11:57:35 -0500
Michael Breuer <mbreuer@majjas.com> wrote:

> On 1/27/2010 11:50 AM, Stephen Hemminger wrote:
> > On Wed, 27 Jan 2010 10:34:51 -0500
> > Michael Breuer<mbreuer@majjas.com>  wrote:
> >
> >    
> >> On 01/23/2010 06:21 PM, Jarek Poplawski wrote:
> >>      
> >>> On Fri, Jan 22, 2010 at 06:50:21PM -0500, Michael Breuer wrote:
> >>>
> >>>        
> >>>> When the packets were dropped, there was a different sequence in the
> >>>> log - DISCOVER/OFFER repeated. The "normal" is that the sequence
> >>>> appeared correct and complete - DISCOVER/OFFER/REQUEST/ACK - or
> >>>> INFORM/ACK (vs. INFORM repeatedly sans ACK) as the case may be.
> >>>>
> >>>>          
> >>> Anyway, I'd be intersted if the switch matters here.
> >>>
> >>> Plus one more test: could you try to load sky2 with the parameter:
> >>> "copybreak=1" (the rest as in any recent test, which gave you dmar
> >>> errors; any switch).
> >>>
> >>> Thanks,
> >>> Jarek P.
> >>>
> >>>        
> >> Ok - now up 80+ hours with copybreak=1. I'm going to redo w/o copybreak
> >> to confirm that I haven't inadvertently fixed something. However, given
> >> that it might be copybreak-related, I looked at sky2.c again and I'm
> >> wondering about the copybreak max size in sky2_rx_start:
> >>
> >>     size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
> >>
> >>           /* Stopping point for hardware truncation */
> >>           thresh = (size - 8) / sizeof(u32);
> >>
> >>           sky2->rx_nfrags = size>>  PAGE_SHIFT;
> >>           BUG_ON(sky2->rx_nfrags>  ARRAY_SIZE(re->frag_addr));
> >>
> >>           /* Compute residue after pages */
> >>           size -= sky2->rx_nfrags<<  PAGE_SHIFT;
> >>
> >>           /* Optimize to handle small packets and headers */
> >>           if (size<  copybreak)
> >>                   size = copybreak;
> >>           if (size<  ETH_HLEN)
> >>                   size = ETH_HLEN;
> >>
> >>
> >> Why would increasing size to copybreak be valid here?
> >>
> >> Guessing a bit as I'm not sure about rx_nfrags, but if I read this
> >> correctly, if size is ever less than copybreak it's because there isn't
> >> enough space left for anything larger. If so, wouldn't increasing size
> >> potentially corrupt something? I'd further guess that the resulting
> >> condition manifests sooner (or at least with a more visible effect) when
> >> using DMAR.
> >>
> >> In any event, why "copybreak" as the minimum buffer size? I'd suggest
> >> that if it isn't possible to allocate at least MTU + overhead that
> >> sky2_rx_start ought to be delayed until there is room.
> >>      
> > This code is where driver decides how much data will be received in skb
> > data area and the remaining data spills over into skb frags.
> > Copybreak is the threshold so that packets less than size are copied
> > to a new skb.  The code doing the copying there assumes the data is
> > totally contained in the skb (not in frags). The size increase there
> > is to make sure that assumption is always true.  I suppose you
> > could do something perverse like setting copybreak really huge
> > and confuse driver, but that is a user error.
> >
> >    
> Ok - but I'm wondering under what circumstances size would be < 
> copybreak in the first place after computing the residue. If size ends 
> up being unreasonably small, is simply increasing the number to whatever 
> copybreak is correct? Assuming my testing is correct, then the crash 
> I've been experiencing when using dmar (only) seems related to the value 
> of copybreak. I don't think the other use (skb reuse) is the issue (but 
> hey, I could have missed something). The crash occurs when copybreak is 
> the default of 128, didn't happen when I set copybreak to 1.
> 

Setting it to 1 causes driver to never go through the dma_sync_single/memcpy
path.  Perhaps the code for DMAR doesn't do dma_sync_single_for_cpu
properly, or the value passed to sync_single_for_cpu doesn't account for
all the overhead of padding and/or ether header.

-- 

^ permalink raw reply

* Re: [PATCH net-next-2.6] packet: Add GSO/checksum offload support to af_packet sockets
From: Sridhar Samudrala @ 2010-01-27 17:42 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: David Miller, Rusty Russell, Herbert Xu, netdev
In-Reply-To: <20100127114202.GA6696@redhat.com>

On Wed, 2010-01-27 at 13:42 +0200, Michael S. Tsirkin wrote: 
> On Tue, Jan 26, 2010 at 12:30:19PM -0800, Sridhar Samudrala wrote:
> > This patch adds GSO/checksum offload to af_packet sockets using
> > virtio_net_hdr. Based on Rusty's patch to add this support to tun.
> > It allows GSO/checksum offload to be enabled when using raw socket
> > backend with virtio_net.
> > Adds PACKET_VNET_HDR socket option to prepend virtio_net_hdr in the
> > receive path and process/skip virtio_net_hdr in the send path. This
> > option is only allowed with SOCK_RAW sockets attached to ethernet
> > type devices.
> > 
> > Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
> 
> So the main issue with this implemenation is that it silently fails for
> non-ethernet protocols.  It would be better to detect unsupported
> protocols and return an error to user. 

Yes. I could return EINVAL or EOPNOTSUPP when trying to send/receive a
packet with virtio_net_hdr on non-ethernet devices.

> This is same issue that was
> pointed out by DaveM with my earlier attempt to solve a different
> (related) problem:
> http://lkml.org/lkml/2010/1/5/474
> For an incomplete prototype attempting to solve the issue in a generic way:
> http://lkml.org/lkml/2010/1/6/56
> 
> A couple of additional comments below.
> 
> > diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h
> > index 4021d47..aa57a5f 100644
> > --- a/include/linux/if_packet.h
> > +++ b/include/linux/if_packet.h
> > @@ -46,6 +46,7 @@ struct sockaddr_ll {
> >  #define PACKET_RESERVE			12
> >  #define PACKET_TX_RING			13
> >  #define PACKET_LOSS			14
> > +#define PACKET_VNET_HDR			15
> >  
> >  struct tpacket_stats {
> >  	unsigned int	tp_packets;
> > diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> > index 53633c5..36d5360 100644
> > --- a/net/packet/af_packet.c
> > +++ b/net/packet/af_packet.c
> > @@ -80,6 +80,8 @@
> >  #include <linux/init.h>
> >  #include <linux/mutex.h>
> >  #include <linux/if_vlan.h>
> > +#include <linux/virtio_net.h>
> > +#include <linux/if_arp.h>
> >  
> >  #ifdef CONFIG_INET
> >  #include <net/inet_common.h>
> > @@ -193,7 +195,8 @@ struct packet_sock {
> >  	struct mutex		pg_vec_lock;
> >  	unsigned int		running:1,	/* prot_hook is attached*/
> >  				auxdata:1,
> > -				origdev:1;
> > +				origdev:1,
> > +				vnet_hdr:1;
> >  	int			ifindex;	/* bound device		*/
> >  	__be16			num;
> >  	struct packet_mclist	*mclist;
> > @@ -1056,6 +1059,30 @@ out:
> >  }
> >  #endif
> >  
> > +static inline struct sk_buff *packet_alloc_skb(struct sock *sk, size_t prepad,
> > +					       size_t reserve, size_t len,
> > +					       size_t linear, int noblock,
> > +					       int *err)
> > +{
> > +	struct sk_buff *skb;
> > +
> > +	/* Under a page?  Don't bother with paged skb. */
> > +	if (prepad + len < PAGE_SIZE || !linear)
> > +		linear = len;
> > +
> > +	skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock,
> > +				   err);
> > +	if (!skb)
> > +		return NULL;
> > +
> > +	skb_reserve(skb, reserve);
> > +	skb_put(skb, linear);
> > +	skb->data_len = len - linear;
> > +	skb->len += len - linear;
> > +
> > +	return skb;
> > +}
> > +
> >  static int packet_snd(struct socket *sock,
> >  			  struct msghdr *msg, size_t len)
> >  {
> > @@ -1066,14 +1093,15 @@ static int packet_snd(struct socket *sock,
> >  	__be16 proto;
> >  	unsigned char *addr;
> >  	int ifindex, err, reserve = 0;
> > +	struct virtio_net_hdr vnethdr = { 0 };
> > +	int offset = 0;
> > +	struct packet_sock *po = pkt_sk(sk);
> >  
> >  	/*
> >  	 *	Get and verify the address.
> >  	 */
> >  
> >  	if (saddr == NULL) {
> > -		struct packet_sock *po = pkt_sk(sk);
> > -
> >  		ifindex	= po->ifindex;
> >  		proto	= po->num;
> >  		addr	= NULL;
> > @@ -1100,25 +1128,52 @@ static int packet_snd(struct socket *sock,
> >  	if (!(dev->flags & IFF_UP))
> >  		goto out_unlock;
> >  
> > -	err = -EMSGSIZE;
> > -	if (len > dev->mtu+reserve)
> > -		goto out_unlock;
> > +	if (po->vnet_hdr) {
> > +		err = -EINVAL;
> > +		if (dev->type != ARPHRD_ETHER)
> > +			goto out_unlock;
> > +
> > +		if (len < sizeof(vnethdr))
> > +			goto out_unlock;
> >  
> > -	skb = sock_alloc_send_skb(sk, len + LL_ALLOCATED_SPACE(dev),
> > -				msg->msg_flags & MSG_DONTWAIT, &err);
> > +		len -= sizeof(vnethdr);
> > +
> > +		err = -EFAULT;
> > +		if (memcpy_fromiovec((void *)&vnethdr, msg->msg_iov,
> > +					sizeof(vnethdr))) 
> > +			goto out_unlock;
> > +	
> > +		if ((vnethdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
> > +		    (vnethdr.csum_start + vnethdr.csum_offset + 2 >
> > +		      vnethdr.hdr_len))
> > +			vnethdr.hdr_len = vnethdr.csum_start +
> > +						 vnethdr.csum_offset + 2;
> > +
> > +		err = -EINVAL;
> > +		if (vnethdr.hdr_len > len)
> > +			goto out_unlock;
> > +	} else {
> > +		err = -EMSGSIZE;
> > +		if (len > dev->mtu+reserve)
> > +			goto out_unlock;
> 
> IMO we should always perform the length check if GSO is off.
OK. I will fix this. 
> 
> > +	}
> > +
> > +	err = -ENOBUFS;
> > +	skb = packet_alloc_skb(sk, LL_ALLOCATED_SPACE(dev),
> > +			       LL_RESERVED_SPACE(dev), len, vnethdr.hdr_len,
> > +			       msg->msg_flags & MSG_DONTWAIT, &err);
> >  	if (skb == NULL)
> >  		goto out_unlock;
> >  
> > -	skb_reserve(skb, LL_RESERVED_SPACE(dev));
> > -	skb_reset_network_header(skb);
> > +	skb_set_network_header(skb, reserve);
> 
> I think the above is wrong for vlans?

I also thought we need to address vlans here, but even tun doesn't
handle this in the send routine. I submitted a patch that fixed
skb_gso_segment() to handle vlan packets. This will address both
tun and packet sockets.
http://thread.gmane.org/gmane.linux.network/150198

With this patch, i tested vlans with both ipv4 and ipv6.

> 
> >  
> >  	err = -EINVAL;
> >  	if (sock->type == SOCK_DGRAM &&
> > -	    dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len) < 0)
> > +	    (offset = dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len)) < 0)
> >  		goto out_free;
> >  
> >  	/* Returns -EFAULT on error */
> > -	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
> > +	err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len);
> >  	if (err)
> >  		goto out_free;
> >  
> > @@ -1127,6 +1182,51 @@ static int packet_snd(struct socket *sock,
> >  	skb->priority = sk->sk_priority;
> >  	skb->mark = sk->sk_mark;
> >  
> > +	if (po->vnet_hdr) {
> > +		skb_reset_mac_header(skb);
> > +		skb->protocol = eth_hdr(skb)->h_proto;
> > +
> 
> Is this also broken for vlans?

Same as above. 
> 
> > +		if (vnethdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
> > +			if (!skb_partial_csum_set(skb, vnethdr.csum_start,
> > +						  vnethdr.csum_offset)) {
> > +				err = -EINVAL;
> > +				goto out_free;
> > +			}
> > +		}
> > +
> > +		if (vnethdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
> > +			switch (vnethdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
> > +			case VIRTIO_NET_HDR_GSO_TCPV4:
> > +				skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
> > +				break;
> > +			case VIRTIO_NET_HDR_GSO_TCPV6:
> > +				skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
> > +				break;
> > +			case VIRTIO_NET_HDR_GSO_UDP:
> > +				skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
> > +				break;
> > +			default:
> > +				err = -EINVAL;
> > +				goto out_free;
> > +			}
> > +
> > +			if (vnethdr.gso_type & VIRTIO_NET_HDR_GSO_ECN)
> > +				skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
> > +
> > +			skb_shinfo(skb)->gso_size = vnethdr.gso_size;
> > +			if (skb_shinfo(skb)->gso_size == 0) {
> > +				err = -EINVAL;
> > +				goto out_free;
> > +                	}
> > +
> > +			/* Header must be checked, and gso_segs computed. */
> > +			skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
> > +			skb_shinfo(skb)->gso_segs = 0;
> > +		}
> > +
> > +		len += sizeof(vnethdr);
> > +	}
> > +
> >  	/*
> >  	 *	Now send it
> >  	 */
> > @@ -1420,6 +1520,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
> >  	struct sk_buff *skb;
> >  	int copied, err;
> >  	struct sockaddr_ll *sll;
> > +	int vnet_hdr_len = 0;
> >  
> >  	err = -EINVAL;
> >  	if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT))
> > @@ -1451,6 +1552,44 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
> >  	if (skb == NULL)
> >  		goto out;
> >  
> > +	if (pkt_sk(sk)->vnet_hdr) {
> > +		struct virtio_net_hdr vnethdr = { 0 };
> > +
> > +		vnet_hdr_len = sizeof(vnethdr);
> > +		if ((len -= vnet_hdr_len) < 0)
> > +			return -EINVAL;
> > +
> > +		if (skb_is_gso(skb)) {
> > +			struct skb_shared_info *sinfo = skb_shinfo(skb);
> > +
> > +			/* This is a hint as to how much should be linear. */
> > +			vnethdr.hdr_len = skb_headlen(skb);
> > +			vnethdr.gso_size = sinfo->gso_size;
> > +			if (sinfo->gso_type & SKB_GSO_TCPV4)
> > +				vnethdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
> > +			else if (sinfo->gso_type & SKB_GSO_TCPV6)
> > +				vnethdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
> > +			else if (sinfo->gso_type & SKB_GSO_UDP)
> > +				vnethdr.gso_type = VIRTIO_NET_HDR_GSO_UDP;
> > +			else
> > +				BUG();
> 
> Is there any chance this can get SKB_GSO_FCOE by binding to
> an appropriate interface?  Maybe we don't want to BUG().
I could return -EINVAL in that case.

> 
> > +			if (sinfo->gso_type & SKB_GSO_TCP_ECN)
> > +				vnethdr.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
> > +		} else
> > +			vnethdr.gso_type = VIRTIO_NET_HDR_GSO_NONE;
> > +
> > +		if (skb->ip_summed == CHECKSUM_PARTIAL) {
> > +			vnethdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
> > +			vnethdr.csum_start = skb->csum_start - skb_headroom(skb);
> > +			vnethdr.csum_offset = skb->csum_offset;
> > +		} /* else everything is zero */
> > +
> > +		if (unlikely(memcpy_toiovec(msg->msg_iov, (void *)&vnethdr,
> > +					    sizeof(vnethdr)))) {
> > +			return -EFAULT;
> > +		}
> > +	}
> > +
> >  	/*
> >  	 *	If the address length field is there to be filled in, we fill
> >  	 *	it in now.
> > @@ -1502,7 +1641,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
> >  	 *	Free or return the buffer as appropriate. Again this
> >  	 *	hides all the races and re-entrancy issues from us.
> >  	 */
> > -	err = (flags&MSG_TRUNC) ? skb->len : copied;
> > +	err = vnet_hdr_len + ((flags&MSG_TRUNC) ? skb->len : copied);
> >  
> >  out_free:
> >  	skb_free_datagram(sk, skb);
> > @@ -1826,6 +1965,22 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
> >  		po->origdev = !!val;
> >  		return 0;
> >  	}
> > +	case PACKET_VNET_HDR:
> > +	{
> > +		int val;
> > +
> > +		if (sock->type != SOCK_RAW)
> > +			return -EINVAL;
> > +		if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)	
> > +			return -EBUSY;
> 
> Another way to get a broken ring + vnet hdr configuration
> would be to enable vnet hdr first and mmap second.
> I think we need to guard against this as well, by checking vnet_hdr
> when tx/rx ring is enabled.

OK. i will add a check when setting PACKET_RX_RING/TX_RING socket
options. 
> > +		if (optlen < sizeof(val))
> > +			return -EINVAL;
> > +		if (copy_from_user(&val, optval, sizeof(val)))
> > +			return -EFAULT;
> > +
> > +		po->vnet_hdr = !!val;
> > +		return 0;
> > +	}
> >  	default:
> >  		return -ENOPROTOOPT;
> >  	}
> > @@ -1876,6 +2031,13 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
> >  
> >  		data = &val;
> >  		break;
> > +	case PACKET_VNET_HDR:
> > +		if (len > sizeof(int))
> > +			len = sizeof(int);
> > +		val = po->vnet_hdr;
> > +
> > +		data = &val;
> > +		break;
> >  #ifdef CONFIG_PACKET_MMAP
> >  	case PACKET_VERSION:
> >  		if (len > sizeof(int))
> > 
> 


^ permalink raw reply

* Re: [PATCH 3/3] sky2: Remove failure cases for sky2_rx_start
From: Stephen Hemminger @ 2010-01-27 17:10 UTC (permalink / raw)
  To: Mike McCormack; +Cc: netdev
In-Reply-To: <4B605652.6020400@ring3k.org>

On Thu, 28 Jan 2010 00:05:54 +0900
Mike McCormack <mikem@ring3k.org> wrote:

> sky2_rx_start() can no longer fail, so remove redundant code pathes.
> 
> Signed-off-by: Mike McCormack <mikem@ring3k.org>

This can't work right if MTU is increased. The buffers need to be reallocated
in change_mtu(); and yes it could fail when getting the new buffers.


-- 

^ permalink raw reply

* [PATCH] cxgb3/iw_cxgb3: doorbell overflow avoidance and recovery.
From: Steve Wise @ 2010-01-27 17:03 UTC (permalink / raw)
  To: rdreier-FYB4Gu1CFyUAvxtiuMwx3w
  Cc: jeff-o2qLIJkoznsdnm+yROfE0A, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, divy-ut6Up61K2wZBDgjK7y7TUQ

T3 hardware doorbell fifo overflows can cause application stalls due to
lost doorbell ring events.  This has been seen when running large NP IMB
alltoall MPI jobs.  The T3 hardware supports an xon/xoff type control
mechanism to help avoid overflowing the hw db fifo.

This patch utilizes these interrupts to disable rdma qp db rings when
we near an overflow condition, and then turn them back on (and ring all
the active qp dbs) when when the db fifo emptys out.  In addition if an
db ring is dropped by the hardware, the code will now recover.

Design:

cxgb3:

- enable these DB interrupts

- in the intr handler, schedule work tasks to call the ULPs event handlers
with the new events.

- ring all the qset txqs when an overflow is detected.

iw_cxgb3:

- disable db ringing on all active qps when we get the DB_FULL event

- enable db ringing on all active qps and ring all active dbs when we get
  the DB_EMPTY event

- On DB_DROP event:
       - disable db rings in the event handler

       - delay-schedule a work task which rings and enables the dbs on
         all active qps.

- in post_send and post_recv logic, don't ring the db if its disabled.

Signed-off-by: Steve Wise <swise-7bPotxP6k4+P2YhJcF5u+vpXobYPEAuW@public.gmane.org>
---

 drivers/infiniband/hw/cxgb3/cxio_wr.h |   17 +++++++
 drivers/infiniband/hw/cxgb3/iwch.c    |   79 +++++++++++++++++++++++++++++++--
 drivers/infiniband/hw/cxgb3/iwch.h    |    2 +
 drivers/infiniband/hw/cxgb3/iwch_qp.c |    9 +++-
 drivers/net/cxgb3/adapter.h           |    5 ++
 drivers/net/cxgb3/cxgb3_main.c        |   57 +++++++++++++++++++++++-
 drivers/net/cxgb3/cxgb3_offload.h     |    5 ++
 drivers/net/cxgb3/regs.h              |   16 +++++++
 drivers/net/cxgb3/sge.c               |   15 +++++-
 drivers/net/cxgb3/t3_hw.c             |    5 ++
 10 files changed, 196 insertions(+), 14 deletions(-)

diff --git a/drivers/infiniband/hw/cxgb3/cxio_wr.h b/drivers/infiniband/hw/cxgb3/cxio_wr.h
index a197a5b..15073b2 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_wr.h
+++ b/drivers/infiniband/hw/cxgb3/cxio_wr.h
@@ -730,7 +730,22 @@ struct t3_cq {
 
 static inline void cxio_set_wq_in_error(struct t3_wq *wq)
 {
-	wq->queue->wq_in_err.err = 1;
+	wq->queue->wq_in_err.err |= 1;
+}
+
+static inline void cxio_disable_wq_db(struct t3_wq *wq)
+{
+	wq->queue->wq_in_err.err |= 2;
+}
+
+static inline void cxio_enable_wq_db(struct t3_wq *wq)
+{
+	wq->queue->wq_in_err.err &= ~2;
+}
+
+static inline int cxio_wq_db_enabled(struct t3_wq *wq)
+{
+	return !(wq->queue->wq_in_err.err & 2);
 }
 
 static inline struct t3_cqe *cxio_next_hw_cqe(struct t3_cq *cq)
diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c
index b0ea010..6a3214a 100644
--- a/drivers/infiniband/hw/cxgb3/iwch.c
+++ b/drivers/infiniband/hw/cxgb3/iwch.c
@@ -65,6 +65,46 @@ struct cxgb3_client t3c_client = {
 static LIST_HEAD(dev_list);
 static DEFINE_MUTEX(dev_mutex);
 
+static int disable_qp_db(int id, void *p, void *data)
+{
+	struct iwch_qp *qhp = p;
+	
+	cxio_disable_wq_db(&qhp->wq);
+	return 0;
+}
+
+static int enable_qp_db(int id, void *p, void *data)
+{
+	struct iwch_qp *qhp = p;
+	
+	if (data)
+		ring_doorbell(qhp->rhp->rdev.ctrl_qp.doorbell, qhp->wq.qpid);
+	cxio_enable_wq_db(&qhp->wq);
+	return 0;
+}
+
+static void disable_dbs(struct iwch_dev *rnicp)
+{
+	spin_lock_irq(&rnicp->lock);
+	idr_for_each(&rnicp->qpidr, disable_qp_db, NULL);
+	spin_unlock_irq(&rnicp->lock);
+}
+
+static void enable_dbs(struct iwch_dev *rnicp, int ring_db)
+{
+	spin_lock_irq(&rnicp->lock);
+	idr_for_each(&rnicp->qpidr, enable_qp_db, 
+		     (void *)(unsigned long)ring_db);
+	spin_unlock_irq(&rnicp->lock);
+}
+
+static void iwch_db_drop_task(struct work_struct *work)
+{
+	struct iwch_dev *rnicp = container_of(work, struct iwch_dev,
+					      db_drop_task.work);
+	enable_dbs(rnicp, 1);
+}
+
 static void rnic_init(struct iwch_dev *rnicp)
 {
 	PDBG("%s iwch_dev %p\n", __func__,  rnicp);
@@ -72,6 +112,7 @@ static void rnic_init(struct iwch_dev *rnicp)
 	idr_init(&rnicp->qpidr);
 	idr_init(&rnicp->mmidr);
 	spin_lock_init(&rnicp->lock);
+	INIT_DELAYED_WORK(&rnicp->db_drop_task, iwch_db_drop_task);
 
 	rnicp->attr.max_qps = T3_MAX_NUM_QP - 32;
 	rnicp->attr.max_wrs = T3_MAX_QP_DEPTH;
@@ -147,6 +188,7 @@ static void close_rnic_dev(struct t3cdev *tdev)
 	mutex_lock(&dev_mutex);
 	list_for_each_entry_safe(dev, tmp, &dev_list, entry) {
 		if (dev->rdev.t3cdev_p == tdev) {
+			cancel_delayed_work_sync(&dev->db_drop_task);
 			list_del(&dev->entry);
 			iwch_unregister_device(dev);
 			cxio_rdev_close(&dev->rdev);
@@ -165,7 +207,8 @@ static void iwch_event_handler(struct t3cdev *tdev, u32 evt, u32 port_id)
 	struct cxio_rdev *rdev = tdev->ulp;
 	struct iwch_dev *rnicp;
 	struct ib_event event;
-	u32    portnum = port_id + 1;
+	u32 portnum = port_id + 1;
+	int dispatch = 0;
 
 	if (!rdev)
 		return;
@@ -174,21 +217,49 @@ static void iwch_event_handler(struct t3cdev *tdev, u32 evt, u32 port_id)
 	case OFFLOAD_STATUS_DOWN: {
 		rdev->flags = CXIO_ERROR_FATAL;
 		event.event  = IB_EVENT_DEVICE_FATAL;
+		dispatch = 1;
 		break;
 		}
 	case OFFLOAD_PORT_DOWN: {
 		event.event  = IB_EVENT_PORT_ERR;
+		dispatch = 1;
 		break;
 		}
 	case OFFLOAD_PORT_UP: {
 		event.event  = IB_EVENT_PORT_ACTIVE;
+		dispatch = 1;
+		break;
+		}
+	case OFFLOAD_DB_FULL: {
+		disable_dbs(rnicp);
+		break;
+		}
+	case OFFLOAD_DB_EMPTY: {
+		enable_dbs(rnicp, 1);
+		break;
+		}
+	case OFFLOAD_DB_DROP: {
+		unsigned long delay = 1000;
+		unsigned short r;
+
+		disable_dbs(rnicp);
+		get_random_bytes(&r, 2);
+		delay += r & 1023;
+
+		/*
+		 * delay is between 1000-2023 usecs.
+		 */
+		schedule_delayed_work(&rnicp->db_drop_task, 
+			usecs_to_jiffies(delay));
 		break;
 		}
 	}
 
-	event.device = &rnicp->ibdev;
-	event.element.port_num = portnum;
-	ib_dispatch_event(&event);
+	if (dispatch) {
+		event.device = &rnicp->ibdev;
+		event.element.port_num = portnum;
+		ib_dispatch_event(&event);
+	}
 
 	return;
 }
diff --git a/drivers/infiniband/hw/cxgb3/iwch.h b/drivers/infiniband/hw/cxgb3/iwch.h
index 8473550..a1c4457 100644
--- a/drivers/infiniband/hw/cxgb3/iwch.h
+++ b/drivers/infiniband/hw/cxgb3/iwch.h
@@ -36,6 +36,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/idr.h>
+#include <linux/workqueue.h>
 
 #include <rdma/ib_verbs.h>
 
@@ -110,6 +111,7 @@ struct iwch_dev {
 	struct idr mmidr;
 	spinlock_t lock;
 	struct list_head entry;
+	struct delayed_work db_drop_task;
 };
 
 static inline struct iwch_dev *to_iwch_dev(struct ib_device *ibdev)
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index 3eb8cec..b4d893d 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -452,7 +452,8 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		++(qhp->wq.sq_wptr);
 	}
 	spin_unlock_irqrestore(&qhp->lock, flag);
-	ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+	if (cxio_wq_db_enabled(&qhp->wq))
+		ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
 
 out:
 	if (err)
@@ -514,7 +515,8 @@ int iwch_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 		num_wrs--;
 	}
 	spin_unlock_irqrestore(&qhp->lock, flag);
-	ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+	if (cxio_wq_db_enabled(&qhp->wq))
+		ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
 
 out:
 	if (err)
@@ -597,7 +599,8 @@ int iwch_bind_mw(struct ib_qp *qp,
 	++(qhp->wq.sq_wptr);
 	spin_unlock_irqrestore(&qhp->lock, flag);
 
-	ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+	if (cxio_wq_db_enabled(&qhp->wq))
+		ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
 
 	return err;
 }
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 3e8618b..11d148c 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -263,6 +263,10 @@ struct adapter {
 	struct work_struct ext_intr_handler_task;
 	struct work_struct fatal_error_handler_task;
 	struct work_struct link_fault_handler_task;
+	
+	struct work_struct db_full_task;
+	struct work_struct db_empty_task;
+	struct work_struct db_drop_task;
 
 	struct dentry *debugfs_root;
 
@@ -335,6 +339,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
 int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx,
 		unsigned char *data);
 irqreturn_t t3_sge_intr_msix(int irq, void *cookie);
+extern struct workqueue_struct *cxgb3_wq;
 
 int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size);
 
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 2aaa747..f47dc76 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -45,6 +45,7 @@
 #include <linux/firmware.h>
 #include <linux/log2.h>
 #include <linux/stringify.h>
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 
 #include "common.h"
@@ -140,7 +141,7 @@ MODULE_PARM_DESC(ofld_disable, "whether to enable offload at init time or not");
  * will block keventd as it needs the rtnl lock, and we'll deadlock waiting
  * for our work to complete.  Get our own work queue to solve this.
  */
-static struct workqueue_struct *cxgb3_wq;
+struct workqueue_struct *cxgb3_wq;
 
 /**
  *	link_report - show link status and link speed/duplex
@@ -590,6 +591,19 @@ static void setup_rss(struct adapter *adap)
 		      V_RRCPLCPUSIZE(6) | F_HASHTOEPLITZ, cpus, rspq_map);
 }
 
+static void ring_dbs(struct adapter *adap)
+{
+	int i, j;
+
+	for (i = 0; i < SGE_QSETS; i++) {
+		struct sge_qset *qs = &adap->sge.qs[i];
+
+		if (qs->adap)
+			for (j=0; j < SGE_TXQ_PER_SET; j++)
+				t3_write_reg(adap, A_SG_KDOORBELL, F_SELEGRCNTX | V_EGRCNTX(qs->txq[j].cntxt_id));
+	}
+}
+
 static void init_napi(struct adapter *adap)
 {
 	int i;
@@ -2778,6 +2792,42 @@ static void t3_adap_check_task(struct work_struct *work)
 	spin_unlock_irq(&adapter->work_lock);
 }
 
+static void db_full_task(struct work_struct *work)
+{
+	struct adapter *adapter = container_of(work, struct adapter,
+					       db_full_task);
+
+	cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_FULL, 0);
+}
+
+static void db_empty_task(struct work_struct *work)
+{
+	struct adapter *adapter = container_of(work, struct adapter,
+					       db_empty_task);
+
+	cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_EMPTY, 0);
+}
+
+static void db_drop_task(struct work_struct *work)
+{
+	struct adapter *adapter = container_of(work, struct adapter,
+					       db_drop_task);
+	unsigned long delay = 1000;
+	unsigned short r;
+
+	cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_DROP, 0);
+
+	/* 
+	 * Sleep a while before ringing the driver qset dbs.
+	 * The delay is between 1000-2023 usecs.
+	 */
+	get_random_bytes(&r, 2);
+	delay += r & 1023;
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(usecs_to_jiffies(delay));
+	ring_dbs(adapter);
+}
+
 /*
  * Processes external (PHY) interrupts in process context.
  */
@@ -3246,6 +3296,11 @@ static int __devinit init_one(struct pci_dev *pdev,
 	INIT_LIST_HEAD(&adapter->adapter_list);
 	INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task);
 	INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task);
+
+	INIT_WORK(&adapter->db_full_task, db_full_task);
+	INIT_WORK(&adapter->db_empty_task, db_empty_task);
+	INIT_WORK(&adapter->db_drop_task, db_drop_task);
+
 	INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task);
 
 	for (i = 0; i < ai->nports0 + ai->nports1; ++i) {
diff --git a/drivers/net/cxgb3/cxgb3_offload.h b/drivers/net/cxgb3/cxgb3_offload.h
index 670aa62..929c298 100644
--- a/drivers/net/cxgb3/cxgb3_offload.h
+++ b/drivers/net/cxgb3/cxgb3_offload.h
@@ -73,7 +73,10 @@ enum {
 	OFFLOAD_STATUS_UP,
 	OFFLOAD_STATUS_DOWN,
 	OFFLOAD_PORT_DOWN,
-	OFFLOAD_PORT_UP
+	OFFLOAD_PORT_UP,
+	OFFLOAD_DB_FULL,
+	OFFLOAD_DB_EMPTY,
+	OFFLOAD_DB_DROP
 };
 
 struct cxgb3_client {
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index 1b5327b..cb42353 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -254,6 +254,22 @@
 #define V_LOPIODRBDROPERR(x) ((x) << S_LOPIODRBDROPERR)
 #define F_LOPIODRBDROPERR    V_LOPIODRBDROPERR(1U)
 
+#define S_HIPRIORITYDBFULL    7
+#define V_HIPRIORITYDBFULL(x) ((x) << S_HIPRIORITYDBFULL)
+#define F_HIPRIORITYDBFULL    V_HIPRIORITYDBFULL(1U)
+
+#define S_HIPRIORITYDBEMPTY   6
+#define V_HIPRIORITYDBEMPTY(x) ((x) << S_HIPRIORITYDBEMPTY)
+#define F_HIPRIORITYDBEMPTY    V_HIPRIORITYDBEMPTY(1U)
+
+#define S_LOPRIORITYDBFULL    5
+#define V_LOPRIORITYDBFULL(x) ((x) << S_LOPRIORITYDBFULL)
+#define F_LOPRIORITYDBFULL    V_LOPRIORITYDBFULL(1U)
+
+#define S_LOPRIORITYDBEMPTY   4
+#define V_LOPRIORITYDBEMPTY(x) ((x) << S_LOPRIORITYDBEMPTY)
+#define F_LOPRIORITYDBEMPTY    V_LOPRIORITYDBEMPTY(1U)
+
 #define S_RSPQDISABLED    3
 #define V_RSPQDISABLED(x) ((x) << S_RSPQDISABLED)
 #define F_RSPQDISABLED    V_RSPQDISABLED(1U)
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index bdbd147..08978ad 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -42,6 +42,7 @@
 #include "sge_defs.h"
 #include "t3_cpl.h"
 #include "firmware_exports.h"
+#include "cxgb3_offload.h"
 
 #define USE_GTS 0
 
@@ -2828,9 +2829,17 @@ void t3_sge_err_intr_handler(struct adapter *adapter)
 			 "(0x%x)\n", (v >> S_RSPQ0DISABLED) & 0xff);
 	}
 
-	if (status & (F_HIPIODRBDROPERR | F_LOPIODRBDROPERR))
-		CH_ALERT(adapter, "SGE dropped %s priority doorbell\n",
-			 status & F_HIPIODRBDROPERR ? "high" : "lo");
+	if (status & (F_HIPIODRBDROPERR | F_LOPIODRBDROPERR)) {
+		queue_work(cxgb3_wq, &adapter->db_drop_task);
+	}
+
+	if (status & (F_HIPRIORITYDBFULL | F_LOPRIORITYDBFULL)) {
+		queue_work(cxgb3_wq, &adapter->db_full_task);
+	}
+
+	if (status & (F_HIPRIORITYDBEMPTY | F_LOPRIORITYDBEMPTY)) {
+		queue_work(cxgb3_wq, &adapter->db_empty_task);
+	}
 
 	t3_write_reg(adapter, A_SG_INT_CAUSE, status);
 	if (status &  SGE_FATALERR)
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index 032cfe0..c38fc71 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -1432,7 +1432,10 @@ static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg,
 		       F_IRPARITYERROR | V_ITPARITYERROR(M_ITPARITYERROR) | \
 		       V_FLPARITYERROR(M_FLPARITYERROR) | F_LODRBPARITYERROR | \
 		       F_HIDRBPARITYERROR | F_LORCQPARITYERROR | \
-		       F_HIRCQPARITYERROR)
+		       F_HIRCQPARITYERROR | F_LOPRIORITYDBFULL | \
+		       F_HIPRIORITYDBFULL | F_LOPRIORITYDBEMPTY | \
+		       F_HIPRIORITYDBEMPTY | F_HIPIODRBDROPERR | \
+		       F_LOPIODRBDROPERR)
 #define MC5_INTR_MASK (F_PARITYERR | F_ACTRGNFULL | F_UNKNOWNCMD | \
 		       F_REQQPARERR | F_DISPQPARERR | F_DELACTEMPTY | \
 		       F_NFASRCHFAIL)

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH 1/2] syncookies: print synflood warning if syn queue is full
From: Olaf van der Spek @ 2010-01-27 17:01 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netdev
In-Reply-To: <20091208.130959.138311725.davem@davemloft.net>

On Tue, Dec 8, 2009 at 10:09 PM, David Miller <davem@davemloft.net> wrote:
> From: Olaf van der Spek <olafvdspek@gmail.com>
> Date: Tue, 8 Dec 2009 15:47:59 +0100
>
>> On Fri, Oct 16, 2009 at 8:49 PM, Florian Westphal <fw@strlen.de> wrote:
>>> Always print a warning if the syn queue is full, just like
>>> the tcp/ipv6 code does.
>>>
>>> The "want_cookie" define is no longer needed -- gcc
>>> removes the relevant branches in the CONFIG_SYN_COOKIES=n case.
>>>
>>> Signed-off-by: Florian Westphal <fw@strlen.de>
>>
>> Any comments?
>
> You patch isn't even in patchwork any more, so for one thing
> it's definitely not in my queue any more.

Florian?

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox