Commit 9c799c22 authored by Jason Gunthorpe's avatar Jason Gunthorpe Committed by Alex Williamson
Browse files

vfio/mdev: add mdev available instance checking to the core



Many of the mdev drivers use a simple counter for keeping track of the
available instances. Move this code to the core code and store the counter
in the mdev_parent. Implement it using correct locking, fixing mdpy.

Drivers just provide the value in the mdev_driver at registration time
and the core code takes care of maintaining it and exposing the value in
sysfs.

[hch: count instances per-parent instead of per-type, use an atomic_t
 to avoid taking mdev_list_lock in the show method]

Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Reviewed-by: default avatarKirti Wankhede <kwankhede@nvidia.com>
Reviewed-by: default avatarEric Farman <farman@linux.ibm.com>
Link: https://lore.kernel.org/r/20220923092652.100656-15-hch@lst.de


Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent 685a1537
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -141,7 +141,6 @@ static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch)
	INIT_LIST_HEAD(&private->crw);
	INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
	INIT_WORK(&private->crw_work, vfio_ccw_crw_todo);
	atomic_set(&private->avail, 1);

	private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX, sizeof(struct ccw1),
				       GFP_KERNEL);
+1 −14
Original line number Diff line number Diff line
@@ -44,13 +44,6 @@ static void vfio_ccw_dma_unmap(struct vfio_device *vdev, u64 iova, u64 length)
	vfio_ccw_mdev_reset(private);
}

static unsigned int vfio_ccw_get_available(struct mdev_type *mtype)
{
	struct vfio_ccw_private *private = dev_get_drvdata(mtype->parent->dev);

	return atomic_read(&private->avail);
}

static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
{
	struct vfio_ccw_private *private =
@@ -68,9 +61,6 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev)
	if (private->state == VFIO_CCW_STATE_NOT_OPER)
		return -ENODEV;

	if (atomic_dec_if_positive(&private->avail) < 0)
		return -EPERM;

	ret = vfio_init_device(&private->vdev, &mdev->dev, &vfio_ccw_dev_ops);
	if (ret)
		return ret;
@@ -88,7 +78,6 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev)

err_put_vdev:
	vfio_put_device(&private->vdev);
	atomic_inc(&private->avail);
	return ret;
}

@@ -130,8 +119,6 @@ static void vfio_ccw_mdev_remove(struct mdev_device *mdev)
	 * cycle.
	 */
	wait_for_completion(&private->release_comp);

	atomic_inc(&private->avail);
}

static int vfio_ccw_mdev_open_device(struct vfio_device *vdev)
@@ -605,6 +592,7 @@ static const struct vfio_device_ops vfio_ccw_dev_ops = {

struct mdev_driver vfio_ccw_mdev_driver = {
	.device_api = VFIO_DEVICE_API_CCW_STRING,
	.max_instances = 1,
	.driver = {
		.name = "vfio_ccw_mdev",
		.owner = THIS_MODULE,
@@ -612,5 +600,4 @@ struct mdev_driver vfio_ccw_mdev_driver = {
	},
	.probe = vfio_ccw_mdev_probe,
	.remove = vfio_ccw_mdev_remove,
	.get_available = vfio_ccw_get_available,
};
+0 −2
Original line number Diff line number Diff line
@@ -73,7 +73,6 @@ struct vfio_ccw_crw {
 * @sch: pointer to the subchannel
 * @state: internal state of the device
 * @completion: synchronization helper of the I/O completion
 * @avail: available for creating a mediated device
 * @io_region: MMIO region to input/output I/O arguments/results
 * @io_mutex: protect against concurrent update of I/O regions
 * @region: additional regions for other subchannel operations
@@ -97,7 +96,6 @@ struct vfio_ccw_private {
	struct subchannel	*sch;
	int			state;
	struct completion	*completion;
	atomic_t		avail;
	struct ccw_io_region	*io_region;
	struct mutex		io_mutex;
	struct vfio_ccw_region *region;
+1 −12
Original line number Diff line number Diff line
@@ -689,9 +689,6 @@ static int vfio_ap_mdev_init_dev(struct vfio_device *vdev)
	struct ap_matrix_mdev *matrix_mdev =
		container_of(vdev, struct ap_matrix_mdev, vdev);

	if ((atomic_dec_if_positive(&matrix_dev->available_instances) < 0))
		return -EPERM;

	matrix_mdev->mdev = to_mdev_device(vdev->dev);
	vfio_ap_matrix_init(&matrix_dev->info, &matrix_mdev->matrix);
	matrix_mdev->pqap_hook = handle_pqap;
@@ -770,7 +767,6 @@ static void vfio_ap_mdev_unlink_fr_queues(struct ap_matrix_mdev *matrix_mdev)

static void vfio_ap_mdev_release_dev(struct vfio_device *vdev)
{
	atomic_inc(&matrix_dev->available_instances);
	vfio_free_device(vdev);
}

@@ -790,11 +786,6 @@ static void vfio_ap_mdev_remove(struct mdev_device *mdev)
	vfio_put_device(&matrix_mdev->vdev);
}

static unsigned int vfio_ap_mdev_get_available(struct mdev_type *mtype)
{
	return atomic_read(&matrix_dev->available_instances);
}

#define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \
			 "already assigned to %s"

@@ -1772,6 +1763,7 @@ static const struct vfio_device_ops vfio_ap_matrix_dev_ops = {

static struct mdev_driver vfio_ap_matrix_driver = {
	.device_api = VFIO_DEVICE_API_AP_STRING,
	.max_instances = MAX_ZDEV_ENTRIES_EXT,
	.driver = {
		.name = "vfio_ap_mdev",
		.owner = THIS_MODULE,
@@ -1780,15 +1772,12 @@ static struct mdev_driver vfio_ap_matrix_driver = {
	},
	.probe = vfio_ap_mdev_probe,
	.remove = vfio_ap_mdev_remove,
	.get_available = vfio_ap_mdev_get_available,
};

int vfio_ap_mdev_register(void)
{
	int ret;

	atomic_set(&matrix_dev->available_instances, MAX_ZDEV_ENTRIES_EXT);

	ret = mdev_register_driver(&vfio_ap_matrix_driver);
	if (ret)
		return ret;
+0 −2
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@
 * struct ap_matrix_dev - Contains the data for the matrix device.
 *
 * @device:	generic device structure associated with the AP matrix device
 * @available_instances: number of mediated matrix devices that can be created
 * @info:	the struct containing the output from the PQAP(QCI) instruction
 * @mdev_list:	the list of mediated matrix devices created
 * @mdevs_lock: mutex for locking the AP matrix device. This lock will be
@@ -46,7 +45,6 @@
 */
struct ap_matrix_dev {
	struct device device;
	atomic_t available_instances;
	struct ap_config_info info;
	struct list_head mdev_list;
	struct mutex mdevs_lock; /* serializes access to each ap_matrix_mdev */
Loading