Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost

Pull virtio fixes from Michael Tsirkin:
"Fixes and cleanups:

- A couple of mlx5 fixes related to cvq

- A couple of reverts dropping useless code (code that used it got
reverted earlier)"

* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
vdpa: mlx5: synchronize driver status with CVQ
vdpa: mlx5: prevent cvq work from hogging CPU
Revert "virtio_config: introduce a new .enable_cbs method"
Revert "virtio: use virtio_device_ready() in virtio_device_restore()"

+43 -30
+41 -21
drivers/vdpa/mlx5/net/mlx5_vnet.c
··· 163 163 u32 cur_num_vqs; 164 164 struct notifier_block nb; 165 165 struct vdpa_callback config_cb; 166 + struct mlx5_vdpa_wq_ent cvq_ent; 166 167 }; 167 168 168 169 static void free_resources(struct mlx5_vdpa_net *ndev); ··· 1659 1658 mvdev = wqent->mvdev; 1660 1659 ndev = to_mlx5_vdpa_ndev(mvdev); 1661 1660 cvq = &mvdev->cvq; 1661 + 1662 + mutex_lock(&ndev->reslock); 1663 + 1664 + if (!(mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) 1665 + goto out; 1666 + 1662 1667 if (!(ndev->mvdev.actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ))) 1663 1668 goto out; 1664 1669 ··· 1703 1696 1704 1697 if (vringh_need_notify_iotlb(&cvq->vring)) 1705 1698 vringh_notify(&cvq->vring); 1699 + 1700 + queue_work(mvdev->wq, &wqent->work); 1701 + break; 1706 1702 } 1703 + 1707 1704 out: 1708 - kfree(wqent); 1705 + mutex_unlock(&ndev->reslock); 1709 1706 } 1710 1707 1711 1708 static void mlx5_vdpa_kick_vq(struct vdpa_device *vdev, u16 idx) ··· 1717 1706 struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); 1718 1707 struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); 1719 1708 struct mlx5_vdpa_virtqueue *mvq; 1720 - struct mlx5_vdpa_wq_ent *wqent; 1721 1709 1722 1710 if (!is_index_valid(mvdev, idx)) 1723 1711 return; ··· 1725 1715 if (!mvdev->wq || !mvdev->cvq.ready) 1726 1716 return; 1727 1717 1728 - wqent = kzalloc(sizeof(*wqent), GFP_ATOMIC); 1729 - if (!wqent) 1730 - return; 1731 - 1732 - wqent->mvdev = mvdev; 1733 - INIT_WORK(&wqent->work, mlx5_cvq_kick_handler); 1734 - queue_work(mvdev->wq, &wqent->work); 1718 + queue_work(mvdev->wq, &ndev->cvq_ent.work); 1735 1719 return; 1736 1720 } 1737 1721 ··· 2184 2180 goto err_mr; 2185 2181 2186 2182 if (!(mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) 2187 - return 0; 2183 + goto err_mr; 2188 2184 2189 2185 restore_channels_info(ndev); 2190 2186 err = setup_driver(mvdev); ··· 2199 2195 return err; 2200 2196 } 2201 2197 2198 + /* reslock must be held for this function */ 2202 2199 static int setup_driver(struct mlx5_vdpa_dev *mvdev) 2203 2200 { 2204 2201 struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); 2205 2202 int err; 2206 2203 2207 - mutex_lock(&ndev->reslock); 2204 + WARN_ON(!mutex_is_locked(&ndev->reslock)); 2205 + 2208 2206 if (ndev->setup) { 2209 2207 mlx5_vdpa_warn(mvdev, "setup driver called for already setup driver\n"); 2210 2208 err = 0; ··· 2236 2230 goto err_fwd; 2237 2231 } 2238 2232 ndev->setup = true; 2239 - mutex_unlock(&ndev->reslock); 2240 2233 2241 2234 return 0; 2242 2235 ··· 2246 2241 err_rqt: 2247 2242 teardown_virtqueues(ndev); 2248 2243 out: 2249 - mutex_unlock(&ndev->reslock); 2250 2244 return err; 2251 2245 } 2252 2246 2247 + /* reslock must be held for this function */ 2253 2248 static void teardown_driver(struct mlx5_vdpa_net *ndev) 2254 2249 { 2255 - mutex_lock(&ndev->reslock); 2250 + 2251 + WARN_ON(!mutex_is_locked(&ndev->reslock)); 2252 + 2256 2253 if (!ndev->setup) 2257 - goto out; 2254 + return; 2258 2255 2259 2256 remove_fwd_to_tir(ndev); 2260 2257 destroy_tir(ndev); 2261 2258 destroy_rqt(ndev); 2262 2259 teardown_virtqueues(ndev); 2263 2260 ndev->setup = false; 2264 - out: 2265 - mutex_unlock(&ndev->reslock); 2266 2261 } 2267 2262 2268 2263 static void clear_vqs_ready(struct mlx5_vdpa_net *ndev) ··· 2283 2278 2284 2279 print_status(mvdev, status, true); 2285 2280 2281 + mutex_lock(&ndev->reslock); 2282 + 2286 2283 if ((status ^ ndev->mvdev.status) & VIRTIO_CONFIG_S_DRIVER_OK) { 2287 2284 if (status & VIRTIO_CONFIG_S_DRIVER_OK) { 2288 2285 err = setup_driver(mvdev); ··· 2294 2287 } 2295 2288 } else { 2296 2289 mlx5_vdpa_warn(mvdev, "did not expect DRIVER_OK to be cleared\n"); 2297 - return; 2290 + goto err_clear; 2298 2291 } 2299 2292 } 2300 2293 2301 2294 ndev->mvdev.status = status; 2295 + mutex_unlock(&ndev->reslock); 2302 2296 return; 2303 2297 2304 2298 err_setup: 2305 2299 mlx5_vdpa_destroy_mr(&ndev->mvdev); 2306 2300 ndev->mvdev.status |= VIRTIO_CONFIG_S_FAILED; 2301 + err_clear: 2302 + mutex_unlock(&ndev->reslock); 2307 2303 } 2308 2304 2309 2305 static int mlx5_vdpa_reset(struct vdpa_device *vdev) ··· 2316 2306 2317 2307 print_status(mvdev, 0, true); 2318 2308 mlx5_vdpa_info(mvdev, "performing device reset\n"); 2309 + 2310 + mutex_lock(&ndev->reslock); 2319 2311 teardown_driver(ndev); 2320 2312 clear_vqs_ready(ndev); 2321 2313 mlx5_vdpa_destroy_mr(&ndev->mvdev); ··· 2330 2318 if (mlx5_vdpa_create_mr(mvdev, NULL)) 2331 2319 mlx5_vdpa_warn(mvdev, "create MR failed\n"); 2332 2320 } 2321 + mutex_unlock(&ndev->reslock); 2333 2322 2334 2323 return 0; 2335 2324 } ··· 2366 2353 static int mlx5_vdpa_set_map(struct vdpa_device *vdev, struct vhost_iotlb *iotlb) 2367 2354 { 2368 2355 struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); 2356 + struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); 2369 2357 bool change_map; 2370 2358 int err; 2359 + 2360 + mutex_lock(&ndev->reslock); 2371 2361 2372 2362 err = mlx5_vdpa_handle_set_map(mvdev, iotlb, &change_map); 2373 2363 if (err) { 2374 2364 mlx5_vdpa_warn(mvdev, "set map failed(%d)\n", err); 2375 - return err; 2365 + goto err; 2376 2366 } 2377 2367 2378 2368 if (change_map) 2379 - return mlx5_vdpa_change_map(mvdev, iotlb); 2369 + err = mlx5_vdpa_change_map(mvdev, iotlb); 2380 2370 2381 - return 0; 2371 + err: 2372 + mutex_unlock(&ndev->reslock); 2373 + return err; 2382 2374 } 2383 2375 2384 2376 static void mlx5_vdpa_free(struct vdpa_device *vdev) ··· 2758 2740 if (err) 2759 2741 goto err_mr; 2760 2742 2743 + ndev->cvq_ent.mvdev = mvdev; 2744 + INIT_WORK(&ndev->cvq_ent.work, mlx5_cvq_kick_handler); 2761 2745 mvdev->wq = create_singlethread_workqueue("mlx5_vdpa_wq"); 2762 2746 if (!mvdev->wq) { 2763 2747 err = -ENOMEM;
+2 -3
drivers/virtio/virtio.c
··· 526 526 goto err; 527 527 } 528 528 529 - /* If restore didn't do it, mark device DRIVER_OK ourselves. */ 530 - if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK)) 531 - virtio_device_ready(dev); 529 + /* Finally, tell the device we're all set */ 530 + virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); 532 531 533 532 virtio_config_enable(dev); 534 533
-6
include/linux/virtio_config.h
··· 23 23 * any of @get/@set, @get_status/@set_status, or @get_features/ 24 24 * @finalize_features are NOT safe to be called from an atomic 25 25 * context. 26 - * @enable_cbs: enable the callbacks 27 - * vdev: the virtio_device 28 26 * @get: read the value of a configuration field 29 27 * vdev: the virtio_device 30 28 * offset: the offset of the configuration field ··· 76 78 */ 77 79 typedef void vq_callback_t(struct virtqueue *); 78 80 struct virtio_config_ops { 79 - void (*enable_cbs)(struct virtio_device *vdev); 80 81 void (*get)(struct virtio_device *vdev, unsigned offset, 81 82 void *buf, unsigned len); 82 83 void (*set)(struct virtio_device *vdev, unsigned offset, ··· 229 232 void virtio_device_ready(struct virtio_device *dev) 230 233 { 231 234 unsigned status = dev->config->get_status(dev); 232 - 233 - if (dev->config->enable_cbs) 234 - dev->config->enable_cbs(dev); 235 235 236 236 BUG_ON(status & VIRTIO_CONFIG_S_DRIVER_OK); 237 237 dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK);