aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-01-21 14:14:09 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-21 14:14:09 -0500
commitcd5f20461de8e3e9b04932e4ba3e37afe39b8898 (patch)
tree26b31fbcf0995c22b073394946717eba0151fbe5
parent3fcd550a4b37b1c60b4afce2e4b200919ec8bd20 (diff)
parent7e58d5aea8abb993983a3f3088fd4a3f06180a1c (diff)
Merge branch 'virtio_mac'
Amos Kong says: ==================== Currenly mac is programmed byte by byte. This means that we have an intermediate step where mac is wrong. Third patch introduced a new vq control command to set mac address, it's atomic. V2: check return of sending command, delay eth_mac_addr() V3: restore software address when fail to set hardware address V4: split eth_mac_addr, fix error handle V5: rebase patches to net-next tree ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/virtio_net.c110
-rw-r--r--include/linux/etherdevice.h2
-rw-r--r--include/uapi/linux/virtio_net.h8
-rw-r--r--net/ethernet/eth.c41
4 files changed, 106 insertions, 55 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index a6fcf15adc4f..701408a1ded6 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -753,19 +753,77 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
753 return NETDEV_TX_OK; 753 return NETDEV_TX_OK;
754} 754}
755 755
756/*
757 * Send command via the control virtqueue and check status. Commands
758 * supported by the hypervisor, as indicated by feature bits, should
759 * never fail unless improperly formated.
760 */
761static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
762 struct scatterlist *data, int out, int in)
763{
764 struct scatterlist *s, sg[VIRTNET_SEND_COMMAND_SG_MAX + 2];
765 struct virtio_net_ctrl_hdr ctrl;
766 virtio_net_ctrl_ack status = ~0;
767 unsigned int tmp;
768 int i;
769
770 /* Caller should know better */
771 BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ||
772 (out + in > VIRTNET_SEND_COMMAND_SG_MAX));
773
774 out++; /* Add header */
775 in++; /* Add return status */
776
777 ctrl.class = class;
778 ctrl.cmd = cmd;
779
780 sg_init_table(sg, out + in);
781
782 sg_set_buf(&sg[0], &ctrl, sizeof(ctrl));
783 for_each_sg(data, s, out + in - 2, i)
784 sg_set_buf(&sg[i + 1], sg_virt(s), s->length);
785 sg_set_buf(&sg[out + in - 1], &status, sizeof(status));
786
787 BUG_ON(virtqueue_add_buf(vi->cvq, sg, out, in, vi, GFP_ATOMIC) < 0);
788
789 virtqueue_kick(vi->cvq);
790
791 /* Spin for a response, the kick causes an ioport write, trapping
792 * into the hypervisor, so the request should be handled immediately.
793 */
794 while (!virtqueue_get_buf(vi->cvq, &tmp))
795 cpu_relax();
796
797 return status == VIRTIO_NET_OK;
798}
799
756static int virtnet_set_mac_address(struct net_device *dev, void *p) 800static int virtnet_set_mac_address(struct net_device *dev, void *p)
757{ 801{
758 struct virtnet_info *vi = netdev_priv(dev); 802 struct virtnet_info *vi = netdev_priv(dev);
759 struct virtio_device *vdev = vi->vdev; 803 struct virtio_device *vdev = vi->vdev;
760 int ret; 804 int ret;
805 struct sockaddr *addr = p;
806 struct scatterlist sg;
761 807
762 ret = eth_mac_addr(dev, p); 808 ret = eth_prepare_mac_addr_change(dev, p);
763 if (ret) 809 if (ret)
764 return ret; 810 return ret;
765 811
766 if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) 812 if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR)) {
813 sg_init_one(&sg, addr->sa_data, dev->addr_len);
814 if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC,
815 VIRTIO_NET_CTRL_MAC_ADDR_SET,
816 &sg, 1, 0)) {
817 dev_warn(&vdev->dev,
818 "Failed to set mac address by vq command.\n");
819 return -EINVAL;
820 }
821 } else if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) {
767 vdev->config->set(vdev, offsetof(struct virtio_net_config, mac), 822 vdev->config->set(vdev, offsetof(struct virtio_net_config, mac),
768 dev->dev_addr, dev->addr_len); 823 addr->sa_data, dev->addr_len);
824 }
825
826 eth_commit_mac_addr_change(dev, p);
769 827
770 return 0; 828 return 0;
771} 829}
@@ -819,51 +877,6 @@ static void virtnet_netpoll(struct net_device *dev)
819} 877}
820#endif 878#endif
821 879
822/*
823 * Send command via the control virtqueue and check status. Commands
824 * supported by the hypervisor, as indicated by feature bits, should
825 * never fail unless improperly formated.
826 */
827static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
828 struct scatterlist *data, int out, int in)
829{
830 struct scatterlist *s, sg[VIRTNET_SEND_COMMAND_SG_MAX + 2];
831 struct virtio_net_ctrl_hdr ctrl;
832 virtio_net_ctrl_ack status = ~0;
833 unsigned int tmp;
834 int i;
835
836 /* Caller should know better */
837 BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ||
838 (out + in > VIRTNET_SEND_COMMAND_SG_MAX));
839
840 out++; /* Add header */
841 in++; /* Add return status */
842
843 ctrl.class = class;
844 ctrl.cmd = cmd;
845
846 sg_init_table(sg, out + in);
847
848 sg_set_buf(&sg[0], &ctrl, sizeof(ctrl));
849 for_each_sg(data, s, out + in - 2, i)
850 sg_set_buf(&sg[i + 1], sg_virt(s), s->length);
851 sg_set_buf(&sg[out + in - 1], &status, sizeof(status));
852
853 BUG_ON(virtqueue_add_buf(vi->cvq, sg, out, in, vi, GFP_ATOMIC) < 0);
854
855 virtqueue_kick(vi->cvq);
856
857 /*
858 * Spin for a response, the kick causes an ioport write, trapping
859 * into the hypervisor, so the request should be handled immediately.
860 */
861 while (!virtqueue_get_buf(vi->cvq, &tmp))
862 cpu_relax();
863
864 return status == VIRTIO_NET_OK;
865}
866
867static void virtnet_ack_link_announce(struct virtnet_info *vi) 880static void virtnet_ack_link_announce(struct virtnet_info *vi)
868{ 881{
869 rtnl_lock(); 882 rtnl_lock();
@@ -1628,6 +1641,7 @@ static unsigned int features[] = {
1628 VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, 1641 VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
1629 VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, 1642 VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
1630 VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, 1643 VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ,
1644 VIRTIO_NET_F_CTRL_MAC_ADDR,
1631}; 1645};
1632 1646
1633static struct virtio_driver virtio_net_driver = { 1647static struct virtio_driver virtio_net_driver = {
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 1a43e1b4f7ad..c623861964e4 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -40,6 +40,8 @@ extern int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
40extern void eth_header_cache_update(struct hh_cache *hh, 40extern void eth_header_cache_update(struct hh_cache *hh,
41 const struct net_device *dev, 41 const struct net_device *dev,
42 const unsigned char *haddr); 42 const unsigned char *haddr);
43extern int eth_prepare_mac_addr_change(struct net_device *dev, void *p);
44extern void eth_commit_mac_addr_change(struct net_device *dev, void *p);
43extern int eth_mac_addr(struct net_device *dev, void *p); 45extern int eth_mac_addr(struct net_device *dev, void *p);
44extern int eth_change_mtu(struct net_device *dev, int new_mtu); 46extern int eth_change_mtu(struct net_device *dev, int new_mtu);
45extern int eth_validate_addr(struct net_device *dev); 47extern int eth_validate_addr(struct net_device *dev);
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index 848e3584d7c8..a5a8c88753b9 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -53,6 +53,7 @@
53 * network */ 53 * network */
54#define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow 54#define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow
55 * Steering */ 55 * Steering */
56#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */
56 57
57#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ 58#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
58#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */ 59#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */
@@ -127,7 +128,7 @@ typedef __u8 virtio_net_ctrl_ack;
127 #define VIRTIO_NET_CTRL_RX_NOBCAST 5 128 #define VIRTIO_NET_CTRL_RX_NOBCAST 5
128 129
129/* 130/*
130 * Control the MAC filter table. 131 * Control the MAC
131 * 132 *
132 * The MAC filter table is managed by the hypervisor, the guest should 133 * The MAC filter table is managed by the hypervisor, the guest should
133 * assume the size is infinite. Filtering should be considered 134 * assume the size is infinite. Filtering should be considered
@@ -140,6 +141,10 @@ typedef __u8 virtio_net_ctrl_ack;
140 * first sg list contains unicast addresses, the second is for multicast. 141 * first sg list contains unicast addresses, the second is for multicast.
141 * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature 142 * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature
142 * is available. 143 * is available.
144 *
145 * The ADDR_SET command requests one out scatterlist, it contains a
146 * 6 bytes MAC address. This functionality is present if the
147 * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.
143 */ 148 */
144struct virtio_net_ctrl_mac { 149struct virtio_net_ctrl_mac {
145 __u32 entries; 150 __u32 entries;
@@ -148,6 +153,7 @@ struct virtio_net_ctrl_mac {
148 153
149#define VIRTIO_NET_CTRL_MAC 1 154#define VIRTIO_NET_CTRL_MAC 1
150 #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 155 #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0
156 #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1
151 157
152/* 158/*
153 * Control VLAN filtering 159 * Control VLAN filtering
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index bc39c8c8f589..a36c85eab5b4 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -272,6 +272,36 @@ void eth_header_cache_update(struct hh_cache *hh,
272EXPORT_SYMBOL(eth_header_cache_update); 272EXPORT_SYMBOL(eth_header_cache_update);
273 273
274/** 274/**
275 * eth_prepare_mac_addr_change - prepare for mac change
276 * @dev: network device
277 * @p: socket address
278 */
279int eth_prepare_mac_addr_change(struct net_device *dev, void *p)
280{
281 struct sockaddr *addr = p;
282
283 if (!(dev->priv_flags & IFF_LIVE_ADDR_CHANGE) && netif_running(dev))
284 return -EBUSY;
285 if (!is_valid_ether_addr(addr->sa_data))
286 return -EADDRNOTAVAIL;
287 return 0;
288}
289EXPORT_SYMBOL(eth_prepare_mac_addr_change);
290
291/**
292 * eth_commit_mac_addr_change - commit mac change
293 * @dev: network device
294 * @p: socket address
295 */
296void eth_commit_mac_addr_change(struct net_device *dev, void *p)
297{
298 struct sockaddr *addr = p;
299
300 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
301}
302EXPORT_SYMBOL(eth_commit_mac_addr_change);
303
304/**
275 * eth_mac_addr - set new Ethernet hardware address 305 * eth_mac_addr - set new Ethernet hardware address
276 * @dev: network device 306 * @dev: network device
277 * @p: socket address 307 * @p: socket address
@@ -283,13 +313,12 @@ EXPORT_SYMBOL(eth_header_cache_update);
283 */ 313 */
284int eth_mac_addr(struct net_device *dev, void *p) 314int eth_mac_addr(struct net_device *dev, void *p)
285{ 315{
286 struct sockaddr *addr = p; 316 int ret;
287 317
288 if (!(dev->priv_flags & IFF_LIVE_ADDR_CHANGE) && netif_running(dev)) 318 ret = eth_prepare_mac_addr_change(dev, p);
289 return -EBUSY; 319 if (ret < 0)
290 if (!is_valid_ether_addr(addr->sa_data)) 320 return ret;
291 return -EADDRNOTAVAIL; 321 eth_commit_mac_addr_change(dev, p);
292 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
293 return 0; 322 return 0;
294} 323}
295EXPORT_SYMBOL(eth_mac_addr); 324EXPORT_SYMBOL(eth_mac_addr);