#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/init.h>
-#include <linux/idr.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
ctrl->max_cg = SLIM_MAX_CLK_GEAR;
ida_init(&ctrl->laddr_ida);
- idr_init(&ctrl->tid_idr);
+ xa_init_flags(&ctrl->tids, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
+ ctrl->tid_next = 0;
mutex_init(&ctrl->lock);
mutex_init(&ctrl->sched.m_reconf);
init_completion(&ctrl->sched.pause_comp);
- spin_lock_init(&ctrl->txn_lock);
dev_dbg(ctrl->dev, "Bus [%s] registered:dev:%p\n",
ctrl->name, ctrl->dev);
{
struct slim_msg_txn *txn;
struct slim_val_inf *msg;
- unsigned long flags;
-
- spin_lock_irqsave(&ctrl->txn_lock, flags);
- txn = idr_find(&ctrl->tid_idr, tid);
- spin_unlock_irqrestore(&ctrl->txn_lock, flags);
+ txn = xa_load(&ctrl->tids, tid);
if (txn == NULL)
return;
int slim_alloc_txn_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn)
{
unsigned long flags;
- int ret = 0;
+ int ret;
+ u32 tid;
+
+ xa_lock_irqsave(&ctrl->tids, flags);
+ ret = __xa_alloc_cyclic(&ctrl->tids, &tid, txn,
+ XA_LIMIT(0, SLIM_TID_MAX), &ctrl->tid_next, GFP_ATOMIC);
+ xa_unlock_irqrestore(&ctrl->tids, flags);
- spin_lock_irqsave(&ctrl->txn_lock, flags);
- ret = idr_alloc_cyclic(&ctrl->tid_idr, txn, 0,
- SLIM_MAX_TIDS, GFP_ATOMIC);
- if (ret < 0) {
- spin_unlock_irqrestore(&ctrl->txn_lock, flags);
+ if (ret < 0)
return ret;
- }
- txn->tid = ret;
- spin_unlock_irqrestore(&ctrl->txn_lock, flags);
+
+ txn->tid = tid;
return 0;
}
EXPORT_SYMBOL_GPL(slim_alloc_txn_tid);
/**
- * slim_free_txn_tid() - Freee tid of txn
+ * slim_free_txn_tid() - Free tid of txn
*
* @ctrl: Controller handle
* @txn: transaction whose tid should be freed
{
unsigned long flags;
- spin_lock_irqsave(&ctrl->txn_lock, flags);
- idr_remove(&ctrl->tid_idr, txn->tid);
- spin_unlock_irqrestore(&ctrl->txn_lock, flags);
+ xa_lock_irqsave(&ctrl->tids, flags);
+ __xa_erase(&ctrl->tids, txn->tid);
+ xa_unlock_irqrestore(&ctrl->tids, flags);
}
EXPORT_SYMBOL_GPL(slim_free_txn_tid);
*/
int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup, u8 restart)
{
- int i, ret = 0;
- unsigned long flags;
+ int ret = 0;
struct slim_sched *sched = &ctrl->sched;
struct slim_val_inf msg = {0, 0, NULL, NULL};
return 0;
}
- spin_lock_irqsave(&ctrl->txn_lock, flags);
- for (i = 0; i < SLIM_MAX_TIDS; i++) {
- /* Pending response for a message */
- if (idr_find(&ctrl->tid_idr, i)) {
- spin_unlock_irqrestore(&ctrl->txn_lock, flags);
- mutex_unlock(&sched->m_reconf);
- return -EBUSY;
- }
+ if (!xa_empty(&ctrl->tids)) {
+ mutex_unlock(&sched->m_reconf);
+ return -EBUSY;
}
- spin_unlock_irqrestore(&ctrl->txn_lock, flags);
sched->clk_state = SLIM_CLK_ENTERING_PAUSE;
#include <linux/mutex.h>
#include <linux/completion.h>
#include <linux/slimbus.h>
+#include <linux/xarray.h>
/* Standard values per SLIMbus spec needed by controllers and devices */
#define SLIM_CL_PER_SUPERFRAME 6144
/* Manager's logical address is set to 0xFF per spec */
#define SLIM_LA_MANAGER 0xFF
-#define SLIM_MAX_TIDS 256
+#define SLIM_TID_MAX 255
/**
* struct slim_framer - Represents SLIMbus framer.
* Every controller may have multiple framers. There is 1 active framer device
* @a_framer: Active framer which is clocking the bus managed by this controller
* @lock: Mutex protecting controller data structures
* @devices: Slim device list
- * @tid_idr: tid id allocator
- * @txn_lock: Lock to protect table of transactions
+ * @tids: tid id allocator
+ * @tid_next: Next tid to allocate
* @sched: scheduler structure used by the controller
* @xfer_msg: Transfer a message on this controller (this can be a broadcast
* control/status message like data channel setup, or a unicast message
int min_cg;
int max_cg;
int clkgear;
+ u32 tid_next;
struct ida laddr_ida;
struct slim_framer *a_framer;
struct mutex lock;
struct list_head devices;
- struct idr tid_idr;
- spinlock_t txn_lock;
+ struct xarray tids;
struct slim_sched sched;
int (*xfer_msg)(struct slim_controller *ctrl,
struct slim_msg_txn *tx);