diff options
Diffstat (limited to 'drivers/net/xen-netback/interface.c')
-rw-r--r-- | drivers/net/xen-netback/interface.c | 47 |
1 files changed, 23 insertions, 24 deletions
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 625c6f49cfba..b78ee10a956a 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c | |||
@@ -214,10 +214,14 @@ 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->csum) | 219 | if (~(vif->gso_mask | vif->gso_prefix_mask) & GSO_BIT(TCPV6)) |
220 | features &= ~NETIF_F_TSO6; | ||
221 | if (!vif->ip_csum) | ||
220 | features &= ~NETIF_F_IP_CSUM; | 222 | features &= ~NETIF_F_IP_CSUM; |
223 | if (!vif->ipv6_csum) | ||
224 | features &= ~NETIF_F_IPV6_CSUM; | ||
221 | 225 | ||
222 | return features; | 226 | return features; |
223 | } | 227 | } |
@@ -306,18 +310,19 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, | |||
306 | vif->domid = domid; | 310 | vif->domid = domid; |
307 | vif->handle = handle; | 311 | vif->handle = handle; |
308 | vif->can_sg = 1; | 312 | vif->can_sg = 1; |
309 | vif->csum = 1; | 313 | vif->ip_csum = 1; |
310 | vif->dev = dev; | 314 | vif->dev = dev; |
311 | 315 | ||
312 | vif->credit_bytes = vif->remaining_credit = ~0UL; | 316 | vif->credit_bytes = vif->remaining_credit = ~0UL; |
313 | vif->credit_usec = 0UL; | 317 | vif->credit_usec = 0UL; |
314 | init_timer(&vif->credit_timeout); | 318 | init_timer(&vif->credit_timeout); |
315 | /* Initialize 'expires' now: it's used to track the credit window. */ | 319 | vif->credit_window_start = get_jiffies_64(); |
316 | vif->credit_timeout.expires = jiffies; | ||
317 | 320 | ||
318 | dev->netdev_ops = &xenvif_netdev_ops; | 321 | dev->netdev_ops = &xenvif_netdev_ops; |
319 | dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; | 322 | dev->hw_features = NETIF_F_SG | |
320 | dev->features = dev->hw_features; | 323 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | |
324 | NETIF_F_TSO | NETIF_F_TSO6; | ||
325 | dev->features = dev->hw_features | NETIF_F_RXCSUM; | ||
321 | SET_ETHTOOL_OPS(dev, &xenvif_ethtool_ops); | 326 | SET_ETHTOOL_OPS(dev, &xenvif_ethtool_ops); |
322 | 327 | ||
323 | dev->tx_queue_len = XENVIF_QUEUE_LENGTH; | 328 | dev->tx_queue_len = XENVIF_QUEUE_LENGTH; |
@@ -353,6 +358,9 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, | |||
353 | } | 358 | } |
354 | 359 | ||
355 | netdev_dbg(dev, "Successfully created xenvif\n"); | 360 | netdev_dbg(dev, "Successfully created xenvif\n"); |
361 | |||
362 | __module_get(THIS_MODULE); | ||
363 | |||
356 | return vif; | 364 | return vif; |
357 | } | 365 | } |
358 | 366 | ||
@@ -366,8 +374,6 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, | |||
366 | if (vif->tx_irq) | 374 | if (vif->tx_irq) |
367 | return 0; | 375 | return 0; |
368 | 376 | ||
369 | __module_get(THIS_MODULE); | ||
370 | |||
371 | err = xenvif_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref); | 377 | err = xenvif_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref); |
372 | if (err < 0) | 378 | if (err < 0) |
373 | goto err; | 379 | goto err; |
@@ -406,7 +412,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, | |||
406 | 412 | ||
407 | init_waitqueue_head(&vif->wq); | 413 | init_waitqueue_head(&vif->wq); |
408 | vif->task = kthread_create(xenvif_kthread, | 414 | vif->task = kthread_create(xenvif_kthread, |
409 | (void *)vif, vif->dev->name); | 415 | (void *)vif, "%s", vif->dev->name); |
410 | if (IS_ERR(vif->task)) { | 416 | if (IS_ERR(vif->task)) { |
411 | pr_warn("Could not allocate kthread for %s\n", vif->dev->name); | 417 | pr_warn("Could not allocate kthread for %s\n", vif->dev->name); |
412 | err = PTR_ERR(vif->task); | 418 | err = PTR_ERR(vif->task); |
@@ -452,12 +458,6 @@ void xenvif_carrier_off(struct xenvif *vif) | |||
452 | 458 | ||
453 | void xenvif_disconnect(struct xenvif *vif) | 459 | void xenvif_disconnect(struct xenvif *vif) |
454 | { | 460 | { |
455 | /* Disconnect funtion might get called by generic framework | ||
456 | * even before vif connects, so we need to check if we really | ||
457 | * need to do a module_put. | ||
458 | */ | ||
459 | int need_module_put = 0; | ||
460 | |||
461 | if (netif_carrier_ok(vif->dev)) | 461 | if (netif_carrier_ok(vif->dev)) |
462 | xenvif_carrier_off(vif); | 462 | xenvif_carrier_off(vif); |
463 | 463 | ||
@@ -468,23 +468,22 @@ void xenvif_disconnect(struct xenvif *vif) | |||
468 | unbind_from_irqhandler(vif->tx_irq, vif); | 468 | unbind_from_irqhandler(vif->tx_irq, vif); |
469 | unbind_from_irqhandler(vif->rx_irq, vif); | 469 | unbind_from_irqhandler(vif->rx_irq, vif); |
470 | } | 470 | } |
471 | /* vif->irq is valid, we had a module_get in | 471 | vif->tx_irq = 0; |
472 | * xenvif_connect. | ||
473 | */ | ||
474 | need_module_put = 1; | ||
475 | } | 472 | } |
476 | 473 | ||
477 | if (vif->task) | 474 | if (vif->task) |
478 | kthread_stop(vif->task); | 475 | kthread_stop(vif->task); |
479 | 476 | ||
477 | xenvif_unmap_frontend_rings(vif); | ||
478 | } | ||
479 | |||
480 | void xenvif_free(struct xenvif *vif) | ||
481 | { | ||
480 | netif_napi_del(&vif->napi); | 482 | netif_napi_del(&vif->napi); |
481 | 483 | ||
482 | unregister_netdev(vif->dev); | 484 | unregister_netdev(vif->dev); |
483 | 485 | ||
484 | xenvif_unmap_frontend_rings(vif); | ||
485 | |||
486 | free_netdev(vif->dev); | 486 | free_netdev(vif->dev); |
487 | 487 | ||
488 | if (need_module_put) | 488 | module_put(THIS_MODULE); |
489 | module_put(THIS_MODULE); | ||
490 | } | 489 | } |