Sideband queue is a HW queue and has much faster completion time than
other queues.

With <5 us for read on average it is possible to use spin_lock to be
able to read/write sideband queue messages in the interrupt top half.

Add send queue lock/unlock operations and assign them based on the queue
type. Use ice_sq_spin_lock/unlock for sideband queue and
ice_sq_mutex_lock/unlock for other queues.

Reviewed-by: Milena Olech <[email protected]>
Signed-off-by: Karol Kolacinski <[email protected]>
---
 drivers/net/ethernet/intel/ice/ice_common.c   |   8 +-
 drivers/net/ethernet/intel/ice/ice_common.h   |   3 +-
 drivers/net/ethernet/intel/ice/ice_controlq.c | 105 +++++++++++++++---
 drivers/net/ethernet/intel/ice/ice_controlq.h |  19 +++-
 4 files changed, 111 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_common.c 
b/drivers/net/ethernet/intel/ice/ice_common.c
index 53b9b5b54187..058c93f6429b 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2018-2023, Intel Corporation. */
+/* Copyright (c) 2018-2025, Intel Corporation. */
 
 #include "ice_common.h"
 #include "ice_sched.h"
@@ -1627,8 +1627,10 @@ ice_sq_send_cmd_retry(struct ice_hw *hw, struct 
ice_ctl_q_info *cq,
 
                memcpy(desc, &desc_cpy, sizeof(desc_cpy));
 
-               msleep(ICE_SQ_SEND_DELAY_TIME_MS);
-
+               if (cq->qtype == ICE_CTL_Q_SB)
+                       udelay(ICE_CTL_Q_SQ_CMD_TIMEOUT_SPIN);
+               else
+                       fsleep(ICE_CTL_Q_SQ_CMD_TIMEOUT);
        } while (++idx < ICE_SQ_SEND_MAX_EXECUTE);
 
        return status;
diff --git a/drivers/net/ethernet/intel/ice/ice_common.h 
b/drivers/net/ethernet/intel/ice/ice_common.h
index 3f74570b99bf..b1c766cb4ec5 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.h
+++ b/drivers/net/ethernet/intel/ice/ice_common.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2018, Intel Corporation. */
+/* Copyright (c) 2018-2025, Intel Corporation. */
 
 #ifndef _ICE_COMMON_H_
 #define _ICE_COMMON_H_
@@ -15,6 +15,7 @@
 #include "ice_switch.h"
 #include "ice_fdir.h"
 
+#define ICE_SQ_SEND_ATOMIC_DELAY_TIME_US 100
 #define ICE_SQ_SEND_DELAY_TIME_MS      10
 #define ICE_SQ_SEND_MAX_EXECUTE                3
 
diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.c 
b/drivers/net/ethernet/intel/ice/ice_controlq.c
index fb7e1218797c..b873a9fb3f0b 100644
--- a/drivers/net/ethernet/intel/ice/ice_controlq.c
+++ b/drivers/net/ethernet/intel/ice/ice_controlq.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2018, Intel Corporation. */
+/* Copyright (c) 2018-2025, Intel Corporation. */
 
 #include "ice_common.h"
 
@@ -467,7 +467,7 @@ static int ice_shutdown_sq(struct ice_hw *hw, struct 
ice_ctl_q_info *cq)
        if (!cq->sq.count)
                return -EBUSY;
 
-       mutex_lock(&cq->sq_lock);
+       cq->sq_ops.lock(&cq->sq_lock);
 
        /* Stop processing of the control queue */
        wr32(hw, cq->sq.head, 0);
@@ -477,7 +477,7 @@ static int ice_shutdown_sq(struct ice_hw *hw, struct 
ice_ctl_q_info *cq)
        wr32(hw, cq->sq.bah, 0);
        cq->sq.count = 0;       /* to indicate uninitialized queue */
 
-       mutex_unlock(&cq->sq_lock);
+       cq->sq_ops.unlock(&cq->sq_lock);
 
        /* free ring buffers and the ring itself */
        ICE_FREE_CQ_BUFS(hw, cq, sq);
@@ -776,15 +776,75 @@ int ice_init_all_ctrlq(struct ice_hw *hw)
        return ice_init_ctrlq(hw, ICE_CTL_Q_MAILBOX);
 }
 
