aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/virtio_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r--drivers/net/virtio_net.c44
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
1708static int virtnet_freeze(struct virtio_device *vdev) 1716static 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