diff options
-rw-r--r-- | drivers/net/virtio_net.c | 75 | ||||
-rw-r--r-- | drivers/virtio/virtio.c | 42 | ||||
-rw-r--r-- | include/linux/virtio.h | 4 |
3 files changed, 73 insertions, 48 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 3b3c5c571b6d..4cc3da1e4070 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -1661,6 +1661,49 @@ static const struct ethtool_ops virtnet_ethtool_ops = { | |||
1661 | .set_settings = virtnet_set_settings, | 1661 | .set_settings = virtnet_set_settings, |
1662 | }; | 1662 | }; |
1663 | 1663 | ||
1664 | static void virtnet_freeze_down(struct virtio_device *vdev) | ||
1665 | { | ||
1666 | struct virtnet_info *vi = vdev->priv; | ||
1667 | int i; | ||
1668 | |||
1669 | /* Make sure no work handler is accessing the device */ | ||
1670 | flush_work(&vi->config_work); | ||
1671 | |||
1672 | netif_device_detach(vi->dev); | ||
1673 | cancel_delayed_work_sync(&vi->refill); | ||
1674 | |||
1675 | if (netif_running(vi->dev)) { | ||
1676 | for (i = 0; i < vi->max_queue_pairs; i++) | ||
1677 | napi_disable(&vi->rq[i].napi); | ||
1678 | } | ||
1679 | } | ||
1680 | |||
1681 | static int init_vqs(struct virtnet_info *vi); | ||
1682 | |||
1683 | static int virtnet_restore_up(struct virtio_device *vdev) | ||
1684 | { | ||
1685 | struct virtnet_info *vi = vdev->priv; | ||
1686 | int err, i; | ||
1687 | |||
1688 | err = init_vqs(vi); | ||
1689 | if (err) | ||
1690 | return err; | ||
1691 | |||
1692 | virtio_device_ready(vdev); | ||
1693 | |||
1694 | if (netif_running(vi->dev)) { | ||
1695 | for (i = 0; i < vi->curr_queue_pairs; i++) | ||
1696 | if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL)) | ||
1697 | schedule_delayed_work(&vi->refill, 0); | ||
1698 | |||
1699 | for (i = 0; i < vi->max_queue_pairs; i++) | ||
1700 | virtnet_napi_enable(&vi->rq[i]); | ||
1701 | } | ||
1702 | |||
1703 | netif_device_attach(vi->dev); | ||
1704 | return err; | ||
1705 | } | ||
1706 | |||
1664 | static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog) | 1707 | static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog) |
1665 | { | 1708 | { |
1666 | unsigned long int max_sz = PAGE_SIZE - sizeof(struct padded_vnet_hdr); | 1709 | unsigned long int max_sz = PAGE_SIZE - sizeof(struct padded_vnet_hdr); |
@@ -2353,21 +2396,9 @@ static void virtnet_remove(struct virtio_device *vdev) | |||
2353 | static int virtnet_freeze(struct virtio_device *vdev) | 2396 | static int virtnet_freeze(struct virtio_device *vdev) |
2354 | { | 2397 | { |
2355 | struct virtnet_info *vi = vdev->priv; | 2398 | struct virtnet_info *vi = vdev->priv; |
2356 | int i; | ||
2357 | 2399 | ||
2358 | virtnet_cpu_notif_remove(vi); | 2400 | virtnet_cpu_notif_remove(vi); |
2359 | 2401 | virtnet_freeze_down(vdev); | |
2360 | /* Make sure no work handler is accessing the device */ | ||
2361 | flush_work(&vi->config_work); | ||
2362 | |||
2363 | netif_device_detach(vi->dev); | ||
2364 | cancel_delayed_work_sync(&vi->refill); | ||
2365 | |||
2366 | if (netif_running(vi->dev)) { | ||
2367 | for (i = 0; i < vi->max_queue_pairs; i++) | ||
2368 | napi_disable(&vi->rq[i].napi); | ||
2369 | } | ||
2370 | |||
2371 | remove_vq_common(vi); | 2402 | remove_vq_common(vi); |
2372 | 2403 | ||
2373 | return 0; | 2404 | return 0; |
@@ -2376,25 +2407,11 @@ static int virtnet_freeze(struct virtio_device *vdev) | |||
2376 | static int virtnet_restore(struct virtio_device *vdev) | 2407 | static int virtnet_restore(struct virtio_device *vdev) |
2377 | { | 2408 | { |
2378 | struct virtnet_info *vi = vdev->priv; | 2409 | struct virtnet_info *vi = vdev->priv; |
2379 | int err, i; | 2410 | int err; |
2380 | 2411 | ||
2381 | err = init_vqs(vi); | 2412 | err = virtnet_restore_up(vdev); |
2382 | if (err) | 2413 | if (err) |
2383 | return err; | 2414 | return err; |
2384 | |||
2385 | virtio_device_ready(vdev); | ||
2386 | |||
2387 | if (netif_running(vi->dev)) { | ||
2388 | for (i = 0; i < vi->curr_queue_pairs; i++) | ||
2389 | if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL)) | ||
2390 | schedule_delayed_work(&vi->refill, 0); | ||
2391 | |||
2392 | for (i = 0; i < vi->max_queue_pairs; i++) | ||
2393 | virtnet_napi_enable(&vi->rq[i]); | ||
2394 | } | ||
2395 | |||
2396 | netif_device_attach(vi->dev); | ||
2397 | |||
2398 | virtnet_set_queues(vi, vi->curr_queue_pairs); | 2415 | virtnet_set_queues(vi, vi->curr_queue_pairs); |
2399 | 2416 | ||
2400 | err = virtnet_cpu_notif_add(vi); | 2417 | err = virtnet_cpu_notif_add(vi); |
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 7062bb0975a5..400d70b69379 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c | |||
@@ -100,11 +100,6 @@ static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env) | |||
100 | dev->id.device, dev->id.vendor); | 100 | dev->id.device, dev->id.vendor); |
101 | } | 101 | } |
102 | 102 | ||
103 | static void add_status(struct virtio_device *dev, unsigned status) | ||
104 | { | ||
105 | dev->config->set_status(dev, dev->config->get_status(dev) | status); | ||
106 | } | ||
107 | |||
108 | void virtio_check_driver_offered_feature(const struct virtio_device *vdev, | 103 | void virtio_check_driver_offered_feature(const struct virtio_device *vdev, |
109 | unsigned int fbit) | 104 | unsigned int fbit) |
110 | { | 105 | { |
@@ -145,14 +140,15 @@ void virtio_config_changed(struct virtio_device *dev) | |||
145 | } | 140 | } |
146 | EXPORT_SYMBOL_GPL(virtio_config_changed); | 141 | EXPORT_SYMBOL_GPL(virtio_config_changed); |
147 | 142 | ||
148 | static void virtio_config_disable(struct virtio_device *dev) | 143 | void virtio_config_disable(struct virtio_device *dev) |
149 | { | 144 | { |
150 | spin_lock_irq(&dev->config_lock); | 145 | spin_lock_irq(&dev->config_lock); |
151 | dev->config_enabled = false; | 146 | dev->config_enabled = false; |
152 | spin_unlock_irq(&dev->config_lock); | 147 | spin_unlock_irq(&dev->config_lock); |
153 | } | 148 | } |
149 | EXPORT_SYMBOL_GPL(virtio_config_disable); | ||
154 | 150 | ||
155 | static void virtio_config_enable(struct virtio_device *dev) | 151 | void virtio_config_enable(struct virtio_device *dev) |
156 | { | 152 | { |
157 | spin_lock_irq(&dev->config_lock); | 153 | spin_lock_irq(&dev->config_lock); |
158 | dev->config_enabled = true; | 154 | dev->config_enabled = true; |
@@ -161,8 +157,15 @@ static void virtio_config_enable(struct virtio_device *dev) | |||
161 | dev->config_change_pending = false; | 157 | dev->config_change_pending = false; |
162 | spin_unlock_irq(&dev->config_lock); | 158 | spin_unlock_irq(&dev->config_lock); |
163 | } | 159 | } |
160 | EXPORT_SYMBOL_GPL(virtio_config_enable); | ||
161 | |||
162 | void virtio_add_status(struct virtio_device *dev, unsigned int status) | ||
163 | { | ||
164 | dev->config->set_status(dev, dev->config->get_status(dev) | status); | ||
165 | } | ||
166 | EXPORT_SYMBOL_GPL(virtio_add_status); | ||
164 | 167 | ||
165 | static int virtio_finalize_features(struct virtio_device *dev) | 168 | int virtio_finalize_features(struct virtio_device *dev) |
166 | { | 169 | { |
167 | int ret = dev->config->finalize_features(dev); | 170 | int ret = dev->config->finalize_features(dev); |
168 | unsigned status; | 171 | unsigned status; |
@@ -173,7 +176,7 @@ static int virtio_finalize_features(struct virtio_device *dev) | |||
173 | if (!virtio_has_feature(dev, VIRTIO_F_VERSION_1)) | 176 | if (!virtio_has_feature(dev, VIRTIO_F_VERSION_1)) |
174 | return 0; | 177 | return 0; |
175 | 178 | ||
176 | add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); | 179 | virtio_add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); |
177 | status = dev->config->get_status(dev); | 180 | status = dev->config->get_status(dev); |
178 | if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) { | 181 | if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) { |
179 | dev_err(&dev->dev, "virtio: device refuses features: %x\n", | 182 | dev_err(&dev->dev, "virtio: device refuses features: %x\n", |
@@ -182,6 +185,7 @@ static int virtio_finalize_features(struct virtio_device *dev) | |||
182 | } | 185 | } |
183 | return 0; | 186 | return 0; |
184 | } | 187 | } |
188 | EXPORT_SYMBOL_GPL(virtio_finalize_features); | ||
185 | 189 | ||
186 | static int virtio_dev_probe(struct device *_d) | 190 | static int virtio_dev_probe(struct device *_d) |
187 | { | 191 | { |
@@ -193,7 +197,7 @@ static int virtio_dev_probe(struct device *_d) | |||
193 | u64 driver_features_legacy; | 197 | u64 driver_features_legacy; |
194 | 198 | ||
195 | /* We have a driver! */ | 199 | /* We have a driver! */ |
196 | add_status(dev, VIRTIO_CONFIG_S_DRIVER); | 200 | virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER); |
197 | 201 | ||
198 | /* Figure out what features the device supports. */ | 202 | /* Figure out what features the device supports. */ |
199 | device_features = dev->config->get_features(dev); | 203 | device_features = dev->config->get_features(dev); |
@@ -247,7 +251,7 @@ static int virtio_dev_probe(struct device *_d) | |||
247 | 251 | ||
248 | return 0; | 252 | return 0; |
249 | err: | 253 | err: |
250 | add_status(dev, VIRTIO_CONFIG_S_FAILED); | 254 | virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); |
251 | return err; | 255 | return err; |
252 | 256 | ||
253 | } | 257 | } |
@@ -265,7 +269,7 @@ static int virtio_dev_remove(struct device *_d) | |||
265 | WARN_ON_ONCE(dev->config->get_status(dev)); | 269 | WARN_ON_ONCE(dev->config->get_status(dev)); |
266 | 270 | ||
267 | /* Acknowledge the device's existence again. */ | 271 | /* Acknowledge the device's existence again. */ |
268 | add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); | 272 | virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); |
269 | return 0; | 273 | return 0; |
270 | } | 274 | } |
271 | 275 | ||
@@ -316,7 +320,7 @@ int register_virtio_device(struct virtio_device *dev) | |||
316 | dev->config->reset(dev); | 320 | dev->config->reset(dev); |
317 | 321 | ||
318 | /* Acknowledge that we've seen the device. */ | 322 | /* Acknowledge that we've seen the device. */ |
319 | add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); | 323 | virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); |
320 | 324 | ||
321 | INIT_LIST_HEAD(&dev->vqs); | 325 | INIT_LIST_HEAD(&dev->vqs); |
322 | 326 | ||
@@ -325,7 +329,7 @@ int register_virtio_device(struct virtio_device *dev) | |||
325 | err = device_register(&dev->dev); | 329 | err = device_register(&dev->dev); |
326 | out: | 330 | out: |
327 | if (err) | 331 | if (err) |
328 | add_status(dev, VIRTIO_CONFIG_S_FAILED); | 332 | virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); |
329 | return err; | 333 | return err; |
330 | } | 334 | } |
331 | EXPORT_SYMBOL_GPL(register_virtio_device); | 335 | EXPORT_SYMBOL_GPL(register_virtio_device); |
@@ -365,18 +369,18 @@ int virtio_device_restore(struct virtio_device *dev) | |||
365 | dev->config->reset(dev); | 369 | dev->config->reset(dev); |
366 | 370 | ||
367 | /* Acknowledge that we've seen the device. */ | 371 | /* Acknowledge that we've seen the device. */ |
368 | add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); | 372 | virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); |
369 | 373 | ||
370 | /* Maybe driver failed before freeze. | 374 | /* Maybe driver failed before freeze. |
371 | * Restore the failed status, for debugging. */ | 375 | * Restore the failed status, for debugging. */ |
372 | if (dev->failed) | 376 | if (dev->failed) |
373 | add_status(dev, VIRTIO_CONFIG_S_FAILED); | 377 | virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); |
374 | 378 | ||
375 | if (!drv) | 379 | if (!drv) |
376 | return 0; | 380 | return 0; |
377 | 381 | ||
378 | /* We have a driver! */ | 382 | /* We have a driver! */ |
379 | add_status(dev, VIRTIO_CONFIG_S_DRIVER); | 383 | virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER); |
380 | 384 | ||
381 | ret = virtio_finalize_features(dev); | 385 | ret = virtio_finalize_features(dev); |
382 | if (ret) | 386 | if (ret) |
@@ -389,14 +393,14 @@ int virtio_device_restore(struct virtio_device *dev) | |||
389 | } | 393 | } |
390 | 394 | ||
391 | /* Finally, tell the device we're all set */ | 395 | /* Finally, tell the device we're all set */ |
392 | add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); | 396 | virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); |
393 | 397 | ||
394 | virtio_config_enable(dev); | 398 | virtio_config_enable(dev); |
395 | 399 | ||
396 | return 0; | 400 | return 0; |
397 | 401 | ||
398 | err: | 402 | err: |
399 | add_status(dev, VIRTIO_CONFIG_S_FAILED); | 403 | virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); |
400 | return ret; | 404 | return ret; |
401 | } | 405 | } |
402 | EXPORT_SYMBOL_GPL(virtio_device_restore); | 406 | EXPORT_SYMBOL_GPL(virtio_device_restore); |
diff --git a/include/linux/virtio.h b/include/linux/virtio.h index d5eb5479a425..04b0d3f95043 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h | |||
@@ -132,12 +132,16 @@ static inline struct virtio_device *dev_to_virtio(struct device *_dev) | |||
132 | return container_of(_dev, struct virtio_device, dev); | 132 | return container_of(_dev, struct virtio_device, dev); |
133 | } | 133 | } |
134 | 134 | ||
135 | void virtio_add_status(struct virtio_device *dev, unsigned int status); | ||
135 | int register_virtio_device(struct virtio_device *dev); | 136 | int register_virtio_device(struct virtio_device *dev); |
136 | void unregister_virtio_device(struct virtio_device *dev); | 137 | void unregister_virtio_device(struct virtio_device *dev); |
137 | 138 | ||
138 | void virtio_break_device(struct virtio_device *dev); | 139 | void virtio_break_device(struct virtio_device *dev); |
139 | 140 | ||
140 | void virtio_config_changed(struct virtio_device *dev); | 141 | void virtio_config_changed(struct virtio_device *dev); |
142 | void virtio_config_disable(struct virtio_device *dev); | ||
143 | void virtio_config_enable(struct virtio_device *dev); | ||
144 | int virtio_finalize_features(struct virtio_device *dev); | ||
141 | #ifdef CONFIG_PM_SLEEP | 145 | #ifdef CONFIG_PM_SLEEP |
142 | int virtio_device_freeze(struct virtio_device *dev); | 146 | int virtio_device_freeze(struct virtio_device *dev); |
143 | int virtio_device_restore(struct virtio_device *dev); | 147 | int virtio_device_restore(struct virtio_device *dev); |