This patch adds slim_prepare_txn() to allow controllers to prepare
controller specific transaction. If not each controllers will duplicate
the same code from core.

Signed-off-by: Srinivas Kandagatla <[email protected]>
---
 drivers/slimbus/messaging.c | 89 ++++++++++++++++++++++++++++++---------------
 drivers/slimbus/qcom-ctrl.c |  7 +++-
 drivers/slimbus/slimbus.h   |  2 +
 3 files changed, 68 insertions(+), 30 deletions(-)

diff --git a/drivers/slimbus/messaging.c b/drivers/slimbus/messaging.c
index 1c57b631031a..fd0788019357 100644
--- a/drivers/slimbus/messaging.c
+++ b/drivers/slimbus/messaging.c
@@ -55,6 +55,50 @@ void slim_msg_response(struct slim_controller *ctrl, u8 
*reply, u8 tid, u8 len)
 }
 EXPORT_SYMBOL_GPL(slim_msg_response);
 
+/**
+ * slim_prepare_txn() - Prepare a transaction
+ *
+ * @ctrl: Controller handle
+ * @txn: transaction to be prepared
+ * @done: completion for transaction
+ * @need_tid: flag to indicate if tid is required for this txn
+ *
+ * Called by controller to prepare a transaction
+ *
+ * Return: zero on success and error code on failures.
+ */
+int slim_prepare_txn(struct slim_controller *ctrl, struct slim_msg_txn *txn,
+                    struct completion *done, bool need_tid)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&ctrl->txn_lock, flags);
+
+       if (need_tid) {
+               ret = idr_alloc(&ctrl->tid_idr, txn, 0, SLIM_MAX_TIDS,
+                               GFP_ATOMIC);
+               if (ret < 0) {
+                       spin_unlock_irqrestore(&ctrl->txn_lock, flags);
+                       return ret;
+               }
+               txn->tid = ret;
+               txn->need_tid = true;
+       } else {
+               txn->need_tid = false;
+       }
+
+       if (!txn->msg->comp)
+               txn->comp = done;
+       else
+               txn->comp = txn->msg->comp;
+
+       spin_unlock_irqrestore(&ctrl->txn_lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(slim_prepare_txn);
+
 /**
  * slim_do_transfer() - Process a SLIMbus-messaging transaction
  *
@@ -70,10 +114,9 @@ EXPORT_SYMBOL_GPL(slim_msg_response);
  */
 int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn)
 {
-       DECLARE_COMPLETION_ONSTACK(done);
-       bool need_tid = false, clk_pause_msg = false;
+       bool clk_pause_msg = false;
        unsigned long flags;
-       int ret, tid, timeout;
+       int ret, timeout;
 
        /*
         * do not vote for runtime-PM if the transactions are part of clock
@@ -94,28 +137,8 @@ int slim_do_transfer(struct slim_controller *ctrl, struct 
slim_msg_txn *txn)
                }
        }
 
-       need_tid = slim_tid_txn(txn->mt, txn->mc);
-
-       if (need_tid) {
-               spin_lock_irqsave(&ctrl->txn_lock, flags);
-               tid = idr_alloc(&ctrl->tid_idr, txn, 0,
-                               SLIM_MAX_TIDS, GFP_ATOMIC);
-               txn->tid = tid;
-
-               if (!txn->msg->comp)
-                       txn->comp = &done;
-               else
-                       txn->comp = txn->comp;
-
-               spin_unlock_irqrestore(&ctrl->txn_lock, flags);
-
-               if (tid < 0)
-                       return tid;
-       }
-
        ret = ctrl->xfer_msg(ctrl, txn);
-
-       if (ret && need_tid && !txn->msg->comp) {
+       if (!ret && txn->need_tid && !txn->msg->comp) {
                unsigned long ms = txn->rl + HZ;
 
                timeout = wait_for_completion_timeout(txn->comp,
@@ -123,7 +146,7 @@ int slim_do_transfer(struct slim_controller *ctrl, struct 
slim_msg_txn *txn)
                if (!timeout) {
                        ret = -ETIMEDOUT;
                        spin_lock_irqsave(&ctrl->txn_lock, flags);
-                       idr_remove(&ctrl->tid_idr, tid);
+                       idr_remove(&ctrl->tid_idr, txn->tid);
                        spin_unlock_irqrestore(&ctrl->txn_lock, flags);
                }
        }
@@ -133,13 +156,12 @@ int slim_do_transfer(struct slim_controller *ctrl, struct 
slim_msg_txn *txn)
                        txn->mt, txn->mc, txn->la, ret);
 
 slim_xfer_err:
-       if (!clk_pause_msg && (!need_tid  || ret == -ETIMEDOUT)) {
+       if (!clk_pause_msg && (!txn->need_tid  || ret == -ETIMEDOUT)) {
                /*
                 * remove runtime-pm vote if this was TX only, or
                 * if there was error during this transaction
                 */
                pm_runtime_mark_last_busy(ctrl->dev);
-               pm_runtime_put_autosuspend(ctrl->dev);
        }
        return ret;
 }
