diff options
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index d8838dedb7a4..f94ab786088f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -140,6 +140,12 @@ struct virtnet_info { | |||
140 | 140 | ||
141 | /* CPU hot plug notifier */ | 141 | /* CPU hot plug notifier */ |
142 | struct notifier_block nb; | 142 | struct notifier_block nb; |
143 | |||
144 | /* Control VQ buffers: protected by the rtnl lock */ | ||
145 | struct virtio_net_ctrl_hdr ctrl_hdr; | ||
146 | virtio_net_ctrl_ack ctrl_status; | ||
147 | u8 ctrl_promisc; | ||
148 | u8 ctrl_allmulti; | ||
143 | }; | 149 | }; |
144 | 150 | ||
145 | struct padded_vnet_hdr { | 151 | struct padded_vnet_hdr { |
@@ -976,31 +982,30 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, | |||
976 | struct scatterlist *out) | 982 | struct scatterlist *out) |
977 | { | 983 | { |
978 | struct scatterlist *sgs[4], hdr, stat; | 984 | struct scatterlist *sgs[4], hdr, stat; |
979 | struct virtio_net_ctrl_hdr ctrl; | ||
980 | virtio_net_ctrl_ack status = ~0; | ||
981 | unsigned out_num = 0, tmp; | 985 | unsigned out_num = 0, tmp; |
982 | 986 | ||
983 | /* Caller should know better */ | 987 | /* Caller should know better */ |
984 | BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)); | 988 | BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)); |
985 | 989 | ||
986 | ctrl.class = class; | 990 | vi->ctrl_status = ~0; |
987 | ctrl.cmd = cmd; | 991 | vi->ctrl_hdr.class = class; |
992 | vi->ctrl_hdr.cmd = cmd; | ||
988 | /* Add header */ | 993 | /* Add header */ |
989 | sg_init_one(&hdr, &ctrl, sizeof(ctrl)); | 994 | sg_init_one(&hdr, &vi->ctrl_hdr, sizeof(vi->ctrl_hdr)); |
990 | sgs[out_num++] = &hdr; | 995 | sgs[out_num++] = &hdr; |
991 | 996 | ||
992 | if (out) | 997 | if (out) |
993 | sgs[out_num++] = out; | 998 | sgs[out_num++] = out; |
994 | 999 | ||
995 | /* Add return status. */ | 1000 | /* Add return status. */ |
996 | sg_init_one(&stat, &status, sizeof(status)); | 1001 | sg_init_one(&stat, &vi->ctrl_status, sizeof(vi->ctrl_status)); |
997 | sgs[out_num] = &stat; | 1002 | sgs[out_num] = &stat; |
998 | 1003 | ||
999 | BUG_ON(out_num + 1 > ARRAY_SIZE(sgs)); | 1004 | BUG_ON(out_num + 1 > ARRAY_SIZE(sgs)); |
1000 | virtqueue_add_sgs(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC); | 1005 | virtqueue_add_sgs(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC); |
1001 | 1006 | ||
1002 | if (unlikely(!virtqueue_kick(vi->cvq))) | 1007 | if (unlikely(!virtqueue_kick(vi->cvq))) |
1003 | return status == VIRTIO_NET_OK; | 1008 | return vi->ctrl_status == VIRTIO_NET_OK; |
1004 | 1009 | ||
1005 | /* Spin for a response, the kick causes an ioport write, trapping | 1010 | /* Spin for a response, the kick causes an ioport write, trapping |
1006 | * into the hypervisor, so the request should be handled immediately. | 1011 | * into the hypervisor, so the request should be handled immediately. |
@@ -1009,7 +1014,7 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, | |||
1009 | !virtqueue_is_broken(vi->cvq)) | 1014 | !virtqueue_is_broken(vi->cvq)) |
1010 | cpu_relax(); | 1015 | cpu_relax(); |
1011 | 1016 | ||
1012 | return status == VIRTIO_NET_OK; | 1017 | return vi->ctrl_status == VIRTIO_NET_OK; |
1013 | } | 1018 | } |
1014 | 1019 | ||
1015 | static int virtnet_set_mac_address(struct net_device *dev, void *p) | 1020 | static int virtnet_set_mac_address(struct net_device *dev, void *p) |
@@ -1151,7 +1156,6 @@ static void virtnet_set_rx_mode(struct net_device *dev) | |||
1151 | { | 1156 | { |
1152 | struct virtnet_info *vi = netdev_priv(dev); | 1157 | struct virtnet_info *vi = netdev_priv(dev); |
1153 | struct scatterlist sg[2]; | 1158 | struct scatterlist sg[2]; |
1154 | u8 promisc, allmulti; | ||
1155 | struct virtio_net_ctrl_mac *mac_data; | 1159 | struct virtio_net_ctrl_mac *mac_data; |
1156 | struct netdev_hw_addr *ha; | 1160 | struct netdev_hw_addr *ha; |
1157 | int uc_count; | 1161 | int uc_count; |
@@ -1163,22 +1167,22 @@ static void virtnet_set_rx_mode(struct net_device *dev) | |||
1163 | if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) | 1167 | if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) |
1164 | return; | 1168 | return; |
1165 | 1169 | ||
1166 | promisc = ((dev->flags & IFF_PROMISC) != 0); | 1170 | vi->ctrl_promisc = ((dev->flags & IFF_PROMISC) != 0); |
1167 | allmulti = ((dev->flags & IFF_ALLMULTI) != 0); | 1171 | vi->ctrl_allmulti = ((dev->flags & IFF_ALLMULTI) != 0); |
1168 | 1172 | ||
1169 | sg_init_one(sg, &promisc, sizeof(promisc)); | 1173 | sg_init_one(sg, &vi->ctrl_promisc, sizeof(vi->ctrl_promisc)); |
1170 | 1174 | ||
1171 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, | 1175 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, |
1172 | VIRTIO_NET_CTRL_RX_PROMISC, sg)) | 1176 | VIRTIO_NET_CTRL_RX_PROMISC, sg)) |
1173 | dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", | 1177 | dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", |
1174 | promisc ? "en" : "dis"); | 1178 | vi->ctrl_promisc ? "en" : "dis"); |
1175 | 1179 | ||
1176 | sg_init_one(sg, &allmulti, sizeof(allmulti)); | 1180 | sg_init_one(sg, &vi->ctrl_allmulti, sizeof(vi->ctrl_allmulti)); |
1177 | 1181 | ||
1178 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, | 1182 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, |
1179 | VIRTIO_NET_CTRL_RX_ALLMULTI, sg)) | 1183 | VIRTIO_NET_CTRL_RX_ALLMULTI, sg)) |
1180 | dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", | 1184 | dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", |
1181 | allmulti ? "en" : "dis"); | 1185 | vi->ctrl_allmulti ? "en" : "dis"); |
1182 | 1186 | ||
1183 | uc_count = netdev_uc_count(dev); | 1187 | uc_count = netdev_uc_count(dev); |
1184 | mc_count = netdev_mc_count(dev); | 1188 | mc_count = netdev_mc_count(dev); |