aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/xen-netback/common.h9
-rw-r--r--drivers/net/xen-netback/interface.c6
-rw-r--r--drivers/net/xen-netback/netback.c48
-rw-r--r--drivers/net/xen-netback/xenbus.c29
-rw-r--r--include/xen/interface/io/netif.h1
5 files changed, 77 insertions, 16 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index b4a9a3c844b2..55b8dec86233 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -87,9 +87,13 @@ struct pending_tx_info {
87struct xenvif_rx_meta { 87struct xenvif_rx_meta {
88 int id; 88 int id;
89 int size; 89 int size;
90 int gso_type;
90 int gso_size; 91 int gso_size;
91}; 92};
92 93
94#define GSO_BIT(type) \
95 (1 << XEN_NETIF_GSO_TYPE_ ## type)
96
93/* Discriminate from any valid pending_idx value. */ 97/* Discriminate from any valid pending_idx value. */
94#define INVALID_PENDING_IDX 0xFFFF 98#define INVALID_PENDING_IDX 0xFFFF
95 99
@@ -150,9 +154,10 @@ struct xenvif {
150 u8 fe_dev_addr[6]; 154 u8 fe_dev_addr[6];
151 155
152 /* Frontend feature information. */ 156 /* Frontend feature information. */
157 int gso_mask;
158 int gso_prefix_mask;
159
153 u8 can_sg:1; 160 u8 can_sg:1;
154 u8 gso:1;
155 u8 gso_prefix:1;
156 u8 ip_csum:1; 161 u8 ip_csum:1;
157 u8 ipv6_csum:1; 162 u8 ipv6_csum:1;
158 163
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index cb0d8ea3d9f2..e4aa26748f80 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -214,8 +214,10 @@ static netdev_features_t xenvif_fix_features(struct net_device *dev,
214 214
215 if (!vif->can_sg) 215 if (!vif->can_sg)
216 features &= ~NETIF_F_SG; 216 features &= ~NETIF_F_SG;
217 if (!vif->gso && !vif->gso_prefix) 217 if (~(vif->gso_mask | vif->gso_prefix_mask) & GSO_BIT(TCPV4))
218 features &= ~NETIF_F_TSO; 218 features &= ~NETIF_F_TSO;
219 if (~(vif->gso_mask | vif->gso_prefix_mask) & GSO_BIT(TCPV6))
220 features &= ~NETIF_F_TSO6;
219 if (!vif->ip_csum) 221 if (!vif->ip_csum)
220 features &= ~NETIF_F_IP_CSUM; 222 features &= ~NETIF_F_IP_CSUM;
221 if (!vif->ipv6_csum) 223 if (!vif->ipv6_csum)
@@ -320,7 +322,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
320 dev->netdev_ops = &xenvif_netdev_ops; 322 dev->netdev_ops = &xenvif_netdev_ops;
321 dev->hw_features = NETIF_F_SG | 323 dev->hw_features = NETIF_F_SG |
322 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | 324 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
323 NETIF_F_TSO; 325 NETIF_F_TSO | NETIF_F_TSO6;
324 dev->features = dev->hw_features | NETIF_F_RXCSUM; 326 dev->features = dev->hw_features | NETIF_F_RXCSUM;
325 SET_ETHTOOL_OPS(dev, &xenvif_ethtool_ops); 327 SET_ETHTOOL_OPS(dev, &xenvif_ethtool_ops);
326 328
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 0e327d46a139..828fdab4f1a4 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -142,7 +142,7 @@ static int max_required_rx_slots(struct xenvif *vif)
142 int max = DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE); 142 int max = DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE);
143 143
144 /* XXX FIXME: RX path dependent on MAX_SKB_FRAGS */ 144 /* XXX FIXME: RX path dependent on MAX_SKB_FRAGS */
145 if (vif->can_sg || vif->gso || vif->gso_prefix) 145 if (vif->can_sg || vif->gso_mask || vif->gso_prefix_mask)
146 max += MAX_SKB_FRAGS + 1; /* extra_info + frags */ 146 max += MAX_SKB_FRAGS + 1; /* extra_info + frags */
147 147
148 return max; 148 return max;
@@ -314,6 +314,7 @@ static struct xenvif_rx_meta *get_next_rx_buffer(struct xenvif *vif,
314 req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++); 314 req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
315 315
316 meta = npo->meta + npo->meta_prod++; 316 meta = npo->meta + npo->meta_prod++;
317 meta->gso_type = XEN_NETIF_GSO_TYPE_NONE;
317 meta->gso_size = 0; 318 meta->gso_size = 0;
318 meta->size = 0; 319 meta->size = 0;
319 meta->id = req->id; 320 meta->id = req->id;
@@ -336,6 +337,7 @@ static void xenvif_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb,
336 struct gnttab_copy *copy_gop; 337 struct gnttab_copy *copy_gop;
337 struct xenvif_rx_meta *meta; 338 struct xenvif_rx_meta *meta;
338 unsigned long bytes; 339 unsigned long bytes;
340 int gso_type;
339 341
340 /* Data must not cross a page boundary. */ 342 /* Data must not cross a page boundary. */
341 BUG_ON(size + offset > PAGE_SIZE<<compound_order(page)); 343 BUG_ON(size + offset > PAGE_SIZE<<compound_order(page));
@@ -394,7 +396,14 @@ static void xenvif_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb,
394 } 396 }
395 397
396 /* Leave a gap for the GSO descriptor. */ 398 /* Leave a gap for the GSO descriptor. */
397 if (*head && skb_shinfo(skb)->gso_size && !vif->gso_prefix) 399 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
400 gso_type = XEN_NETIF_GSO_TYPE_TCPV4;
401 else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
402 gso_type = XEN_NETIF_GSO_TYPE_TCPV6;
403 else
404 gso_type = XEN_NETIF_GSO_TYPE_NONE;
405
406 if (*head && ((1 << gso_type) & vif->gso_mask))
398 vif->rx.req_cons++; 407 vif->rx.req_cons++;
399 408
400 *head = 0; /* There must be something in this buffer now. */ 409 *head = 0; /* There must be something in this buffer now. */
@@ -425,14 +434,28 @@ static int xenvif_gop_skb(struct sk_buff *skb,
425 unsigned char *data; 434 unsigned char *data;
426 int head = 1; 435 int head = 1;
427 int old_meta_prod; 436 int old_meta_prod;
437 int gso_type;
438 int gso_size;
428 439
429 old_meta_prod = npo->meta_prod; 440 old_meta_prod = npo->meta_prod;
430 441
442 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) {
443 gso_type = XEN_NETIF_GSO_TYPE_TCPV4;
444 gso_size = skb_shinfo(skb)->gso_size;
445 } else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
446 gso_type = XEN_NETIF_GSO_TYPE_TCPV6;
447 gso_size = skb_shinfo(skb)->gso_size;
448 } else {
449 gso_type = XEN_NETIF_GSO_TYPE_NONE;
450 gso_size = 0;
451 }
452
431 /* Set up a GSO prefix descriptor, if necessary */ 453 /* Set up a GSO prefix descriptor, if necessary */
432 if (skb_shinfo(skb)->gso_size && vif->gso_prefix) { 454 if ((1 << skb_shinfo(skb)->gso_type) & vif->gso_prefix_mask) {
433 req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++); 455 req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
434 meta = npo->meta + npo->meta_prod++; 456 meta = npo->meta + npo->meta_prod++;
435 meta->gso_size = skb_shinfo(skb)->gso_size; 457 meta->gso_type = gso_type;
458 meta->gso_size = gso_size;
436 meta->size = 0; 459 meta->size = 0;
437 meta->id = req->id; 460 meta->id = req->id;
438 } 461 }
@@ -440,10 +463,13 @@ static int xenvif_gop_skb(struct sk_buff *skb,
440 req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++); 463 req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
441 meta = npo->meta + npo->meta_prod++; 464 meta = npo->meta + npo->meta_prod++;
442 465
443 if (!vif->gso_prefix) 466 if ((1 << gso_type) & vif->gso_mask) {
444 meta->gso_size = skb_shinfo(skb)->gso_size; 467 meta->gso_type = gso_type;
445 else 468 meta->gso_size = gso_size;
469 } else {
470 meta->gso_type = XEN_NETIF_GSO_TYPE_NONE;
446 meta->gso_size = 0; 471 meta->gso_size = 0;
472 }
447 473
448 meta->size = 0; 474 meta->size = 0;
449 meta->id = req->id; 475 meta->id = req->id;
@@ -589,7 +615,8 @@ void xenvif_rx_action(struct xenvif *vif)
589 615
590 vif = netdev_priv(skb->dev); 616 vif = netdev_priv(skb->dev);
591 617
592 if (vif->meta[npo.meta_cons].gso_size && vif->gso_prefix) { 618 if ((1 << vif->meta[npo.meta_cons].gso_type) &
619 vif->gso_prefix_mask) {
593 resp = RING_GET_RESPONSE(&vif->rx, 620 resp = RING_GET_RESPONSE(&vif->rx,
594 vif->rx.rsp_prod_pvt++); 621 vif->rx.rsp_prod_pvt++);
595 622
@@ -626,7 +653,8 @@ void xenvif_rx_action(struct xenvif *vif)
626 vif->meta[npo.meta_cons].size, 653 vif->meta[npo.meta_cons].size,
627 flags); 654 flags);
628 655
629 if (vif->meta[npo.meta_cons].gso_size && !vif->gso_prefix) { 656 if ((1 << vif->meta[npo.meta_cons].gso_type) &
657 vif->gso_mask) {
630 struct xen_netif_extra_info *gso = 658 struct xen_netif_extra_info *gso =
631 (struct xen_netif_extra_info *) 659 (struct xen_netif_extra_info *)
632 RING_GET_RESPONSE(&vif->rx, 660 RING_GET_RESPONSE(&vif->rx,
@@ -634,8 +662,8 @@ void xenvif_rx_action(struct xenvif *vif)
634 662
635 resp->flags |= XEN_NETRXF_extra_info; 663 resp->flags |= XEN_NETRXF_extra_info;
636 664
665 gso->u.gso.type = vif->meta[npo.meta_cons].gso_type;
637 gso->u.gso.size = vif->meta[npo.meta_cons].gso_size; 666 gso->u.gso.size = vif->meta[npo.meta_cons].gso_size;
638 gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
639 gso->u.gso.pad = 0; 667 gso->u.gso.pad = 0;
640 gso->u.gso.features = 0; 668 gso->u.gso.features = 0;
641 669
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 02cb00bebdc9..f0358992b04f 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -577,15 +577,40 @@ static int connect_rings(struct backend_info *be)
577 val = 0; 577 val = 0;
578 vif->can_sg = !!val; 578 vif->can_sg = !!val;
579 579
580 vif->gso_mask = 0;
581 vif->gso_prefix_mask = 0;
582
580 if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4", 583 if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4",
581 "%d", &val) < 0) 584 "%d", &val) < 0)
582 val = 0; 585 val = 0;
583 vif->gso = !!val; 586 if (val)
587 vif->gso_mask |= GSO_BIT(TCPV4);
584 588
585 if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4-prefix", 589 if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4-prefix",
586 "%d", &val) < 0) 590 "%d", &val) < 0)
587 val = 0; 591 val = 0;
588 vif->gso_prefix = !!val; 592 if (val)
593 vif->gso_prefix_mask |= GSO_BIT(TCPV4);
594
595 if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv6",
596 "%d", &val) < 0)
597 val = 0;
598 if (val)
599 vif->gso_mask |= GSO_BIT(TCPV6);
600
601 if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv6-prefix",
602 "%d", &val) < 0)
603 val = 0;
604 if (val)
605 vif->gso_prefix_mask |= GSO_BIT(TCPV6);
606
607 if (vif->gso_mask & vif->gso_prefix_mask) {
608 xenbus_dev_fatal(dev, err,
609 "%s: gso and gso prefix flags are not "
610 "mutually exclusive",
611 dev->otherend);
612 return -EOPNOTSUPP;
613 }
589 614
590 if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload", 615 if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
591 "%d", &val) < 0) 616 "%d", &val) < 0)
diff --git a/include/xen/interface/io/netif.h b/include/xen/interface/io/netif.h
index 5e766ebe77f6..c50061db6098 100644
--- a/include/xen/interface/io/netif.h
+++ b/include/xen/interface/io/netif.h
@@ -110,6 +110,7 @@ struct xen_netif_tx_request {
110#define XEN_NETIF_EXTRA_FLAG_MORE (1U<<_XEN_NETIF_EXTRA_FLAG_MORE) 110#define XEN_NETIF_EXTRA_FLAG_MORE (1U<<_XEN_NETIF_EXTRA_FLAG_MORE)
111 111
112/* GSO types */ 112/* GSO types */
113#define XEN_NETIF_GSO_TYPE_NONE (0)
113#define XEN_NETIF_GSO_TYPE_TCPV4 (1) 114#define XEN_NETIF_GSO_TYPE_TCPV4 (1)
114#define XEN_NETIF_GSO_TYPE_TCPV6 (2) 115#define XEN_NETIF_GSO_TYPE_TCPV6 (2)
115 116