Hi:
[NET] front: Transmit TSO packets if supported
This patch adds TSO transmission support to the frontend. This also fixes
a bug where SG may not be turned off correctly when migrating to an old
host.
Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@xxxxxxxxxxxxxxxxxxx>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff -r fb922826baef -r ea33ffdb9973
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Jun 30
22:28:09 2006 +1000
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Jun 30
22:44:18 2006 +1000
@@ -463,7 +463,7 @@ static int network_open(struct net_devic
static inline int netfront_tx_slot_available(struct netfront_info *np)
{
- return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 1;
+ return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 2;
}
static inline void network_maybe_wake_tx(struct net_device *dev)
@@ -491,7 +491,13 @@ static void network_tx_buf_gc(struct net
rmb(); /* Ensure we see responses up to 'rp'. */
for (cons = np->tx.rsp_cons; cons != prod; cons++) {
- id = RING_GET_RESPONSE(&np->tx, cons)->id;
+ struct netif_tx_response *txrsp;
+
+ txrsp = RING_GET_RESPONSE(&np->tx, cons);
+ if (txrsp->status == NETIF_RSP_NULL)
+ continue;
+
+ id = txrsp->id;
skb = np->tx_skbs[id];
if (unlikely(gnttab_query_foreign_access(
np->grant_tx_ref[id]) != 0)) {
@@ -719,6 +725,7 @@ static int network_start_xmit(struct sk_
unsigned short id;
struct netfront_info *np = netdev_priv(dev);
struct netif_tx_request *tx;
+ struct netif_tx_extra *txtra;
char *data = skb->data;
RING_IDX i;
grant_ref_t ref;
@@ -739,7 +746,8 @@ static int network_start_xmit(struct sk_
spin_lock_irq(&np->tx_lock);
if (unlikely(!netif_carrier_ok(dev) ||
- (frags > 1 && !xennet_can_sg(dev)))) {
+ (frags > 1 && !xennet_can_sg(dev)) ||
+ netif_needs_gso(dev, skb))) {
spin_unlock_irq(&np->tx_lock);
goto drop;
}
@@ -762,10 +770,30 @@ static int network_start_xmit(struct sk_
tx->size = len;
tx->flags = 0;
+ txtra = NULL;
+
if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
if (skb->proto_data_valid) /* remote but checksummed? */
tx->flags |= NETTXF_data_validated;
+
+ if (skb_shinfo(skb)->gso_size) {
+ struct netif_tx_extra *gso =
+ (struct netif_tx_extra *)RING_GET_REQUEST(&np->tx, ++i);
+
+ if (txtra)
+ txtra->flags |= XEN_NETIF_TXTRA_MORE;
+ else
+ tx->flags |= NETTXF_extra_info;
+
+ gso->gso.size = skb_shinfo(skb)->gso_size;
+ gso->gso.type =
+ xen_gso_type_linux2xen(skb_shinfo(skb)->gso_type);
+
+ gso->type = XEN_NETIF_TXTRA_TYPE_GSO;
+ gso->flags = 0;
+ txtra = gso;
+ }
np->tx.req_prod_pvt = i + 1;
@@ -1065,9 +1093,47 @@ static int xennet_set_sg(struct net_devi
return ethtool_op_set_sg(dev, data);
}
+static int xennet_set_tso(struct net_device *dev, u32 data)
+{
+ if (data) {
+ struct netfront_info *np = netdev_priv(dev);
+ int val;
+
+ if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-gso",
+ "%d", &val) < 0)
+ val = 0;
+ if (!(val & XEN_GSO_TCPV4))
+ return -ENOSYS;
+ }
+
+ return ethtool_op_set_tso(dev, data);
+}
+
+static void xennet_set_gso(struct net_device *dev)
+{
+ struct netfront_info *np = netdev_priv(dev);
+ int allowed_types = SKB_GSO_TCPV4 | SKB_GSO_DODGY;
+ int val;
+
+ if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-gso",
+ "%d", &val) < 0)
+ return;
+
+ /* Filter out things we don't understand. */
+ val = xen_gso_type_xen2linux(val) & allowed_types;
+
+ /* Turn on the advertised bits. */
+ dev->features |= val << NETIF_F_GSO_SHIFT;
+}
+
static void xennet_set_features(struct net_device *dev)
{
- xennet_set_sg(dev, 1);
+ /* Turn off all negotiated bits. */
+ dev->features &= (1 << NETIF_F_GSO_SHIFT) - 1;
+ xennet_set_sg(dev, 0);
+
+ if (!xennet_set_sg(dev, 1))
+ xennet_set_gso(dev);
}
static void network_connect(struct net_device *dev)
@@ -1148,6 +1214,8 @@ static struct ethtool_ops network_ethtoo
.set_tx_csum = ethtool_op_set_tx_csum,
.get_sg = ethtool_op_get_sg,
.set_sg = xennet_set_sg,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = xennet_set_tso,
};
#ifdef CONFIG_SYSFS
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|