summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Fastabend <john.fastabend@gmail.com>2017-02-02 22:16:01 -0500
committerDavid S. Miller <davem@davemloft.net>2017-02-07 10:05:12 -0500
commit9fe7bfce8b3e112e8e08c40deb72ee7e24c6f072 (patch)
treecb9910cfafe6c9d2cb9525fc86dfd474859d52fc
parent722d82830a04ccff6c7390535fcdfb1e4d69d126 (diff)
virtio_net: refactor freeze/restore logic into virtnet reset logic
For XDP we will need to reset the queues to allow for buffer headroom to be configured. In order to do this we need to essentially run the freeze()/restore() code path. Unfortunately the locking requirements between the freeze/restore and reset paths are different however so we can not simply reuse the code. This patch refactors the code path and adds a reset helper routine. Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Acked-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/virtio_net.c75
-rw-r--r--drivers/virtio/virtio.c42
-rw-r--r--include/linux/virtio.h4
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
1664static 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
1681static int init_vqs(struct virtnet_info *vi);
1682
1683static 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
1664static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog) 1707static 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)
2353static int virtnet_freeze(struct virtio_device *vdev) 2396static 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)
2376static int virtnet_restore(struct virtio_device *vdev) 2407static 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
103static void add_status(struct virtio_device *dev, unsigned status)
104{
105 dev->config->set_status(dev, dev->config->get_status(dev) | status);
106}
107
108void virtio_check_driver_offered_feature(const struct virtio_device *vdev, 103void 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}
146EXPORT_SYMBOL_GPL(virtio_config_changed); 141EXPORT_SYMBOL_GPL(virtio_config_changed);
147 142
148static void virtio_config_disable(struct virtio_device *dev) 143void 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}
149EXPORT_SYMBOL_GPL(virtio_config_disable);
154 150
155static void virtio_config_enable(struct virtio_device *dev) 151void 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}
160EXPORT_SYMBOL_GPL(virtio_config_enable);
161
162void virtio_add_status(struct virtio_device *dev, unsigned int status)
163{
164 dev->config->set_status(dev, dev->config->get_status(dev) | status);
165}
166EXPORT_SYMBOL_GPL(virtio_add_status);
164 167
165static int virtio_finalize_features(struct virtio_device *dev) 168int 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}
188EXPORT_SYMBOL_GPL(virtio_finalize_features);
185 189
186static int virtio_dev_probe(struct device *_d) 190static 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;
249err: 253err:
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);
326out: 330out:
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}
331EXPORT_SYMBOL_GPL(register_virtio_device); 335EXPORT_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
398err: 402err:
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}
402EXPORT_SYMBOL_GPL(virtio_device_restore); 406EXPORT_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
135void virtio_add_status(struct virtio_device *dev, unsigned int status);
135int register_virtio_device(struct virtio_device *dev); 136int register_virtio_device(struct virtio_device *dev);
136void unregister_virtio_device(struct virtio_device *dev); 137void unregister_virtio_device(struct virtio_device *dev);
137 138
138void virtio_break_device(struct virtio_device *dev); 139void virtio_break_device(struct virtio_device *dev);
139 140
140void virtio_config_changed(struct virtio_device *dev); 141void virtio_config_changed(struct virtio_device *dev);
142void virtio_config_disable(struct virtio_device *dev);
143void virtio_config_enable(struct virtio_device *dev);
144int virtio_finalize_features(struct virtio_device *dev);
141#ifdef CONFIG_PM_SLEEP 145#ifdef CONFIG_PM_SLEEP
142int virtio_device_freeze(struct virtio_device *dev); 146int virtio_device_freeze(struct virtio_device *dev);
143int virtio_device_restore(struct virtio_device *dev); 147int virtio_device_restore(struct virtio_device *dev);