#include <linux/device.h>
#include <linux/slab.h>
#include <linux/mm.h>
-#include <linux/idr.h>
#include <linux/sched/signal.h>
#include <linux/string.h>
#include <linux/kobject.h>
#include <linux/cdev.h>
#include <linux/uio_driver.h>
+#include <linux/xarray.h>
#define UIO_MAX_DEVICES (1U << MINORBITS)
static int uio_major;
static struct cdev *uio_cdev;
-static DEFINE_IDR(uio_idr);
+static DEFINE_XARRAY_ALLOC(uio_devs);
static const struct file_operations uio_fops;
-/* Protect idr accesses */
-static DEFINE_MUTEX(minor_lock);
-
/*
* attributes
*/
static int uio_get_minor(struct uio_device *idev)
{
- int retval = -ENOMEM;
-
- mutex_lock(&minor_lock);
- retval = idr_alloc(&uio_idr, idev, 0, UIO_MAX_DEVICES, GFP_KERNEL);
- if (retval >= 0) {
- idev->minor = retval;
- retval = 0;
- } else if (retval == -ENOSPC) {
+ int err;
+
+ err = xa_alloc(&uio_devs, &idev->minor, idev,
+ XA_LIMIT(0, UIO_MAX_DEVICES - 1), GFP_KERNEL);
+ if (err == -EBUSY) {
dev_err(&idev->dev, "too many uio devices\n");
- retval = -EINVAL;
+ err = -EINVAL;
}
- mutex_unlock(&minor_lock);
- return retval;
+
+ return err;
}
static void uio_free_minor(struct uio_device *idev)
{
- mutex_lock(&minor_lock);
- idr_remove(&uio_idr, idev->minor);
- mutex_unlock(&minor_lock);
+ xa_erase(&uio_devs, idev->minor);
}
/**
struct uio_listener *listener;
int ret = 0;
- mutex_lock(&minor_lock);
- idev = idr_find(&uio_idr, iminor(inode));
- mutex_unlock(&minor_lock);
+ idev = xa_load(&uio_devs, iminor(inode));
if (!idev) {
ret = -ENODEV;
goto out;
static void __exit uio_exit(void)
{
release_uio_class();
- idr_destroy(&uio_idr);
}
module_init(uio_init)