+/**
+ * ice_sq_spin_lock - Call spin_lock_irqsave for union ice_sq_lock
+ * @lock: lock handle
+ */
+static void ice_sq_spin_lock(union ice_sq_lock *lock)
+       __acquires(&lock->sq_spinlock)
+{
+       spin_lock_irqsave(&lock->sq_spinlock, lock->sq_flags);
+}
+
+/**
+ * ice_sq_spin_unlock - Call spin_unlock_irqrestore for union ice_sq_lock
+ * @lock: lock handle
+ */
+static void ice_sq_spin_unlock(union ice_sq_lock *lock)
+       __releases(&lock->sq_spinlock)
+{
+       spin_unlock_irqrestore(&lock->sq_spinlock, lock->sq_flags);
+}
+
+/**
+ * ice_sq_mutex_lock - Call mutex_lock for union ice_sq_lock
+ * @lock: lock handle
+ */
+static void ice_sq_mutex_lock(union ice_sq_lock *lock)
+       __acquires(&lock->sq_mutex)
+{
+       mutex_lock(&lock->sq_mutex);
+}
+
+/**
+ * ice_sq_mutex_unlock - Call mutex_unlock for union ice_sq_lock
+ * @lock: lock handle
+ */
+static void ice_sq_mutex_unlock(union ice_sq_lock *lock)
+       __releases(&lock->sq_mutex)
+{
+       mutex_unlock(&lock->sq_mutex);
+}
+
+static struct ice_sq_ops ice_spin_ops = {
+       .lock = ice_sq_spin_lock,
+       .unlock = ice_sq_spin_unlock,
+};
+
+static struct ice_sq_ops ice_mutex_ops = {
+       .lock = ice_sq_mutex_lock,
+       .unlock = ice_sq_mutex_unlock,
+};
+
 /**
  * ice_init_ctrlq_locks - Initialize locks for a control queue
+ * @hw: pointer to the hardware structure
  * @cq: pointer to the control queue
+ * @q_type: specific control queue type
  *
  * Initializes the send and receive queue locks for a given control queue.
  */
-static void ice_init_ctrlq_locks(struct ice_ctl_q_info *cq)
+static void ice_init_ctrlq_locks(struct ice_hw *hw, struct ice_ctl_q_info *cq,
+                                enum ice_ctl_q q_type)
 {
-       mutex_init(&cq->sq_lock);
+       if (q_type == ICE_CTL_Q_SB) {
+               cq->sq_ops = ice_spin_ops;
+               spin_lock_init(&cq->sq_lock.sq_spinlock);
+       } else {
+               cq->sq_ops = ice_mutex_ops;
+               mutex_init(&cq->sq_lock.sq_mutex);
+       }
+
        mutex_init(&cq->rq_lock);
 }
 
@@ -806,23 +866,26 @@ static void ice_init_ctrlq_locks(struct ice_ctl_q_info 
*cq)
  */
 int ice_create_all_ctrlq(struct ice_hw *hw)
 {
-       ice_init_ctrlq_locks(&hw->adminq);
+       ice_init_ctrlq_locks(hw, &hw->adminq, ICE_CTL_Q_ADMIN);
        if (ice_is_sbq_supported(hw))
-               ice_init_ctrlq_locks(&hw->sbq);
-       ice_init_ctrlq_locks(&hw->mailboxq);
+               ice_init_ctrlq_locks(hw, &hw->sbq, ICE_CTL_Q_SB);
+       ice_init_ctrlq_locks(hw, &hw->mailboxq, ICE_CTL_Q_MAILBOX);
 
        return ice_init_all_ctrlq(hw);
 }
 
 /**
  * ice_destroy_ctrlq_locks - Destroy locks for a control queue
+ * @hw: pointer to the hardware structure
  * @cq: pointer to the control queue
  *
  * Destroys the send and receive queue locks for a given control queue.
  */
-static void ice_destroy_ctrlq_locks(struct ice_ctl_q_info *cq)
+static void ice_destroy_ctrlq_locks(struct ice_hw *hw,
+                                   struct ice_ctl_q_info *cq)
 {
-       mutex_destroy(&cq->sq_lock);
+       if (cq->qtype != ICE_CTL_Q_SB)
+               mutex_destroy(&cq->sq_lock.sq_mutex);
        mutex_destroy(&cq->rq_lock);
 }
 
@@ -840,10 +903,10 @@ void ice_destroy_all_ctrlq(struct ice_hw *hw)
        /* shut down all the control queues first */
        ice_shutdown_all_ctrlq(hw, true);
 
