diff options
| -rw-r--r-- | drivers/net/xen-netback/common.h | 9 | ||||
| -rw-r--r-- | drivers/net/xen-netback/interface.c | 6 | ||||
| -rw-r--r-- | drivers/net/xen-netback/netback.c | 48 | ||||
| -rw-r--r-- | drivers/net/xen-netback/xenbus.c | 29 | ||||
| -rw-r--r-- | include/xen/interface/io/netif.h | 1 |
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 { | |||
| 87 | struct xenvif_rx_meta { | 87 | struct 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 | ||
