diff options
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index bf7c734259ad..cdc7c90a6a9e 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -591,7 +591,8 @@ static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp) | |||
591 | } while (rq->vq->num_free); | 591 | } while (rq->vq->num_free); |
592 | if (unlikely(rq->num > rq->max)) | 592 | if (unlikely(rq->num > rq->max)) |
593 | rq->max = rq->num; | 593 | rq->max = rq->num; |
594 | virtqueue_kick(rq->vq); | 594 | if (unlikely(!virtqueue_kick(rq->vq))) |
595 | return false; | ||
595 | return !oom; | 596 | return !oom; |
596 | } | 597 | } |
597 | 598 | ||
@@ -797,7 +798,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
797 | err = xmit_skb(sq, skb); | 798 | err = xmit_skb(sq, skb); |
798 | 799 | ||
799 | /* This should not happen! */ | 800 | /* This should not happen! */ |
800 | if (unlikely(err)) { | 801 | if (unlikely(err) || unlikely(!virtqueue_kick(sq->vq))) { |
801 | dev->stats.tx_fifo_errors++; | 802 | dev->stats.tx_fifo_errors++; |
802 | if (net_ratelimit()) | 803 | if (net_ratelimit()) |
803 | dev_warn(&dev->dev, | 804 | dev_warn(&dev->dev, |
@@ -806,7 +807,6 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
806 | kfree_skb(skb); | 807 | kfree_skb(skb); |
807 | return NETDEV_TX_OK; | 808 | return NETDEV_TX_OK; |
808 | } | 809 | } |
809 | virtqueue_kick(sq->vq); | ||
810 | 810 | ||
811 | /* Don't wait up for transmitted skbs to be freed. */ | 811 | /* Don't wait up for transmitted skbs to be freed. */ |
812 | skb_orphan(skb); | 812 | skb_orphan(skb); |
@@ -865,12 +865,14 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, | |||
865 | BUG_ON(virtqueue_add_sgs(vi->cvq, sgs, out_num, in_num, vi, GFP_ATOMIC) | 865 | BUG_ON(virtqueue_add_sgs(vi->cvq, sgs, out_num, in_num, vi, GFP_ATOMIC) |
866 | < 0); | 866 | < 0); |
867 | 867 | ||
868 | virtqueue_kick(vi->cvq); | 868 | if (unlikely(!virtqueue_kick(vi->cvq))) |
869 | return status == VIRTIO_NET_OK; | ||
869 | 870 | ||
870 | /* Spin for a response, the kick causes an ioport write, trapping | 871 | /* Spin for a response, the kick causes an ioport write, trapping |
871 | * into the hypervisor, so the request should be handled immediately. | 872 | * into the hypervisor, so the request should be handled immediately. |
872 | */ | 873 | */ |
873 | while (!virtqueue_get_buf(vi->cvq, &tmp)) | 874 | while (!virtqueue_get_buf(vi->cvq, &tmp) && |
875 | !virtqueue_is_broken(vi->cvq)) | ||
874 | cpu_relax(); | 876 | cpu_relax(); |
875 | 877 | ||
876 | return status == VIRTIO_NET_OK; | 878 | return status == VIRTIO_NET_OK; |
@@ -898,8 +900,13 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p) | |||
898 | return -EINVAL; | 900 | return -EINVAL; |
899 | } | 901 | } |
900 | } else if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) { | 902 | } else if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) { |
901 | vdev->config->set(vdev, offsetof(struct virtio_net_config, mac), | 903 | unsigned int i; |
902 | addr->sa_data, dev->addr_len); | 904 | |
905 | /* Naturally, this has an atomicity problem. */ | ||
906 | for (i = 0; i < dev->addr_len; i++) | ||
907 | virtio_cwrite8(vdev, | ||
908 | offsetof(struct virtio_net_config, mac) + | ||
909 | i, addr->sa_data[i]); | ||
903 | } | 910 | } |
904 | 911 | ||
905 | eth_commit_mac_addr_change(dev, p); | 912 | eth_commit_mac_addr_change(dev, p); |
@@ -1281,9 +1288,8 @@ static void virtnet_config_changed_work(struct work_struct *work) | |||
1281 | if (!vi->config_enable) | 1288 | if (!vi->config_enable) |
1282 | goto done; | 1289 | goto done; |
1283 | 1290 | ||
1284 | if (virtio_config_val(vi->vdev, VIRTIO_NET_F_STATUS, | 1291 | if (virtio_cread_feature(vi->vdev, VIRTIO_NET_F_STATUS, |
1285 | offsetof(struct virtio_net_config, status), | 1292 | struct virtio_net_config, status, &v) < 0) |
1286 | &v) < 0) | ||
1287 | goto done; | 1293 | goto done; |
1288 | 1294 | ||
1289 | if (v & VIRTIO_NET_S_ANNOUNCE) { | 1295 | if (v & VIRTIO_NET_S_ANNOUNCE) { |
@@ -1507,9 +1513,9 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
1507 | u16 max_queue_pairs; | 1513 | u16 max_queue_pairs; |
1508 | 1514 | ||
1509 | /* Find if host supports multiqueue virtio_net device */ | 1515 | /* Find if host supports multiqueue virtio_net device */ |
1510 | err = virtio_config_val(vdev, VIRTIO_NET_F_MQ, | 1516 | err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ, |
1511 | offsetof(struct virtio_net_config, | 1517 | struct virtio_net_config, |
1512 | max_virtqueue_pairs), &max_queue_pairs); | 1518 | max_virtqueue_pairs, &max_queue_pairs); |
1513 | 1519 | ||
1514 | /* We need at least 2 queue's */ | 1520 | /* We need at least 2 queue's */ |
1515 | if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN || | 1521 | if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN || |
@@ -1561,9 +1567,11 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
1561 | dev->vlan_features = dev->features; | 1567 | dev->vlan_features = dev->features; |
1562 | 1568 | ||
1563 | /* Configuration may specify what MAC to use. Otherwise random. */ | 1569 | /* Configuration may specify what MAC to use. Otherwise random. */ |
1564 | if (virtio_config_val_len(vdev, VIRTIO_NET_F_MAC, | 1570 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) |
1565 | offsetof(struct virtio_net_config, mac), | 1571 | virtio_cread_bytes(vdev, |
1566 | dev->dev_addr, dev->addr_len) < 0) | 1572 | offsetof(struct virtio_net_config, mac), |
1573 | dev->dev_addr, dev->addr_len); | ||
1574 | else | ||
1567 | eth_hw_addr_random(dev); | 1575 | eth_hw_addr_random(dev); |
1568 | 1576 | ||
1569 | /* Set up our device-specific information */ | 1577 | /* Set up our device-specific information */ |
@@ -1704,7 +1712,7 @@ static void virtnet_remove(struct virtio_device *vdev) | |||
1704 | free_netdev(vi->dev); | 1712 | free_netdev(vi->dev); |
1705 | } | 1713 | } |
1706 | 1714 | ||
1707 | #ifdef CONFIG_PM | 1715 | #ifdef CONFIG_PM_SLEEP |
1708 | static int virtnet_freeze(struct virtio_device *vdev) | 1716 | static int virtnet_freeze(struct virtio_device *vdev) |
1709 | { | 1717 | { |
1710 | struct virtnet_info *vi = vdev->priv; | 1718 | struct virtnet_info *vi = vdev->priv; |
@@ -1795,7 +1803,7 @@ static struct virtio_driver virtio_net_driver = { | |||
1795 | .probe = virtnet_probe, | 1803 | .probe = virtnet_probe, |
1796 | .remove = virtnet_remove, | 1804 | .remove = virtnet_remove, |
1797 | .config_changed = virtnet_config_changed, | 1805 | .config_changed = virtnet_config_changed, |
1798 | #ifdef CONFIG_PM | 1806 | #ifdef CONFIG_PM_SLEEP |
1799 | .freeze = virtnet_freeze, | 1807 | .freeze = virtnet_freeze, |
1800 | .restore = virtnet_restore, | 1808 | .restore = virtnet_restore, |
1801 | #endif | 1809 | #endif |