@@ -169,6 +191,7 @@ static int slim_val_inf_sanity(struct slim_controller *ctrl,
                if (msg->rbuf != NULL && msg->wbuf != NULL)
                        return 0;
                break;
+
        }
 reterr:
        if (msg)
@@ -205,6 +228,8 @@ int slim_xfer_msg(struct slim_device *sbdev, struct 
slim_val_inf *msg,
        DEFINE_SLIM_LDEST_TXN(txn_stack, mc, 6, sbdev->laddr, msg);
        struct slim_msg_txn *txn = &txn_stack;
        struct slim_controller *ctrl = sbdev->ctrl;
+       DECLARE_COMPLETION_ONSTACK(done);
+       bool need_tid = false;
        int ret;
        u16 sl;
 
@@ -232,10 +257,16 @@ int slim_xfer_msg(struct slim_device *sbdev, struct 
slim_val_inf *msg,
                break;
        }
 
-       if (slim_tid_txn(txn->mt, txn->mc))
+       if (slim_tid_txn(txn->mt, txn->mc)) {
                txn->rl++;
+               need_tid = true;
+       }
 
-       return slim_do_transfer(ctrl, txn);
+       ret = slim_prepare_txn(ctrl, txn, &done, need_tid);
+       if (!ret)
+               return slim_do_transfer(ctrl, txn);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(slim_xfer_msg);
 
diff --git a/drivers/slimbus/qcom-ctrl.c b/drivers/slimbus/qcom-ctrl.c
index ffb46f915334..0783fb11c702 100644
--- a/drivers/slimbus/qcom-ctrl.c
+++ b/drivers/slimbus/qcom-ctrl.c
@@ -397,6 +397,7 @@ static int qcom_set_laddr(struct slim_controller *sctrl,
                u8 instance;
                u8 laddr;
        } __packed p;
+       DECLARE_COMPLETION_ONSTACK(done);
        struct slim_val_inf msg = {0};
        DEFINE_SLIM_EDEST_TXN(txn, SLIM_MSG_MC_ASSIGN_LOGICAL_ADDRESS,
                              10, laddr, &msg);
@@ -410,7 +411,11 @@ static int qcom_set_laddr(struct slim_controller *sctrl,
 
        msg.wbuf = (void *)&p;
        msg.num_bytes = 7;
-       ret = slim_do_transfer(&ctrl->ctrl, &txn);
+
+       ret = slim_prepare_txn(&ctrl->ctrl, &txn, &done,
+                              slim_tid_txn(txn.mt, txn.mc));
+       if (!ret)
+               ret = slim_do_transfer(&ctrl->ctrl, &txn);
 
        if (ret)
                dev_err(ctrl->dev, "set LA:0x%x failed:ret:%d\n",
diff --git a/drivers/slimbus/slimbus.h b/drivers/slimbus/slimbus.h
index c0450f469e07..67e774b2b2dd 100644
--- a/drivers/slimbus/slimbus.h
+++ b/drivers/slimbus/slimbus.h
@@ -241,6 +241,8 @@ int slim_unregister_controller(struct slim_controller 
*ctrl);
 void slim_msg_response(struct slim_controller *ctrl, u8 *reply, u8 tid, u8 l);
 int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn);
 int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup, u8 restart);
+int slim_prepare_txn(struct slim_controller *ctrl, struct slim_msg_txn *txn,
+                    struct completion *done, bool need_tid);
 
 static inline bool slim_tid_txn(u8 mt, u8 mc)
 {
-- 
2.16.2

Reply via email to