#include <linux/ioport.h>
#include <linux/acpi.h>
#include <linux/highmem.h>
-#include <linux/idr.h>
+#include <linux/xarray.h>
#include <linux/platform_data/x86/apple.h>
#define CREATE_TRACE_POINTS
#include "internals.h"
-static DEFINE_IDR(spi_master_idr);
+static DEFINE_XARRAY_ALLOC(spi_masters);
static void spidev_release(struct device *dev)
{
/*
* Used to protect add/del opertion for board_info list and
* spi_controller list, and their matching process
- * also used to protect object of type struct idr
*/
static DEFINE_MUTEX(board_lock);
struct device *dev = ctlr->dev.parent;
struct boardinfo *bi;
int status;
- int id, first_dynamic;
if (!dev)
return -ENODEV;
if (status)
return status;
+ if ((ctlr->bus_num < 0) && ctlr->dev.of_node) {
+ status = of_alias_get_id(ctlr->dev.of_node, "spi");
+ if (status >= 0)
+ ctlr->bus_num = status;
+ }
+
if (ctlr->bus_num >= 0) {
/* devices with a fixed bus num must check-in with the num */
mutex_lock(&board_lock);
- id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num,
- ctlr->bus_num + 1, GFP_KERNEL);
+ status = xa_insert(&spi_masters, ctlr->bus_num, ctlr,
+ GFP_KERNEL);
mutex_unlock(&board_lock);
- if (WARN(id < 0, "couldn't get idr"))
- return id == -ENOSPC ? -EBUSY : id;
- ctlr->bus_num = id;
- } else if (ctlr->dev.of_node) {
- /* allocate dynamic bus number using Linux idr */
- id = of_alias_get_id(ctlr->dev.of_node, "spi");
- if (id >= 0) {
- ctlr->bus_num = id;
- mutex_lock(&board_lock);
- id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num,
- ctlr->bus_num + 1, GFP_KERNEL);
- mutex_unlock(&board_lock);
- if (WARN(id < 0, "couldn't get idr"))
- return id == -ENOSPC ? -EBUSY : id;
- }
- }
- if (ctlr->bus_num < 0) {
- first_dynamic = of_alias_get_highest_id("spi");
+ } else {
+ int id, first_dynamic = of_alias_get_highest_id("spi");
+
if (first_dynamic < 0)
first_dynamic = 0;
else
first_dynamic++;
mutex_lock(&board_lock);
- id = idr_alloc(&spi_master_idr, ctlr, first_dynamic,
- 0, GFP_KERNEL);
+ status = xa_alloc(&spi_masters, &id, ctlr,
+ XA_LIMIT(first_dynamic, INT_MAX), GFP_KERNEL);
+ if (!status)
+ ctlr->bus_num = id;
mutex_unlock(&board_lock);
- if (WARN(id < 0, "couldn't get idr"))
- return id;
- ctlr->bus_num = id;
}
+ if (WARN(status < 0, "couldn't get id"))
+ return status;
+
INIT_LIST_HEAD(&ctlr->queue);
spin_lock_init(&ctlr->queue_lock);
spin_lock_init(&ctlr->bus_lock_spinlock);
if (status < 0) {
/* free bus id */
mutex_lock(&board_lock);
- idr_remove(&spi_master_idr, ctlr->bus_num);
+ xa_erase(&spi_masters, ctlr->bus_num);
mutex_unlock(&board_lock);
goto done;
}
device_del(&ctlr->dev);
/* free bus id */
mutex_lock(&board_lock);
- idr_remove(&spi_master_idr, ctlr->bus_num);
+ xa_erase(&spi_masters, ctlr->bus_num);
mutex_unlock(&board_lock);
goto done;
}
int id = ctlr->bus_num;
/* First make sure that this controller was ever added */
- mutex_lock(&board_lock);
- found = idr_find(&spi_master_idr, id);
- mutex_unlock(&board_lock);
+ found = xa_load(&spi_masters, id);
if (ctlr->queued) {
if (spi_destroy_queue(ctlr))
dev_err(&ctlr->dev, "queue remove failed\n");
/* free bus id */
mutex_lock(&board_lock);
if (found == ctlr)
- idr_remove(&spi_master_idr, id);
+ xa_erase(&spi_masters, id);
mutex_unlock(&board_lock);
}
EXPORT_SYMBOL_GPL(spi_unregister_controller);