aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/virtio_net.c
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@hp.com>2009-02-04 04:02:34 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-04 19:35:11 -0500
commit2a41f71d3bd97dde3305b4e1c43ab0eca46e7c71 (patch)
treed739c170b843ff322ff0897465adbca5cd7041c7 /drivers/net/virtio_net.c
parent073a24364fe6de7eef0a3dec0ec7d48e56624092 (diff)
virtio_net: Add a virtqueue for outbound control commands
This will be used for RX mode, MAC filter table, VLAN filtering, etc... The control transaction consists of one or more "out" sg entries and one or more "in" sg entries. The first out entry contains a header defining the class and command. Additional out entries may provide data for the command. The last in entry provides a status response back from the command. Virtqueues typically run asynchronous, running a callback function when there's data in the channel. We can't readily make use of this in the command paths where we need to use this. Instead, we kick the virtqueue and spin. The kick causes an I/O write, triggering an immediate trap into the hypervisor. Signed-off-by: Alex Williamson <alex.williamson@hp.com> Acked-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r--drivers/net/virtio_net.c68
1 files changed, 65 insertions, 3 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index fe576e75a538..67bb583b7fc9 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -37,10 +37,12 @@ module_param(gso, bool, 0444);
37#define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) 37#define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN)
38#define GOOD_COPY_LEN 128 38#define GOOD_COPY_LEN 128
39 39
40#define VIRTNET_SEND_COMMAND_SG_MAX 0
41
40struct virtnet_info 42struct virtnet_info
41{ 43{
42 struct virtio_device *vdev; 44 struct virtio_device *vdev;
43 struct virtqueue *rvq, *svq; 45 struct virtqueue *rvq, *svq, *cvq;
44 struct net_device *dev; 46 struct net_device *dev;
45 struct napi_struct napi; 47 struct napi_struct napi;
46 unsigned int status; 48 unsigned int status;
@@ -589,6 +591,53 @@ static int virtnet_open(struct net_device *dev)
589 return 0; 591 return 0;
590} 592}
591 593
594/*
595 * Send command via the control virtqueue and check status. Commands
596 * supported by the hypervisor, as indicated by feature bits, should
597 * never fail unless improperly formated.
598 */
599static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
600 struct scatterlist *data, int out, int in)
601{
602 struct scatterlist sg[VIRTNET_SEND_COMMAND_SG_MAX + 2];
603 struct virtio_net_ctrl_hdr ctrl;
604 virtio_net_ctrl_ack status = ~0;
605 unsigned int tmp;
606
607 if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
608 BUG(); /* Caller should know better */
609 return false;
610 }
611
612 BUG_ON(out + in > VIRTNET_SEND_COMMAND_SG_MAX);
613
614 out++; /* Add header */
615 in++; /* Add return status */
616
617 ctrl.class = class;
618 ctrl.cmd = cmd;
619
620 sg_init_table(sg, out + in);
621
622 sg_set_buf(&sg[0], &ctrl, sizeof(ctrl));
623 memcpy(&sg[1], data, sizeof(struct scatterlist) * (out + in - 2));
624 sg_set_buf(&sg[out + in - 1], &status, sizeof(status));
625
626 if (vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) != 0)
627 BUG();
628
629 vi->cvq->vq_ops->kick(vi->cvq);
630
631 /*
632 * Spin for a response, the kick causes an ioport write, trapping
633 * into the hypervisor, so the request should be handled immediately.
634 */
635 while (!vi->cvq->vq_ops->get_buf(vi->cvq, &tmp))
636 cpu_relax();
637
638 return status == VIRTIO_NET_OK;
639}
640
592static int virtnet_close(struct net_device *dev) 641static int virtnet_close(struct net_device *dev)
593{ 642{
594 struct virtnet_info *vi = netdev_priv(dev); 643 struct virtnet_info *vi = netdev_priv(dev);
@@ -752,6 +801,14 @@ static int virtnet_probe(struct virtio_device *vdev)
752 goto free_recv; 801 goto free_recv;
753 } 802 }
754 803
804 if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
805 vi->cvq = vdev->config->find_vq(vdev, 2, NULL);
806 if (IS_ERR(vi->cvq)) {
807 err = PTR_ERR(vi->svq);
808 goto free_send;
809 }
810 }
811
755 /* Initialize our empty receive and send queues. */ 812 /* Initialize our empty receive and send queues. */
756 skb_queue_head_init(&vi->recv); 813 skb_queue_head_init(&vi->recv);
757 skb_queue_head_init(&vi->send); 814 skb_queue_head_init(&vi->send);
@@ -764,7 +821,7 @@ static int virtnet_probe(struct virtio_device *vdev)
764 err = register_netdev(dev); 821 err = register_netdev(dev);
765 if (err) { 822 if (err) {
766 pr_debug("virtio_net: registering device failed\n"); 823 pr_debug("virtio_net: registering device failed\n");
767 goto free_send; 824 goto free_ctrl;
768 } 825 }
769 826
770 /* Last of all, set up some receive buffers. */ 827 /* Last of all, set up some receive buffers. */
@@ -784,6 +841,9 @@ static int virtnet_probe(struct virtio_device *vdev)
784 841
785unregister: 842unregister:
786 unregister_netdev(dev); 843 unregister_netdev(dev);
844free_ctrl:
845 if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
846 vdev->config->del_vq(vi->cvq);
787free_send: 847free_send:
788 vdev->config->del_vq(vi->svq); 848 vdev->config->del_vq(vi->svq);
789free_recv: 849free_recv:
@@ -815,6 +875,8 @@ static void virtnet_remove(struct virtio_device *vdev)
815 875
816 vdev->config->del_vq(vi->svq); 876 vdev->config->del_vq(vi->svq);
817 vdev->config->del_vq(vi->rvq); 877 vdev->config->del_vq(vi->rvq);
878 if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
879 vdev->config->del_vq(vi->cvq);
818 unregister_netdev(vi->dev); 880 unregister_netdev(vi->dev);
819 881
820 while (vi->pages) 882 while (vi->pages)
@@ -834,7 +896,7 @@ static unsigned int features[] = {
834 VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, 896 VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
835 VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, 897 VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
836 VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ 898 VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */
837 VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, 899 VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
838 VIRTIO_F_NOTIFY_ON_EMPTY, 900 VIRTIO_F_NOTIFY_ON_EMPTY,
839}; 901};
840 902