From: Gregory Haskins <ghaskins@novell.com>
To: linux-kernel@vger.kernel.org
Cc: agraf@suse.de, pmullaney@novell.com, pmorreale@novell.com,
anthony@codemonkey.ws, rusty@rustcorp.com.au,
netdev@vger.kernel.org, kvm@vger.kernel.org
Subject: [RFC PATCH 11/17] venet: add scatter-gather support
Date: Tue, 31 Mar 2009 14:43:44 -0400 [thread overview]
Message-ID: <20090331184344.28333.53834.stgit@dev.haskins.net> (raw)
In-Reply-To: <20090331184057.28333.77287.stgit@dev.haskins.net>
Signed-off-by: Gregory Haskins <ghaskins@novell.com>
---
drivers/net/vbus-enet.c | 249 +++++++++++++++++++++++++++++++++++++++++++++--
include/linux/venet.h | 39 +++++++
2 files changed, 275 insertions(+), 13 deletions(-)
diff --git a/drivers/net/vbus-enet.c b/drivers/net/vbus-enet.c
index e698b3f..8e96c9c 100644
--- a/drivers/net/vbus-enet.c
+++ b/drivers/net/vbus-enet.c
@@ -42,6 +42,8 @@ static int rx_ringlen = 256;
module_param(rx_ringlen, int, 0444);
static int tx_ringlen = 256;
module_param(tx_ringlen, int, 0444);
+static int sg_enabled = 1;
+module_param(sg_enabled, int, 0444);
#undef PDEBUG /* undef it, just in case */
#ifdef VBUS_ENET_DEBUG
@@ -64,8 +66,17 @@ struct vbus_enet_priv {
struct vbus_enet_queue rxq;
struct vbus_enet_queue txq;
struct tasklet_struct txtask;
+ struct {
+ int sg:1;
+ int tso:1;
+ int ufo:1;
+ int tso6:1;
+ int ecn:1;
+ } flags;
};
+static void vbus_enet_tx_reap(struct vbus_enet_priv *priv, int force);
+
static struct vbus_enet_priv *
napi_to_priv(struct napi_struct *napi)
{
@@ -199,6 +210,93 @@ rx_teardown(struct vbus_enet_priv *priv)
}
}
+static int
+tx_setup(struct vbus_enet_priv *priv)
+{
+ struct ioq *ioq = priv->txq.queue;
+ struct ioq_iterator iter;
+ int i;
+ int ret;
+
+ if (!priv->flags.sg)
+ /*
+ * There is nothing to do for a ring that is not using
+ * scatter-gather
+ */
+ return 0;
+
+ ret = ioq_iter_init(ioq, &iter, ioq_idxtype_valid, 0);
+ BUG_ON(ret < 0);
+
+ ret = ioq_iter_seek(&iter, ioq_seek_set, 0, 0);
+ BUG_ON(ret < 0);
+
+ /*
+ * Now populate each descriptor with an empty SG descriptor
+ */
+ for (i = 0; i < tx_ringlen; i++) {
+ struct venet_sg *vsg;
+ size_t iovlen = sizeof(struct venet_iov) * (MAX_SKB_FRAGS-1);
+ size_t len = sizeof(*vsg) + iovlen;
+
+ vsg = kzalloc(len, GFP_KERNEL);
+ if (!vsg)
+ return -ENOMEM;
+
+ iter.desc->cookie = (u64)vsg;
+ iter.desc->len = len;
+ iter.desc->ptr = (u64)__pa(vsg);
+
+ ret = ioq_iter_seek(&iter, ioq_seek_next, 0, 0);
+ BUG_ON(ret < 0);
+ }
+
+ return 0;
+}
+
+static void
+tx_teardown(struct vbus_enet_priv *priv)
+{
+ struct ioq *ioq = priv->txq.queue;
+ struct ioq_iterator iter;
+ int ret;
+
+ /* forcefully free all outstanding transmissions */
+ vbus_enet_tx_reap(priv, 1);
+
+ if (!priv->flags.sg)
+ /*
+ * There is nothing else to do for a ring that is not using
+ * scatter-gather
+ */
+ return;
+
+ ret = ioq_iter_init(ioq, &iter, ioq_idxtype_valid, 0);
+ BUG_ON(ret < 0);
+
+ /* seek to position 0 */
+ ret = ioq_iter_seek(&iter, ioq_seek_set, 0, 0);
+ BUG_ON(ret < 0);
+
+ /*
+ * free each valid descriptor
+ */
+ while (iter.desc->cookie) {
+ struct venet_sg *vsg = (struct venet_sg *)iter.desc->cookie;
+
+ iter.desc->valid = 0;
+ wmb();
+
+ iter.desc->ptr = 0;
+ iter.desc->cookie = 0;
+
+ ret = ioq_iter_seek(&iter, ioq_seek_next, 0, 0);
+ BUG_ON(ret < 0);
+
+ kfree(vsg);
+ }
+}
+
/*
* Open and close
*/
@@ -403,14 +501,67 @@ vbus_enet_tx_start(struct sk_buff *skb, struct net_device *dev)
BUG_ON(ret < 0);
BUG_ON(iter.desc->sown);
- /*
- * We simply put the skb right onto the ring. We will get an interrupt
- * later when the data has been consumed and we can reap the pointers
- * at that time
- */
- iter.desc->cookie = (u64)skb;
- iter.desc->len = (u64)skb->len;
- iter.desc->ptr = (u64)__pa(skb->data);
+ if (priv->flags.sg) {
+ struct venet_sg *vsg = (struct venet_sg *)iter.desc->cookie;
+ struct scatterlist sgl[MAX_SKB_FRAGS+1];
+ struct scatterlist *sg;
+ int count, maxcount = ARRAY_SIZE(sgl);
+
+ sg_init_table(sgl, maxcount);
+
+ memset(vsg, 0, sizeof(*vsg));
+
+ vsg->cookie = (u64)skb;
+ vsg->len = skb->len;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ vsg->flags |= VENET_SG_FLAG_NEEDS_CSUM;
+ vsg->csum.start = skb->csum_start - skb_headroom(skb);
+ vsg->csum.offset = skb->csum_offset;
+ }
+
+ if (skb_is_gso(skb)) {
+ struct skb_shared_info *sinfo = skb_shinfo(skb);
+
+ vsg->flags |= VENET_SG_FLAG_GSO;
+
+ vsg->gso.hdrlen = skb_transport_header(skb) - skb->data;
+ vsg->gso.size = sinfo->gso_size;
+ if (sinfo->gso_type & SKB_GSO_TCPV4)
+ vsg->gso.type = VENET_GSO_TYPE_TCPV4;
+ else if (sinfo->gso_type & SKB_GSO_TCPV6)
+ vsg->gso.type = VENET_GSO_TYPE_TCPV6;
+ else if (sinfo->gso_type & SKB_GSO_UDP)
+ vsg->gso.type = VENET_GSO_TYPE_UDP;
+ else
+ panic("Virtual-Ethernet: unknown GSO type " \
+ "0x%x\n", sinfo->gso_type);
+
+ if (sinfo->gso_type & SKB_GSO_TCP_ECN)
+ vsg->flags |= VENET_SG_FLAG_ECN;
+ }
+
+ count = skb_to_sgvec(skb, sgl, 0, skb->len);
+
+ BUG_ON(count > maxcount);
+
+ for (sg = &sgl[0]; sg; sg = sg_next(sg)) {
+ struct venet_iov *iov = &vsg->iov[vsg->count++];
+
+ iov->len = sg->length;
+ iov->ptr = (u64)sg_phys(sg);
+ }
+
+ } else {
+ /*
+ * non scatter-gather mode: simply put the skb right onto the
+ * ring.
+ */
+ iter.desc->cookie = (u64)skb;
+ iter.desc->len = (u64)skb->len;
+ iter.desc->ptr = (u64)__pa(skb->data);
+ }
+
iter.desc->valid = 1;
priv->stats.tx_packets++;
@@ -466,7 +617,17 @@ vbus_enet_tx_reap(struct vbus_enet_priv *priv, int force)
* owned by the south-side
*/
while (iter.desc->valid && (!iter.desc->sown || force)) {
- struct sk_buff *skb = (struct sk_buff *)iter.desc->cookie;
+ struct sk_buff *skb;
+
+ if (priv->flags.sg) {
+ struct venet_sg *vsg;
+
+ vsg = (struct venet_sg *)iter.desc->cookie;
+ skb = (struct sk_buff *)vsg->cookie;
+
+ } else {
+ skb = (struct sk_buff *)iter.desc->cookie;
+ }
PDEBUG("%lld: completed sending %d bytes\n",
priv->vdev->id, skb->len);
@@ -567,6 +728,47 @@ tx_isr(struct ioq_notifier *notifier)
tasklet_schedule(&priv->txtask);
}
+static int
+vbus_enet_negcap(struct vbus_enet_priv *priv)
+{
+ int ret;
+ struct venet_capabilities caps;
+
+ memset(&caps, 0, sizeof(caps));
+
+ if (sg_enabled) {
+ caps.gid = VENET_CAP_GROUP_SG;
+ caps.bits |= (VENET_CAP_SG|VENET_CAP_TSO4|VENET_CAP_TSO6
+ |VENET_CAP_ECN|VENET_CAP_UFO);
+ }
+
+ ret = devcall(priv, VENET_FUNC_NEGCAP, &caps, sizeof(caps));
+ if (ret < 0)
+ return ret;
+
+ if (caps.bits & VENET_CAP_SG) {
+ priv->flags.sg = true;
+
+ if (caps.bits & VENET_CAP_TSO4)
+ priv->flags.tso = true;
+ if (caps.bits & VENET_CAP_TSO6)
+ priv->flags.tso6 = true;
+ if (caps.bits & VENET_CAP_UFO)
+ priv->flags.ufo = true;
+ if (caps.bits & VENET_CAP_ECN)
+ priv->flags.ecn = true;
+
+ printk(KERN_INFO "VBUSENET %lld: " \
+ "Detected GSO features %s%s%s%s\n", priv->vdev->id,
+ priv->flags.tso ? "t" : "-",
+ priv->flags.tso6 ? "T" : "-",
+ priv->flags.ufo ? "u" : "-",
+ priv->flags.ecn ? "e" : "-");
+ }
+
+ return 0;
+}
+
static struct net_device_ops vbus_enet_netdev_ops = {
.ndo_open = vbus_enet_open,
.ndo_stop = vbus_enet_stop,
@@ -606,12 +808,21 @@ vbus_enet_probe(struct vbus_device_proxy *vdev)
priv->dev = dev;
priv->vdev = vdev;
+ ret = vbus_enet_negcap(priv);
+ if (ret < 0) {
+ printk(KERN_INFO "VENET: Error negotiating capabilities for " \
+ "%lld\n",
+ priv->vdev->id);
+ goto out_free;
+ }
+
tasklet_init(&priv->txtask, deferred_tx_isr, (unsigned long)priv);
queue_init(priv, &priv->rxq, VENET_QUEUE_RX, rx_ringlen, rx_isr);
queue_init(priv, &priv->txq, VENET_QUEUE_TX, tx_ringlen, tx_isr);
rx_setup(priv);
+ tx_setup(priv);
ioq_notify_enable(priv->rxq.queue, 0); /* enable interrupts */
ioq_notify_enable(priv->txq.queue, 0);
@@ -633,6 +844,22 @@ vbus_enet_probe(struct vbus_device_proxy *vdev)
dev->features |= NETIF_F_HIGHDMA;
+ if (priv->flags.sg) {
+ dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM|NETIF_F_FRAGLIST;
+
+ if (priv->flags.tso)
+ dev->features |= NETIF_F_TSO;
+
+ if (priv->flags.ufo)
+ dev->features |= NETIF_F_UFO;
+
+ if (priv->flags.tso6)
+ dev->features |= NETIF_F_TSO6;
+
+ if (priv->flags.ecn)
+ dev->features |= NETIF_F_TSO_ECN;
+ }
+
ret = register_netdev(dev);
if (ret < 0) {
printk(KERN_INFO "VENET: error %i registering device \"%s\"\n",
@@ -660,9 +887,9 @@ vbus_enet_remove(struct vbus_device_proxy *vdev)
napi_disable(&priv->napi);
rx_teardown(priv);
- vbus_enet_tx_reap(priv, 1);
-
ioq_put(priv->rxq.queue);
+
+ tx_teardown(priv);
ioq_put(priv->txq.queue);
dev->ops->close(dev, 0);
diff --git a/include/linux/venet.h b/include/linux/venet.h
index ef6b199..1c96b90 100644
--- a/include/linux/venet.h
+++ b/include/linux/venet.h
@@ -35,8 +35,43 @@ struct venet_capabilities {
__u32 bits;
};
-/* CAPABILITIES-GROUP 0 */
-/* #define VENET_CAP_FOO 0 (No capabilities defined yet, for now) */
+#define VENET_CAP_GROUP_SG 0
+
+/* CAPABILITIES-GROUP SG */
+#define VENET_CAP_SG (1 << 0)
+#define VENET_CAP_TSO4 (1 << 1)
+#define VENET_CAP_TSO6 (1 << 2)
+#define VENET_CAP_ECN (1 << 3)
+#define VENET_CAP_UFO (1 << 4)
+
+struct venet_iov {
+ __u32 len;
+ __u64 ptr;
+};
+
+#define VENET_SG_FLAG_NEEDS_CSUM (1 << 0)
+#define VENET_SG_FLAG_GSO (1 << 1)
+#define VENET_SG_FLAG_ECN (1 << 2)
+
+struct venet_sg {
+ __u64 cookie;
+ __u32 flags;
+ __u32 len; /* total length of all iovs */
+ struct {
+ __u16 start; /* csum starting position */
+ __u16 offset; /* offset to place csum */
+ } csum;
+ struct {
+#define VENET_GSO_TYPE_TCPV4 0 /* IPv4 TCP (TSO) */
+#define VENET_GSO_TYPE_UDP 1 /* IPv4 UDP (UFO) */
+#define VENET_GSO_TYPE_TCPV6 2 /* IPv6 TCP */
+ __u8 type;
+ __u16 hdrlen;
+ __u16 size;
+ } gso;
+ __u32 count; /* nr of iovs */
+ struct venet_iov iov[1];
+};
#define VENET_FUNC_LINKUP 0
#define VENET_FUNC_LINKDOWN 1
next prev parent reply other threads:[~2009-03-31 18:43 UTC|newest]
Thread overview: 146+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-03-31 18:42 [RFC PATCH 00/17] virtual-bus Gregory Haskins
2009-03-31 18:42 ` [RFC PATCH 01/17] shm-signal: shared-memory signals Gregory Haskins
2009-03-31 20:44 ` Avi Kivity
2009-03-31 20:58 ` Gregory Haskins
2009-03-31 21:05 ` Avi Kivity
2009-04-01 12:12 ` Gregory Haskins
2009-04-01 12:24 ` Avi Kivity
2009-04-01 13:57 ` Gregory Haskins
2009-03-31 18:42 ` [RFC PATCH 02/17] vbus: add virtual-bus definitions Gregory Haskins
2009-04-02 16:06 ` Ben Hutchings
2009-04-02 18:13 ` Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 03/17] vbus: add connection-client helper infrastructure Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 04/17] vbus: add bus-registration notifiers Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 05/17] vbus: add a "vbus-proxy" bus model for vbus_driver objects Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 06/17] ioq: Add basic definitions for a shared-memory, lockless queue Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 07/17] ioq: add vbus helpers Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 08/17] venet: add the ABI definitions for an 802.x packet interface Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 09/17] net: Add vbus_enet driver Gregory Haskins
2009-03-31 20:39 ` Stephen Hemminger
2009-04-02 11:43 ` Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 10/17] venet-tap: Adds a "venet" compatible "tap" device to VBUS Gregory Haskins
2009-03-31 18:43 ` Gregory Haskins [this message]
2009-03-31 18:43 ` [RFC PATCH 12/17] venettap: add scatter-gather support Gregory Haskins
2009-03-31 18:43 ` [RFC PATCH 13/17] x86: allow the irq->vector translation to be determined outside of ioapic Gregory Haskins
2009-03-31 19:16 ` Alan Cox
2009-03-31 20:02 ` Gregory Haskins
2009-03-31 18:44 ` [RFC PATCH 14/17] kvm: add a reset capability Gregory Haskins
2009-03-31 19:22 ` Avi Kivity
2009-03-31 20:02 ` Gregory Haskins
2009-03-31 20:18 ` Avi Kivity
2009-03-31 20:37 ` Gregory Haskins
2009-03-31 18:44 ` [RFC PATCH 15/17] kvm: add dynamic IRQ support Gregory Haskins
2009-03-31 19:20 ` Avi Kivity
2009-03-31 19:39 ` Gregory Haskins
2009-03-31 20:13 ` Avi Kivity
2009-03-31 20:32 ` Gregory Haskins
2009-03-31 20:59 ` Avi Kivity
2009-03-31 18:44 ` [RFC PATCH 16/17] kvm: Add VBUS support to the host Gregory Haskins
2009-03-31 18:44 ` [RFC PATCH 17/17] kvm: Add guest-side support for VBUS Gregory Haskins
2009-03-31 20:18 ` [RFC PATCH 00/17] virtual-bus Andi Kleen
2009-04-01 12:03 ` Gregory Haskins
2009-04-01 13:23 ` Andi Kleen
2009-04-01 14:19 ` Gregory Haskins
2009-04-01 14:42 ` Gregory Haskins
2009-04-01 17:01 ` Andi Kleen
2009-04-01 18:45 ` Anthony Liguori
2009-04-01 20:40 ` Chris Wright
2009-04-01 21:11 ` Gregory Haskins
2009-04-01 21:28 ` Chris Wright
2009-04-01 22:10 ` Gregory Haskins
2009-04-02 6:00 ` Chris Wright
2009-04-02 3:11 ` Herbert Xu
2009-04-01 21:09 ` Gregory Haskins
2009-04-02 0:29 ` Anthony Liguori
2009-04-02 3:11 ` Gregory Haskins
2009-04-02 6:51 ` Avi Kivity
2009-04-02 8:52 ` Herbert Xu
2009-04-02 9:02 ` Avi Kivity
2009-04-02 9:16 ` Herbert Xu
2009-04-02 9:27 ` Avi Kivity
2009-04-02 9:29 ` Herbert Xu
2009-04-02 9:33 ` Herbert Xu
2009-04-02 9:38 ` Avi Kivity
2009-04-02 9:41 ` Herbert Xu
2009-04-02 9:43 ` Avi Kivity
2009-04-02 9:44 ` Herbert Xu
2009-04-02 11:06 ` Gregory Haskins
2009-04-02 11:59 ` Avi Kivity
2009-04-02 12:30 ` Gregory Haskins
2009-04-02 12:43 ` Avi Kivity
2009-04-02 13:03 ` Gregory Haskins
2009-04-02 12:13 ` Rusty Russell
2009-04-02 12:50 ` Gregory Haskins
2009-04-02 12:52 ` Gregory Haskins
2009-04-02 13:07 ` Avi Kivity
2009-04-02 13:22 ` Gregory Haskins
2009-04-02 13:27 ` Avi Kivity
2009-04-02 14:05 ` Gregory Haskins
2009-04-02 14:50 ` Herbert Xu
2009-04-02 15:00 ` Avi Kivity
2009-04-02 15:40 ` Herbert Xu
2009-04-02 15:57 ` Avi Kivity
2009-04-02 16:09 ` Herbert Xu
2009-04-02 16:54 ` Avi Kivity
2009-04-02 17:06 ` Herbert Xu
2009-04-02 17:17 ` Herbert Xu
2009-04-03 12:25 ` Avi Kivity
2009-04-02 15:10 ` Michael S. Tsirkin
2009-04-03 4:43 ` Jeremy Fitzhardinge
2009-04-02 10:55 ` Gregory Haskins
2009-04-02 11:48 ` Avi Kivity
2009-04-03 10:58 ` Gerd Hoffmann
2009-04-03 11:03 ` Avi Kivity
2009-04-03 11:12 ` Herbert Xu
2009-04-03 11:46 ` Avi Kivity
2009-04-03 11:48 ` Herbert Xu
2009-04-03 11:54 ` Avi Kivity
2009-04-03 11:55 ` Herbert Xu
2009-04-03 12:02 ` Avi Kivity
2009-04-03 13:05 ` Herbert Xu
2009-04-03 11:18 ` Andi Kleen
2009-04-03 11:34 ` Herbert Xu
2009-04-03 11:46 ` Avi Kivity
2009-04-03 11:28 ` Gregory Haskins
2009-04-02 10:46 ` Gregory Haskins
2009-04-02 11:43 ` Avi Kivity
2009-04-02 12:22 ` Gregory Haskins
2009-04-02 12:42 ` Avi Kivity
2009-04-02 12:54 ` Gregory Haskins
2009-04-02 13:08 ` Avi Kivity
2009-04-02 13:36 ` Gregory Haskins
2009-04-02 13:45 ` Avi Kivity
2009-04-02 14:24 ` Gregory Haskins
2009-04-02 14:32 ` Avi Kivity
2009-04-02 14:41 ` Avi Kivity
2009-04-02 14:49 ` Anthony Liguori
2009-04-02 16:09 ` Anthony Liguori
2009-04-02 16:19 ` Avi Kivity
2009-04-02 18:18 ` Anthony Liguori
2009-04-03 1:11 ` Herbert Xu
2009-04-20 18:02 ` Alex Williamson
2009-04-03 12:03 ` Gregory Haskins
2009-04-03 12:15 ` Avi Kivity
2009-04-03 13:13 ` Gregory Haskins
2009-04-03 13:37 ` Avi Kivity
2009-04-03 16:28 ` Gregory Haskins
2009-04-05 10:00 ` Avi Kivity
2009-04-02 3:09 ` Herbert Xu
2009-04-02 6:46 ` Avi Kivity
2009-04-02 8:54 ` Herbert Xu
2009-04-02 9:03 ` Avi Kivity
2009-04-02 9:05 ` Herbert Xu
2009-04-01 20:29 ` Gregory Haskins
2009-04-01 22:23 ` Andi Kleen
2009-04-01 23:05 ` Gregory Haskins
2009-04-01 6:08 ` Rusty Russell
2009-04-01 11:35 ` Gregory Haskins
2009-04-02 1:24 ` Rusty Russell
2009-04-02 2:27 ` Gregory Haskins
2009-04-01 16:10 ` Anthony Liguori
2009-04-05 3:44 ` Rusty Russell
2009-04-05 8:06 ` Avi Kivity
2009-04-05 14:13 ` Anthony Liguori
2009-04-05 16:10 ` Avi Kivity
2009-04-05 16:45 ` Anthony Liguori
2009-04-02 3:15 ` Herbert Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090331184344.28333.53834.stgit@dev.haskins.net \
--to=ghaskins@novell.com \
--cc=agraf@suse.de \
--cc=anthony@codemonkey.ws \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pmorreale@novell.com \
--cc=pmullaney@novell.com \
--cc=rusty@rustcorp.com.au \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).