diff options
author | Len Brown <len.brown@intel.com> | 2009-04-05 02:14:15 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-04-05 02:14:15 -0400 |
commit | 478c6a43fcbc6c11609f8cee7c7b57223907754f (patch) | |
tree | a7f7952099da60d33032aed6de9c0c56c9f8779e /drivers/net/virtio_net.c | |
parent | 8a3f257c704e02aee9869decd069a806b45be3f1 (diff) | |
parent | 6bb597507f9839b13498781e481f5458aea33620 (diff) |
Merge branch 'linus' into release
Conflicts:
arch/x86/kernel/cpu/cpufreq/longhaul.c
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 242 |
1 files changed, 231 insertions, 11 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index e67d16c2e5f3..a6f1e19159d8 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -37,12 +37,15 @@ 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 2 | ||
41 | |||
40 | struct virtnet_info | 42 | struct 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; |
48 | unsigned int status; | ||
46 | 49 | ||
47 | /* The skb we couldn't send because buffers were full. */ | 50 | /* The skb we couldn't send because buffers were full. */ |
48 | struct sk_buff *last_xmit_skb; | 51 | struct sk_buff *last_xmit_skb; |
@@ -375,9 +378,9 @@ static void skb_recv_done(struct virtqueue *rvq) | |||
375 | { | 378 | { |
376 | struct virtnet_info *vi = rvq->vdev->priv; | 379 | struct virtnet_info *vi = rvq->vdev->priv; |
377 | /* Schedule NAPI, Suppress further interrupts if successful. */ | 380 | /* Schedule NAPI, Suppress further interrupts if successful. */ |
378 | if (netif_rx_schedule_prep(&vi->napi)) { | 381 | if (napi_schedule_prep(&vi->napi)) { |
379 | rvq->vq_ops->disable_cb(rvq); | 382 | rvq->vq_ops->disable_cb(rvq); |
380 | __netif_rx_schedule(&vi->napi); | 383 | __napi_schedule(&vi->napi); |
381 | } | 384 | } |
382 | } | 385 | } |
383 | 386 | ||
@@ -403,11 +406,11 @@ again: | |||
403 | 406 | ||
404 | /* Out of packets? */ | 407 | /* Out of packets? */ |
405 | if (received < budget) { | 408 | if (received < budget) { |
406 | netif_rx_complete(napi); | 409 | napi_complete(napi); |
407 | if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq)) | 410 | if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq)) |
408 | && napi_schedule_prep(napi)) { | 411 | && napi_schedule_prep(napi)) { |
409 | vi->rvq->vq_ops->disable_cb(vi->rvq); | 412 | vi->rvq->vq_ops->disable_cb(vi->rvq); |
410 | __netif_rx_schedule(napi); | 413 | __napi_schedule(napi); |
411 | goto again; | 414 | goto again; |
412 | } | 415 | } |
413 | } | 416 | } |
@@ -562,6 +565,22 @@ stop_queue: | |||
562 | goto done; | 565 | goto done; |
563 | } | 566 | } |
564 | 567 | ||
568 | static int virtnet_set_mac_address(struct net_device *dev, void *p) | ||
569 | { | ||
570 | struct virtnet_info *vi = netdev_priv(dev); | ||
571 | struct virtio_device *vdev = vi->vdev; | ||
572 | int ret; | ||
573 | |||
574 | ret = eth_mac_addr(dev, p); | ||
575 | if (ret) | ||
576 | return ret; | ||
577 | |||
578 | vdev->config->set(vdev, offsetof(struct virtio_net_config, mac), | ||
579 | dev->dev_addr, dev->addr_len); | ||
580 | |||
581 | return 0; | ||
582 | } | ||
583 | |||
565 | #ifdef CONFIG_NET_POLL_CONTROLLER | 584 | #ifdef CONFIG_NET_POLL_CONTROLLER |
566 | static void virtnet_netpoll(struct net_device *dev) | 585 | static void virtnet_netpoll(struct net_device *dev) |
567 | { | 586 | { |
@@ -581,13 +600,60 @@ static int virtnet_open(struct net_device *dev) | |||
581 | * won't get another interrupt, so process any outstanding packets | 600 | * won't get another interrupt, so process any outstanding packets |
582 | * now. virtnet_poll wants re-enable the queue, so we disable here. | 601 | * now. virtnet_poll wants re-enable the queue, so we disable here. |
583 | * We synchronize against interrupts via NAPI_STATE_SCHED */ | 602 | * We synchronize against interrupts via NAPI_STATE_SCHED */ |
584 | if (netif_rx_schedule_prep(&vi->napi)) { | 603 | if (napi_schedule_prep(&vi->napi)) { |
585 | vi->rvq->vq_ops->disable_cb(vi->rvq); | 604 | vi->rvq->vq_ops->disable_cb(vi->rvq); |
586 | __netif_rx_schedule(&vi->napi); | 605 | __napi_schedule(&vi->napi); |
587 | } | 606 | } |
588 | return 0; | 607 | return 0; |
589 | } | 608 | } |
590 | 609 | ||
610 | /* | ||
611 | * Send command via the control virtqueue and check status. Commands | ||
612 | * supported by the hypervisor, as indicated by feature bits, should | ||
613 | * never fail unless improperly formated. | ||
614 | */ | ||
615 | static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, | ||
616 | struct scatterlist *data, int out, int in) | ||
617 | { | ||
618 | struct scatterlist sg[VIRTNET_SEND_COMMAND_SG_MAX + 2]; | ||
619 | struct virtio_net_ctrl_hdr ctrl; | ||
620 | virtio_net_ctrl_ack status = ~0; | ||
621 | unsigned int tmp; | ||
622 | |||
623 | if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) { | ||
624 | BUG(); /* Caller should know better */ | ||
625 | return false; | ||
626 | } | ||
627 | |||
628 | BUG_ON(out + in > VIRTNET_SEND_COMMAND_SG_MAX); | ||
629 | |||
630 | out++; /* Add header */ | ||
631 | in++; /* Add return status */ | ||
632 | |||
633 | ctrl.class = class; | ||
634 | ctrl.cmd = cmd; | ||
635 | |||
636 | sg_init_table(sg, out + in); | ||
637 | |||
638 | sg_set_buf(&sg[0], &ctrl, sizeof(ctrl)); | ||
639 | memcpy(&sg[1], data, sizeof(struct scatterlist) * (out + in - 2)); | ||
640 | sg_set_buf(&sg[out + in - 1], &status, sizeof(status)); | ||
641 | |||
642 | if (vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) != 0) | ||
643 | BUG(); | ||
644 | |||
645 | vi->cvq->vq_ops->kick(vi->cvq); | ||
646 | |||
647 | /* | ||
648 | * Spin for a response, the kick causes an ioport write, trapping | ||
649 | * into the hypervisor, so the request should be handled immediately. | ||
650 | */ | ||
651 | while (!vi->cvq->vq_ops->get_buf(vi->cvq, &tmp)) | ||
652 | cpu_relax(); | ||
653 | |||
654 | return status == VIRTIO_NET_OK; | ||
655 | } | ||
656 | |||
591 | static int virtnet_close(struct net_device *dev) | 657 | static int virtnet_close(struct net_device *dev) |
592 | { | 658 | { |
593 | struct virtnet_info *vi = netdev_priv(dev); | 659 | struct virtnet_info *vi = netdev_priv(dev); |
@@ -608,6 +674,99 @@ static int virtnet_set_tx_csum(struct net_device *dev, u32 data) | |||
608 | return ethtool_op_set_tx_hw_csum(dev, data); | 674 | return ethtool_op_set_tx_hw_csum(dev, data); |
609 | } | 675 | } |
610 | 676 | ||
677 | static void virtnet_set_rx_mode(struct net_device *dev) | ||
678 | { | ||
679 | struct virtnet_info *vi = netdev_priv(dev); | ||
680 | struct scatterlist sg[2]; | ||
681 | u8 promisc, allmulti; | ||
682 | struct virtio_net_ctrl_mac *mac_data; | ||
683 | struct dev_addr_list *addr; | ||
684 | void *buf; | ||
685 | int i; | ||
686 | |||
687 | /* We can't dynamicaly set ndo_set_rx_mode, so return gracefully */ | ||
688 | if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) | ||
689 | return; | ||
690 | |||
691 | promisc = ((dev->flags & IFF_PROMISC) != 0); | ||
692 | allmulti = ((dev->flags & IFF_ALLMULTI) != 0); | ||
693 | |||
694 | sg_set_buf(sg, &promisc, sizeof(promisc)); | ||
695 | |||
696 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, | ||
697 | VIRTIO_NET_CTRL_RX_PROMISC, | ||
698 | sg, 1, 0)) | ||
699 | dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", | ||
700 | promisc ? "en" : "dis"); | ||
701 | |||
702 | sg_set_buf(sg, &allmulti, sizeof(allmulti)); | ||
703 | |||
704 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, | ||
705 | VIRTIO_NET_CTRL_RX_ALLMULTI, | ||
706 | sg, 1, 0)) | ||
707 | dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", | ||
708 | allmulti ? "en" : "dis"); | ||
709 | |||
710 | /* MAC filter - use one buffer for both lists */ | ||
711 | mac_data = buf = kzalloc(((dev->uc_count + dev->mc_count) * ETH_ALEN) + | ||
712 | (2 * sizeof(mac_data->entries)), GFP_ATOMIC); | ||
713 | if (!buf) { | ||
714 | dev_warn(&dev->dev, "No memory for MAC address buffer\n"); | ||
715 | return; | ||
716 | } | ||
717 | |||
718 | /* Store the unicast list and count in the front of the buffer */ | ||
719 | mac_data->entries = dev->uc_count; | ||
720 | addr = dev->uc_list; | ||
721 | for (i = 0; i < dev->uc_count; i++, addr = addr->next) | ||
722 | memcpy(&mac_data->macs[i][0], addr->da_addr, ETH_ALEN); | ||
723 | |||
724 | sg_set_buf(&sg[0], mac_data, | ||
725 | sizeof(mac_data->entries) + (dev->uc_count * ETH_ALEN)); | ||
726 | |||
727 | /* multicast list and count fill the end */ | ||
728 | mac_data = (void *)&mac_data->macs[dev->uc_count][0]; | ||
729 | |||
730 | mac_data->entries = dev->mc_count; | ||
731 | addr = dev->mc_list; | ||
732 | for (i = 0; i < dev->mc_count; i++, addr = addr->next) | ||
733 | memcpy(&mac_data->macs[i][0], addr->da_addr, ETH_ALEN); | ||
734 | |||
735 | sg_set_buf(&sg[1], mac_data, | ||
736 | sizeof(mac_data->entries) + (dev->mc_count * ETH_ALEN)); | ||
737 | |||
738 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC, | ||
739 | VIRTIO_NET_CTRL_MAC_TABLE_SET, | ||
740 | sg, 2, 0)) | ||
741 | dev_warn(&dev->dev, "Failed to set MAC fitler table.\n"); | ||
742 | |||
743 | kfree(buf); | ||
744 | } | ||
745 | |||
746 | static void virnet_vlan_rx_add_vid(struct net_device *dev, u16 vid) | ||
747 | { | ||
748 | struct virtnet_info *vi = netdev_priv(dev); | ||
749 | struct scatterlist sg; | ||
750 | |||
751 | sg_set_buf(&sg, &vid, sizeof(vid)); | ||
752 | |||
753 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, | ||
754 | VIRTIO_NET_CTRL_VLAN_ADD, &sg, 1, 0)) | ||
755 | dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid); | ||
756 | } | ||
757 | |||
758 | static void virnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) | ||
759 | { | ||
760 | struct virtnet_info *vi = netdev_priv(dev); | ||
761 | struct scatterlist sg; | ||
762 | |||
763 | sg_set_buf(&sg, &vid, sizeof(vid)); | ||
764 | |||
765 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, | ||
766 | VIRTIO_NET_CTRL_VLAN_DEL, &sg, 1, 0)) | ||
767 | dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid); | ||
768 | } | ||
769 | |||
611 | static struct ethtool_ops virtnet_ethtool_ops = { | 770 | static struct ethtool_ops virtnet_ethtool_ops = { |
612 | .set_tx_csum = virtnet_set_tx_csum, | 771 | .set_tx_csum = virtnet_set_tx_csum, |
613 | .set_sg = ethtool_op_set_sg, | 772 | .set_sg = ethtool_op_set_sg, |
@@ -631,13 +790,51 @@ static const struct net_device_ops virtnet_netdev = { | |||
631 | .ndo_stop = virtnet_close, | 790 | .ndo_stop = virtnet_close, |
632 | .ndo_start_xmit = start_xmit, | 791 | .ndo_start_xmit = start_xmit, |
633 | .ndo_validate_addr = eth_validate_addr, | 792 | .ndo_validate_addr = eth_validate_addr, |
634 | .ndo_set_mac_address = eth_mac_addr, | 793 | .ndo_set_mac_address = virtnet_set_mac_address, |
794 | .ndo_set_rx_mode = virtnet_set_rx_mode, | ||
635 | .ndo_change_mtu = virtnet_change_mtu, | 795 | .ndo_change_mtu = virtnet_change_mtu, |
796 | .ndo_vlan_rx_add_vid = virnet_vlan_rx_add_vid, | ||
797 | .ndo_vlan_rx_kill_vid = virnet_vlan_rx_kill_vid, | ||
636 | #ifdef CONFIG_NET_POLL_CONTROLLER | 798 | #ifdef CONFIG_NET_POLL_CONTROLLER |
637 | .ndo_poll_controller = virtnet_netpoll, | 799 | .ndo_poll_controller = virtnet_netpoll, |
638 | #endif | 800 | #endif |
639 | }; | 801 | }; |
640 | 802 | ||
803 | static void virtnet_update_status(struct virtnet_info *vi) | ||
804 | { | ||
805 | u16 v; | ||
806 | |||
807 | if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) | ||
808 | return; | ||
809 | |||
810 | vi->vdev->config->get(vi->vdev, | ||
811 | offsetof(struct virtio_net_config, status), | ||
812 | &v, sizeof(v)); | ||
813 | |||
814 | /* Ignore unknown (future) status bits */ | ||
815 | v &= VIRTIO_NET_S_LINK_UP; | ||
816 | |||
817 | if (vi->status == v) | ||
818 | return; | ||
819 | |||
820 | vi->status = v; | ||
821 | |||
822 | if (vi->status & VIRTIO_NET_S_LINK_UP) { | ||
823 | netif_carrier_on(vi->dev); | ||
824 | netif_wake_queue(vi->dev); | ||
825 | } else { | ||
826 | netif_carrier_off(vi->dev); | ||
827 | netif_stop_queue(vi->dev); | ||
828 | } | ||
829 | } | ||
830 | |||
831 | static void virtnet_config_changed(struct virtio_device *vdev) | ||
832 | { | ||
833 | struct virtnet_info *vi = vdev->priv; | ||
834 | |||
835 | virtnet_update_status(vi); | ||
836 | } | ||
837 | |||
641 | static int virtnet_probe(struct virtio_device *vdev) | 838 | static int virtnet_probe(struct virtio_device *vdev) |
642 | { | 839 | { |
643 | int err; | 840 | int err; |
@@ -679,8 +876,11 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
679 | vdev->config->get(vdev, | 876 | vdev->config->get(vdev, |
680 | offsetof(struct virtio_net_config, mac), | 877 | offsetof(struct virtio_net_config, mac), |
681 | dev->dev_addr, dev->addr_len); | 878 | dev->dev_addr, dev->addr_len); |
682 | } else | 879 | } else { |
683 | random_ether_addr(dev->dev_addr); | 880 | random_ether_addr(dev->dev_addr); |
881 | vdev->config->set(vdev, offsetof(struct virtio_net_config, mac), | ||
882 | dev->dev_addr, dev->addr_len); | ||
883 | } | ||
684 | 884 | ||
685 | /* Set up our device-specific information */ | 885 | /* Set up our device-specific information */ |
686 | vi = netdev_priv(dev); | 886 | vi = netdev_priv(dev); |
@@ -716,6 +916,17 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
716 | goto free_recv; | 916 | goto free_recv; |
717 | } | 917 | } |
718 | 918 | ||
919 | if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) { | ||
920 | vi->cvq = vdev->config->find_vq(vdev, 2, NULL); | ||
921 | if (IS_ERR(vi->cvq)) { | ||
922 | err = PTR_ERR(vi->svq); | ||
923 | goto free_send; | ||
924 | } | ||
925 | |||
926 | if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN)) | ||
927 | dev->features |= NETIF_F_HW_VLAN_FILTER; | ||
928 | } | ||
929 | |||
719 | /* Initialize our empty receive and send queues. */ | 930 | /* Initialize our empty receive and send queues. */ |
720 | skb_queue_head_init(&vi->recv); | 931 | skb_queue_head_init(&vi->recv); |
721 | skb_queue_head_init(&vi->send); | 932 | skb_queue_head_init(&vi->send); |
@@ -728,7 +939,7 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
728 | err = register_netdev(dev); | 939 | err = register_netdev(dev); |
729 | if (err) { | 940 | if (err) { |
730 | pr_debug("virtio_net: registering device failed\n"); | 941 | pr_debug("virtio_net: registering device failed\n"); |
731 | goto free_send; | 942 | goto free_ctrl; |
732 | } | 943 | } |
733 | 944 | ||
734 | /* Last of all, set up some receive buffers. */ | 945 | /* Last of all, set up some receive buffers. */ |
@@ -740,6 +951,8 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
740 | goto unregister; | 951 | goto unregister; |
741 | } | 952 | } |
742 | 953 | ||
954 | vi->status = VIRTIO_NET_S_LINK_UP; | ||
955 | virtnet_update_status(vi); | ||
743 | netif_carrier_on(dev); | 956 | netif_carrier_on(dev); |
744 | 957 | ||
745 | pr_debug("virtnet: registered device %s\n", dev->name); | 958 | pr_debug("virtnet: registered device %s\n", dev->name); |
@@ -747,6 +960,9 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
747 | 960 | ||
748 | unregister: | 961 | unregister: |
749 | unregister_netdev(dev); | 962 | unregister_netdev(dev); |
963 | free_ctrl: | ||
964 | if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) | ||
965 | vdev->config->del_vq(vi->cvq); | ||
750 | free_send: | 966 | free_send: |
751 | vdev->config->del_vq(vi->svq); | 967 | vdev->config->del_vq(vi->svq); |
752 | free_recv: | 968 | free_recv: |
@@ -778,6 +994,8 @@ static void virtnet_remove(struct virtio_device *vdev) | |||
778 | 994 | ||
779 | vdev->config->del_vq(vi->svq); | 995 | vdev->config->del_vq(vi->svq); |
780 | vdev->config->del_vq(vi->rvq); | 996 | vdev->config->del_vq(vi->rvq); |
997 | if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) | ||
998 | vdev->config->del_vq(vi->cvq); | ||
781 | unregister_netdev(vi->dev); | 999 | unregister_netdev(vi->dev); |
782 | 1000 | ||
783 | while (vi->pages) | 1001 | while (vi->pages) |
@@ -797,7 +1015,8 @@ static unsigned int features[] = { | |||
797 | VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, | 1015 | VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, |
798 | VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, | 1016 | VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, |
799 | VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ | 1017 | VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ |
800 | VIRTIO_NET_F_MRG_RXBUF, | 1018 | VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, |
1019 | VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, | ||
801 | VIRTIO_F_NOTIFY_ON_EMPTY, | 1020 | VIRTIO_F_NOTIFY_ON_EMPTY, |
802 | }; | 1021 | }; |
803 | 1022 | ||
@@ -809,6 +1028,7 @@ static struct virtio_driver virtio_net = { | |||
809 | .id_table = id_table, | 1028 | .id_table = id_table, |
810 | .probe = virtnet_probe, | 1029 | .probe = virtnet_probe, |
811 | .remove = __devexit_p(virtnet_remove), | 1030 | .remove = __devexit_p(virtnet_remove), |
1031 | .config_changed = virtnet_config_changed, | ||
812 | }; | 1032 | }; |
813 | 1033 | ||
814 | static int __init init(void) | 1034 | static int __init init(void) |