diff options
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index ea9890d61967..f36584616e7d 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -2230,14 +2230,8 @@ static bool virtnet_validate_features(struct virtio_device *vdev) | |||
2230 | #define MIN_MTU ETH_MIN_MTU | 2230 | #define MIN_MTU ETH_MIN_MTU |
2231 | #define MAX_MTU ETH_MAX_MTU | 2231 | #define MAX_MTU ETH_MAX_MTU |
2232 | 2232 | ||
2233 | static int virtnet_probe(struct virtio_device *vdev) | 2233 | static int virtnet_validate(struct virtio_device *vdev) |
2234 | { | 2234 | { |
2235 | int i, err; | ||
2236 | struct net_device *dev; | ||
2237 | struct virtnet_info *vi; | ||
2238 | u16 max_queue_pairs; | ||
2239 | int mtu; | ||
2240 | |||
2241 | if (!vdev->config->get) { | 2235 | if (!vdev->config->get) { |
2242 | dev_err(&vdev->dev, "%s failure: config access disabled\n", | 2236 | dev_err(&vdev->dev, "%s failure: config access disabled\n", |
2243 | __func__); | 2237 | __func__); |
@@ -2247,6 +2241,25 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
2247 | if (!virtnet_validate_features(vdev)) | 2241 | if (!virtnet_validate_features(vdev)) |
2248 | return -EINVAL; | 2242 | return -EINVAL; |
2249 | 2243 | ||
2244 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MTU)) { | ||
2245 | int mtu = virtio_cread16(vdev, | ||
2246 | offsetof(struct virtio_net_config, | ||
2247 | mtu)); | ||
2248 | if (mtu < MIN_MTU) | ||
2249 | __virtio_clear_bit(vdev, VIRTIO_NET_F_MTU); | ||
2250 | } | ||
2251 | |||
2252 | return 0; | ||
2253 | } | ||
2254 | |||
2255 | static int virtnet_probe(struct virtio_device *vdev) | ||
2256 | { | ||
2257 | int i, err; | ||
2258 | struct net_device *dev; | ||
2259 | struct virtnet_info *vi; | ||
2260 | u16 max_queue_pairs; | ||
2261 | int mtu; | ||
2262 | |||
2250 | /* Find if host supports multiqueue virtio_net device */ | 2263 | /* Find if host supports multiqueue virtio_net device */ |
2251 | err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ, | 2264 | err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ, |
2252 | struct virtio_net_config, | 2265 | struct virtio_net_config, |
@@ -2362,11 +2375,20 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
2362 | offsetof(struct virtio_net_config, | 2375 | offsetof(struct virtio_net_config, |
2363 | mtu)); | 2376 | mtu)); |
2364 | if (mtu < dev->min_mtu) { | 2377 | if (mtu < dev->min_mtu) { |
2365 | __virtio_clear_bit(vdev, VIRTIO_NET_F_MTU); | 2378 | /* Should never trigger: MTU was previously validated |
2366 | } else { | 2379 | * in virtnet_validate. |
2367 | dev->mtu = mtu; | 2380 | */ |
2368 | dev->max_mtu = mtu; | 2381 | dev_err(&vdev->dev, "device MTU appears to have changed " |
2382 | "it is now %d < %d", mtu, dev->min_mtu); | ||
2383 | goto free_stats; | ||
2369 | } | 2384 | } |
2385 | |||
2386 | dev->mtu = mtu; | ||
2387 | dev->max_mtu = mtu; | ||
2388 | |||
2389 | /* TODO: size buffers correctly in this case. */ | ||
2390 | if (dev->mtu > ETH_DATA_LEN) | ||
2391 | vi->big_packets = true; | ||
2370 | } | 2392 | } |
2371 | 2393 | ||
2372 | if (vi->any_header_sg) | 2394 | if (vi->any_header_sg) |
@@ -2544,6 +2566,7 @@ static struct virtio_driver virtio_net_driver = { | |||
2544 | .driver.name = KBUILD_MODNAME, | 2566 | .driver.name = KBUILD_MODNAME, |
2545 | .driver.owner = THIS_MODULE, | 2567 | .driver.owner = THIS_MODULE, |
2546 | .id_table = id_table, | 2568 | .id_table = id_table, |
2569 | .validate = virtnet_validate, | ||
2547 | .probe = virtnet_probe, | 2570 | .probe = virtnet_probe, |
2548 | .remove = virtnet_remove, | 2571 | .remove = virtnet_remove, |
2549 | .config_changed = virtnet_config_changed, | 2572 | .config_changed = virtnet_config_changed, |