-       ice_destroy_ctrlq_locks(&hw->adminq);
+       ice_destroy_ctrlq_locks(hw, &hw->adminq);
        if (ice_is_sbq_supported(hw))
-               ice_destroy_ctrlq_locks(&hw->sbq);
-       ice_destroy_ctrlq_locks(&hw->mailboxq);
+               ice_destroy_ctrlq_locks(hw, &hw->sbq);
+       ice_destroy_ctrlq_locks(hw, &hw->mailboxq);
 }
 
 /**
@@ -972,9 +1035,15 @@ static bool ice_sq_done(struct ice_hw *hw, struct 
ice_ctl_q_info *cq)
         */
        udelay(5);
 
-       return !rd32_poll_timeout(hw, cq->sq.head,
-                                 head, head == cq->sq.next_to_use,
-                                 20, ICE_CTL_Q_SQ_CMD_TIMEOUT);
+       if (cq->qtype == ICE_CTL_Q_SB)
+               return !read_poll_timeout_atomic(rd32, head,
+                                                head == cq->sq.next_to_use, 5,
+                                                ICE_CTL_Q_SQ_CMD_TIMEOUT_SPIN,
+                                                false, hw, cq->sq.head);
+
+       return !rd32_poll_timeout(hw, cq->sq.head, head,
+                                 head == cq->sq.next_to_use, 20,
+                                 ICE_CTL_Q_SQ_CMD_TIMEOUT);
 }
 
 /**
@@ -1011,7 +1080,7 @@ int ice_sq_send_cmd(struct ice_hw *hw, struct 
ice_ctl_q_info *cq,
        if (!buf && buf_size)
                return -EINVAL;
 
-       mutex_lock(&cq->sq_lock);
+       cq->sq_ops.lock(&cq->sq_lock);
        cq->sq_last_status = LIBIE_AQ_RC_OK;
 
        if (!cq->sq.count) {
@@ -1132,7 +1201,7 @@ int ice_sq_send_cmd(struct ice_hw *hw, struct 
ice_ctl_q_info *cq,
        }
 
 err:
-       mutex_unlock(&cq->sq_lock);
+       cq->sq_ops.unlock(&cq->sq_lock);
        return err;
 }
 
diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.h 
b/drivers/net/ethernet/intel/ice/ice_controlq.h
index 7c98d3a0314e..776ec57b2061 100644
--- a/drivers/net/ethernet/intel/ice/ice_controlq.h
+++ b/drivers/net/ethernet/intel/ice/ice_controlq.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2018, Intel Corporation. */
+/* Copyright (c) 2018-2025, Intel Corporation. */
 
 #ifndef _ICE_CONTROLQ_H_
 #define _ICE_CONTROLQ_H_
@@ -44,6 +44,7 @@ enum ice_ctl_q {
 
 /* Control Queue timeout settings - max delay 1s */
 #define ICE_CTL_Q_SQ_CMD_TIMEOUT       USEC_PER_SEC
+#define ICE_CTL_Q_SQ_CMD_TIMEOUT_SPIN  100
 #define ICE_CTL_Q_ADMIN_INIT_TIMEOUT   10    /* Count 10 times */
 #define ICE_CTL_Q_ADMIN_INIT_MSEC      100   /* Check every 100msec */
 
@@ -88,6 +89,19 @@ struct ice_rq_event_info {
        u8 *msg_buf;
 };
 
+union ice_sq_lock {
+       struct mutex sq_mutex;  /* Non-atomic SQ lock. */
+       struct {
+               spinlock_t sq_spinlock; /* Atomic SQ lock. */
+               unsigned long sq_flags;         /* Send queue IRQ flags. */
+       };
+};
+
+struct ice_sq_ops {
+       void (*lock)(union ice_sq_lock *lock);
+       void (*unlock)(union ice_sq_lock *lock);
+};
+
 /* Control Queue information */
 struct ice_ctl_q_info {
        enum ice_ctl_q qtype;
@@ -98,7 +112,8 @@ struct ice_ctl_q_info {
        u16 rq_buf_size;                /* receive queue buffer size */
        u16 sq_buf_size;                /* send queue buffer size */
        enum libie_aq_err sq_last_status;       /* last status on send queue */
-       struct mutex sq_lock;           /* Send queue lock */
+       union ice_sq_lock sq_lock;      /* Send queue lock. */
+       struct ice_sq_ops sq_ops;       /* Send queue ops. */
        struct mutex rq_lock;           /* Receive queue lock */
 };
 
-- 
2.49.0

Reply via email to