diff options
Diffstat (limited to 'drivers/net/xen-netfront.c')
-rw-r--r-- | drivers/net/xen-netfront.c | 106 |
1 files changed, 51 insertions, 55 deletions
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 5c8d9c385be0..db9a763aaa7f 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c | |||
@@ -1140,6 +1140,42 @@ static void xennet_uninit(struct net_device *dev) | |||
1140 | gnttab_free_grant_references(np->gref_rx_head); | 1140 | gnttab_free_grant_references(np->gref_rx_head); |
1141 | } | 1141 | } |
1142 | 1142 | ||
1143 | static u32 xennet_fix_features(struct net_device *dev, u32 features) | ||
1144 | { | ||
1145 | struct netfront_info *np = netdev_priv(dev); | ||
1146 | int val; | ||
1147 | |||
1148 | if (features & NETIF_F_SG) { | ||
1149 | if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-sg", | ||
1150 | "%d", &val) < 0) | ||
1151 | val = 0; | ||
1152 | |||
1153 | if (!val) | ||
1154 | features &= ~NETIF_F_SG; | ||
1155 | } | ||
1156 | |||
1157 | if (features & NETIF_F_TSO) { | ||
1158 | if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, | ||
1159 | "feature-gso-tcpv4", "%d", &val) < 0) | ||
1160 | val = 0; | ||
1161 | |||
1162 | if (!val) | ||
1163 | features &= ~NETIF_F_TSO; | ||
1164 | } | ||
1165 | |||
1166 | return features; | ||
1167 | } | ||
1168 | |||
1169 | static int xennet_set_features(struct net_device *dev, u32 features) | ||
1170 | { | ||
1171 | if (!(features & NETIF_F_SG) && dev->mtu > ETH_DATA_LEN) { | ||
1172 | netdev_info(dev, "Reducing MTU because no SG offload"); | ||
1173 | dev->mtu = ETH_DATA_LEN; | ||
1174 | } | ||
1175 | |||
1176 | return 0; | ||
1177 | } | ||
1178 | |||
1143 | static const struct net_device_ops xennet_netdev_ops = { | 1179 | static const struct net_device_ops xennet_netdev_ops = { |
1144 | .ndo_open = xennet_open, | 1180 | .ndo_open = xennet_open, |
1145 | .ndo_uninit = xennet_uninit, | 1181 | .ndo_uninit = xennet_uninit, |
@@ -1148,6 +1184,8 @@ static const struct net_device_ops xennet_netdev_ops = { | |||
1148 | .ndo_change_mtu = xennet_change_mtu, | 1184 | .ndo_change_mtu = xennet_change_mtu, |
1149 | .ndo_set_mac_address = eth_mac_addr, | 1185 | .ndo_set_mac_address = eth_mac_addr, |
1150 | .ndo_validate_addr = eth_validate_addr, | 1186 | .ndo_validate_addr = eth_validate_addr, |
1187 | .ndo_fix_features = xennet_fix_features, | ||
1188 | .ndo_set_features = xennet_set_features, | ||
1151 | }; | 1189 | }; |
1152 | 1190 | ||
1153 | static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev) | 1191 | static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev) |
@@ -1209,7 +1247,17 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev | |||
1209 | netdev->netdev_ops = &xennet_netdev_ops; | 1247 | netdev->netdev_ops = &xennet_netdev_ops; |
1210 | 1248 | ||
1211 | netif_napi_add(netdev, &np->napi, xennet_poll, 64); | 1249 | netif_napi_add(netdev, &np->napi, xennet_poll, 64); |
1212 | netdev->features = NETIF_F_IP_CSUM; | 1250 | netdev->features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | |
1251 | NETIF_F_GSO_ROBUST; | ||
1252 | netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO; | ||
1253 | |||
1254 | /* | ||
1255 | * Assume that all hw features are available for now. This set | ||
1256 | * will be adjusted by the call to netdev_update_features() in | ||
1257 | * xennet_connect() which is the earliest point where we can | ||
1258 | * negotiate with the backend regarding supported features. | ||
1259 | */ | ||
1260 | netdev->features |= netdev->hw_features; | ||
1213 | 1261 | ||
1214 | SET_ETHTOOL_OPS(netdev, &xennet_ethtool_ops); | 1262 | SET_ETHTOOL_OPS(netdev, &xennet_ethtool_ops); |
1215 | SET_NETDEV_DEV(netdev, &dev->dev); | 1263 | SET_NETDEV_DEV(netdev, &dev->dev); |
@@ -1416,8 +1464,7 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info) | |||
1416 | goto fail; | 1464 | goto fail; |
1417 | 1465 | ||
1418 | err = bind_evtchn_to_irqhandler(info->evtchn, xennet_interrupt, | 1466 | err = bind_evtchn_to_irqhandler(info->evtchn, xennet_interrupt, |
1419 | IRQF_SAMPLE_RANDOM, netdev->name, | 1467 | 0, netdev->name, netdev); |
1420 | netdev); | ||
1421 | if (err < 0) | 1468 | if (err < 0) |
1422 | goto fail; | 1469 | goto fail; |
1423 | netdev->irq = err; | 1470 | netdev->irq = err; |
@@ -1510,54 +1557,6 @@ again: | |||
1510 | return err; | 1557 | return err; |
1511 | } | 1558 | } |
1512 | 1559 | ||
1513 | static int xennet_set_sg(struct net_device *dev, u32 data) | ||
1514 | { | ||
1515 | if (data) { | ||
1516 | struct netfront_info *np = netdev_priv(dev); | ||
1517 | int val; | ||
1518 | |||
1519 | if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-sg", | ||
1520 | "%d", &val) < 0) | ||
1521 | val = 0; | ||
1522 | if (!val) | ||
1523 | return -ENOSYS; | ||
1524 | } else if (dev->mtu > ETH_DATA_LEN) | ||
1525 | dev->mtu = ETH_DATA_LEN; | ||
1526 | |||
1527 | return ethtool_op_set_sg(dev, data); | ||
1528 | } | ||
1529 | |||
1530 | static int xennet_set_tso(struct net_device *dev, u32 data) | ||
1531 | { | ||
1532 | if (data) { | ||
1533 | struct netfront_info *np = netdev_priv(dev); | ||
1534 | int val; | ||
1535 | |||
1536 | if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, | ||
1537 | "feature-gso-tcpv4", "%d", &val) < 0) | ||
1538 | val = 0; | ||
1539 | if (!val) | ||
1540 | return -ENOSYS; | ||
1541 | } | ||
1542 | |||
1543 | return ethtool_op_set_tso(dev, data); | ||
1544 | } | ||
1545 | |||
1546 | static void xennet_set_features(struct net_device *dev) | ||
1547 | { | ||
1548 | /* Turn off all GSO bits except ROBUST. */ | ||
1549 | dev->features &= ~NETIF_F_GSO_MASK; | ||
1550 | dev->features |= NETIF_F_GSO_ROBUST; | ||
1551 | xennet_set_sg(dev, 0); | ||
1552 | |||
1553 | /* We need checksum offload to enable scatter/gather and TSO. */ | ||
1554 | if (!(dev->features & NETIF_F_IP_CSUM)) | ||
1555 | return; | ||
1556 | |||
1557 | if (!xennet_set_sg(dev, 1)) | ||
1558 | xennet_set_tso(dev, 1); | ||
1559 | } | ||
1560 | |||
1561 | static int xennet_connect(struct net_device *dev) | 1560 | static int xennet_connect(struct net_device *dev) |
1562 | { | 1561 | { |
1563 | struct netfront_info *np = netdev_priv(dev); | 1562 | struct netfront_info *np = netdev_priv(dev); |
@@ -1582,7 +1581,7 @@ static int xennet_connect(struct net_device *dev) | |||
1582 | if (err) | 1581 | if (err) |
1583 | return err; | 1582 | return err; |
1584 | 1583 | ||
1585 | xennet_set_features(dev); | 1584 | netdev_update_features(dev); |
1586 | 1585 | ||
1587 | spin_lock_bh(&np->rx_lock); | 1586 | spin_lock_bh(&np->rx_lock); |
1588 | spin_lock_irq(&np->tx_lock); | 1587 | spin_lock_irq(&np->tx_lock); |
@@ -1710,9 +1709,6 @@ static void xennet_get_strings(struct net_device *dev, u32 stringset, u8 * data) | |||
1710 | 1709 | ||
1711 | static const struct ethtool_ops xennet_ethtool_ops = | 1710 | static const struct ethtool_ops xennet_ethtool_ops = |
1712 | { | 1711 | { |
1713 | .set_tx_csum = ethtool_op_set_tx_csum, | ||
1714 | .set_sg = xennet_set_sg, | ||
1715 | .set_tso = xennet_set_tso, | ||
1716 | .get_link = ethtool_op_get_link, | 1712 | .get_link = ethtool_op_get_link, |
1717 | 1713 | ||
1718 | .get_sset_count = xennet_get_sset_count, | 1714 | .get_sset_count = xennet_get_sset_count, |