common/cnxk: add lower bound check for SSO resources
[dpdk.git] / drivers / net / ice / base / ice_controlq.c
index 41c8c7e..cdd067c 100644 (file)
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2020
+ * Copyright(c) 2001-2021 Intel Corporation
  */
 
 #include "ice_common.h"
@@ -54,6 +54,21 @@ static void ice_mailbox_init_regs(struct ice_hw *hw)
        ICE_CQ_INIT_REGS(cq, PF_MBX);
 }
 
+/**
+ * ice_sb_init_regs - Initialize Sideband registers
+ * @hw: pointer to the hardware structure
+ *
+ * This assumes the alloc_sq and alloc_rq functions have already been called
+ */
+static void ice_sb_init_regs(struct ice_hw *hw)
+{
+       struct ice_ctl_q_info *cq = &hw->sbq;
+
+       ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
+
+       ICE_CQ_INIT_REGS(cq, PF_SB);
+}
+
 /**
  * ice_check_sq_alive
  * @hw: pointer to the HW struct
@@ -182,7 +197,9 @@ unwind_alloc_rq_bufs:
        i--;
        for (; i >= 0; i--)
                ice_free_dma_mem(hw, &cq->rq.r.rq_bi[i]);
+       cq->rq.r.rq_bi = NULL;
        ice_free(hw, cq->rq.dma_head);
+       cq->rq.dma_head = NULL;
 
        return ICE_ERR_NO_MEMORY;
 }
@@ -220,7 +237,9 @@ unwind_alloc_sq_bufs:
        i--;
        for (; i >= 0; i--)
                ice_free_dma_mem(hw, &cq->sq.r.sq_bi[i]);
+       cq->sq.r.sq_bi = NULL;
        ice_free(hw, cq->sq.dma_head);
+       cq->sq.dma_head = NULL;
 
        return ICE_ERR_NO_MEMORY;
 }
@@ -279,6 +298,24 @@ ice_cfg_rq_regs(struct ice_hw *hw, struct ice_ctl_q_info *cq)
        return ICE_SUCCESS;
 }
 
+#define ICE_FREE_CQ_BUFS(hw, qi, ring)                                 \
+do {                                                                   \
+       /* free descriptors */                                          \
+       if ((qi)->ring.r.ring##_bi) {                                   \
+               int i;                                                  \
+                                                                       \
+               for (i = 0; i < (qi)->num_##ring##_entries; i++)        \
+                       if ((qi)->ring.r.ring##_bi[i].pa)               \
+                               ice_free_dma_mem((hw),                  \
+                                       &(qi)->ring.r.ring##_bi[i]);    \
+       }                                                               \
+       /* free the buffer info list */                                 \
+       if ((qi)->ring.cmd_buf)                                         \
+               ice_free(hw, (qi)->ring.cmd_buf);                       \
+       /* free DMA head */                                             \
+       ice_free(hw, (qi)->ring.dma_head);                              \
+} while (0)
+
 /**
  * ice_init_sq - main initialization routine for Control ATQ
  * @hw: pointer to the hardware structure
@@ -334,6 +371,7 @@ static enum ice_status ice_init_sq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
        goto init_ctrlq_exit;
 
 init_ctrlq_free_rings:
+       ICE_FREE_CQ_BUFS(hw, cq, sq);
        ice_free_cq_ring(hw, &cq->sq);
 
 init_ctrlq_exit:
@@ -395,27 +433,13 @@ static enum ice_status ice_init_rq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
        goto init_ctrlq_exit;
 
 init_ctrlq_free_rings:
+       ICE_FREE_CQ_BUFS(hw, cq, rq);
        ice_free_cq_ring(hw, &cq->rq);
 
 init_ctrlq_exit:
        return ret_code;
 }
 
-#define ICE_FREE_CQ_BUFS(hw, qi, ring)                                 \
-do {                                                                   \
-       int i;                                                          \
-       /* free descriptors */                                          \
-       for (i = 0; i < (qi)->num_##ring##_entries; i++)                \
-               if ((qi)->ring.r.ring##_bi[i].pa)                       \
-                       ice_free_dma_mem((hw),                          \
-                                        &(qi)->ring.r.ring##_bi[i]);   \
-       /* free the buffer info list */                                 \
-       if ((qi)->ring.cmd_buf)                                         \
-               ice_free(hw, (qi)->ring.cmd_buf);                       \
-       /* free DMA head */                                             \
-       ice_free(hw, (qi)->ring.dma_head);                              \
-} while (0)
-
 /**
  * ice_shutdown_sq - shutdown the Control ATQ
  * @hw: pointer to the hardware structure
@@ -575,6 +599,10 @@ static enum ice_status ice_init_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type)
                ice_adminq_init_regs(hw);
                cq = &hw->adminq;
                break;
+       case ICE_CTL_Q_SB:
+               ice_sb_init_regs(hw);
+               cq = &hw->sbq;
+               break;
        case ICE_CTL_Q_MAILBOX:
                ice_mailbox_init_regs(hw);
                cq = &hw->mailboxq;
@@ -611,6 +639,18 @@ init_ctrlq_free_sq:
        return ret_code;
 }
 
+/**
+ * ice_is_sbq_supported - is the sideband queue supported
+ * @hw: pointer to the hardware structure
+ *
+ * Returns true if the sideband control queue interface is
+ * supported for the device, false otherwise
+ */
+static bool ice_is_sbq_supported(struct ice_hw *hw)
+{
+       return ice_is_generic_mac(hw);
+}
+
 /**
  * ice_shutdown_ctrlq - shutdown routine for any control queue
  * @hw: pointer to the hardware structure
@@ -630,6 +670,9 @@ static void ice_shutdown_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type)
                if (ice_check_sq_alive(hw, cq))
                        ice_aq_q_shutdown(hw, true);
                break;
+       case ICE_CTL_Q_SB:
+               cq = &hw->sbq;
+               break;
        case ICE_CTL_Q_MAILBOX:
                cq = &hw->mailboxq;
                break;
@@ -654,6 +697,9 @@ void ice_shutdown_all_ctrlq(struct ice_hw *hw)
        ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
        /* Shutdown FW admin queue */
        ice_shutdown_ctrlq(hw, ICE_CTL_Q_ADMIN);
+       /* Shutdown PHY Sideband */
+       if (ice_is_sbq_supported(hw))
+               ice_shutdown_ctrlq(hw, ICE_CTL_Q_SB);
        /* Shutdown PF-VF Mailbox */
        ice_shutdown_ctrlq(hw, ICE_CTL_Q_MAILBOX);
 }
@@ -688,14 +734,22 @@ enum ice_status ice_init_all_ctrlq(struct ice_hw *hw)
                if (status != ICE_ERR_AQ_FW_CRITICAL)
                        break;
 
-               ice_debug(hw, ICE_DBG_AQ_MSG,
-                         "Retry Admin Queue init due to FW critical error\n");
+               ice_debug(hw, ICE_DBG_AQ_MSG, "Retry Admin Queue init due to FW critical error\n");
                ice_shutdown_ctrlq(hw, ICE_CTL_Q_ADMIN);
                ice_msec_delay(ICE_CTL_Q_ADMIN_INIT_MSEC, true);
        } while (retry++ < ICE_CTL_Q_ADMIN_INIT_TIMEOUT);
 
        if (status)
                return status;
+       /* sideband control queue (SBQ) interface is not supported on some
+        * devices. Initialize if supported, else fallback to the admin queue
+        * interface
+        */
+       if (ice_is_sbq_supported(hw)) {
+               status = ice_init_ctrlq(hw, ICE_CTL_Q_SB);
+               if (status)
+                       return status;
+       }
        /* Init Mailbox queue */
        return ice_init_ctrlq(hw, ICE_CTL_Q_MAILBOX);
 }
@@ -731,6 +785,8 @@ static void ice_init_ctrlq_locks(struct ice_ctl_q_info *cq)
 enum ice_status ice_create_all_ctrlq(struct ice_hw *hw)
 {
        ice_init_ctrlq_locks(&hw->adminq);
+       if (ice_is_sbq_supported(hw))
+               ice_init_ctrlq_locks(&hw->sbq);
        ice_init_ctrlq_locks(&hw->mailboxq);
 
        return ice_init_all_ctrlq(hw);
@@ -742,8 +798,7 @@ enum ice_status ice_create_all_ctrlq(struct ice_hw *hw)
  *
  * 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_ctl_q_info *cq)
 {
        ice_destroy_lock(&cq->sq_lock);
        ice_destroy_lock(&cq->rq_lock);
@@ -764,6 +819,8 @@ void ice_destroy_all_ctrlq(struct ice_hw *hw)
        ice_shutdown_all_ctrlq(hw);
 
        ice_destroy_ctrlq_locks(&hw->adminq);
+       if (ice_is_sbq_supported(hw))
+               ice_destroy_ctrlq_locks(&hw->sbq);
        ice_destroy_ctrlq_locks(&hw->mailboxq);
 }
 
@@ -785,8 +842,7 @@ static u16 ice_clean_sq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
        details = ICE_CTL_Q_DETAILS(*sq, ntc);
 
        while (rd32(hw, cq->sq.head) != ntc) {
-               ice_debug(hw, ICE_DBG_AQ_MSG,
-                         "ntc %d head %d.\n", ntc, rd32(hw, cq->sq.head));
+               ice_debug(hw, ICE_DBG_AQ_MSG, "ntc %d head %d.\n", ntc, rd32(hw, cq->sq.head));
                ice_memset(desc, 0, sizeof(*desc), ICE_DMA_MEM);
                ice_memset(details, 0, sizeof(*details), ICE_NONDMA_MEM);
                ntc++;
@@ -824,8 +880,7 @@ static void ice_debug_cq(struct ice_hw *hw, void *desc, void *buf, u16 buf_len)
        datalen = LE16_TO_CPU(cq_desc->datalen);
        flags = LE16_TO_CPU(cq_desc->flags);
 
-       ice_debug(hw, ICE_DBG_AQ_DESC,
-                 "CQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
+       ice_debug(hw, ICE_DBG_AQ_DESC, "CQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
                  LE16_TO_CPU(cq_desc->opcode), flags, datalen,
                  LE16_TO_CPU(cq_desc->retval));
        ice_debug(hw, ICE_DBG_AQ_DESC, "\tcookie (h,l) 0x%08X 0x%08X\n",
@@ -877,7 +932,7 @@ static bool ice_sq_done(struct ice_hw *hw, struct ice_ctl_q_info *cq)
  * This is the main send command routine for the ATQ. It runs the queue,
  * cleans the queue, etc.
  */
-static enum ice_status
+enum ice_status
 ice_sq_send_cmd_nolock(struct ice_hw *hw, struct ice_ctl_q_info *cq,
                       struct ice_aq_desc *desc, void *buf, u16 buf_size,
                       struct ice_sq_cd *cd)
@@ -898,8 +953,7 @@ ice_sq_send_cmd_nolock(struct ice_hw *hw, struct ice_ctl_q_info *cq,
        cq->sq_last_status = ICE_AQ_RC_OK;
 
        if (!cq->sq.count) {
-               ice_debug(hw, ICE_DBG_AQ_MSG,
-                         "Control Send queue not initialized.\n");
+               ice_debug(hw, ICE_DBG_AQ_MSG, "Control Send queue not initialized.\n");
                status = ICE_ERR_AQ_EMPTY;
                goto sq_send_command_error;
        }
@@ -911,8 +965,7 @@ ice_sq_send_cmd_nolock(struct ice_hw *hw, struct ice_ctl_q_info *cq,
 
        if (buf) {
                if (buf_size > cq->sq_buf_size) {
-                       ice_debug(hw, ICE_DBG_AQ_MSG,
-                                 "Invalid buffer size for Control Send queue: %d.\n",
+                       ice_debug(hw, ICE_DBG_AQ_MSG, "Invalid buffer size for Control Send queue: %d.\n",
                                  buf_size);
                        status = ICE_ERR_INVAL_SIZE;
                        goto sq_send_command_error;
@@ -925,8 +978,7 @@ ice_sq_send_cmd_nolock(struct ice_hw *hw, struct ice_ctl_q_info *cq,
 
        val = rd32(hw, cq->sq.head);
        if (val >= cq->num_sq_entries) {
-               ice_debug(hw, ICE_DBG_AQ_MSG,
-                         "head overrun at %d in the Control Send Queue ring\n",
+               ice_debug(hw, ICE_DBG_AQ_MSG, "head overrun at %d in the Control Send Queue ring\n",
                          val);
                status = ICE_ERR_AQ_EMPTY;
                goto sq_send_command_error;
@@ -944,8 +996,7 @@ ice_sq_send_cmd_nolock(struct ice_hw *hw, struct ice_ctl_q_info *cq,
         * called in a separate thread in case of asynchronous completions.
         */
        if (ice_clean_sq(hw, cq) == 0) {
-               ice_debug(hw, ICE_DBG_AQ_MSG,
-                         "Error: Control Send Queue is full.\n");
+               ice_debug(hw, ICE_DBG_AQ_MSG, "Error: Control Send Queue is full.\n");
                status = ICE_ERR_AQ_FULL;
                goto sq_send_command_error;
        }
@@ -974,8 +1025,7 @@ ice_sq_send_cmd_nolock(struct ice_hw *hw, struct ice_ctl_q_info *cq,
        }
 
        /* Debug desc and buffer */
-       ice_debug(hw, ICE_DBG_AQ_DESC,
-                 "ATQ: Control Send queue desc and buffer:\n");
+       ice_debug(hw, ICE_DBG_AQ_DESC, "ATQ: Control Send queue desc and buffer:\n");
 
        ice_debug_cq(hw, (void *)desc_on_ring, buf, buf_size);
 
@@ -1001,8 +1051,7 @@ ice_sq_send_cmd_nolock(struct ice_hw *hw, struct ice_ctl_q_info *cq,
                        u16 copy_size = LE16_TO_CPU(desc->datalen);
 
                        if (copy_size > buf_size) {
-                               ice_debug(hw, ICE_DBG_AQ_MSG,
-                                         "Return len %d > than buf len %d\n",
+                               ice_debug(hw, ICE_DBG_AQ_MSG, "Return len %d > than buf len %d\n",
                                          copy_size, buf_size);
                                status = ICE_ERR_AQ_ERROR;
                        } else {
@@ -1012,8 +1061,7 @@ ice_sq_send_cmd_nolock(struct ice_hw *hw, struct ice_ctl_q_info *cq,
                }
                retval = LE16_TO_CPU(desc->retval);
                if (retval) {
-                       ice_debug(hw, ICE_DBG_AQ_MSG,
-                                 "Control Send Queue command 0x%04X completed with error 0x%X\n",
+                       ice_debug(hw, ICE_DBG_AQ_MSG, "Control Send Queue command 0x%04X completed with error 0x%X\n",
                                  LE16_TO_CPU(desc->opcode),
                                  retval);
 
@@ -1026,8 +1074,7 @@ ice_sq_send_cmd_nolock(struct ice_hw *hw, struct ice_ctl_q_info *cq,
                cq->sq_last_status = (enum ice_aq_err)retval;
        }
 
-       ice_debug(hw, ICE_DBG_AQ_MSG,
-                 "ATQ: desc and buffer writeback:\n");
+       ice_debug(hw, ICE_DBG_AQ_MSG, "ATQ: desc and buffer writeback:\n");
 
        ice_debug_cq(hw, (void *)desc, buf, buf_size);
 
@@ -1040,12 +1087,10 @@ ice_sq_send_cmd_nolock(struct ice_hw *hw, struct ice_ctl_q_info *cq,
        if (!cmd_completed) {
                if (rd32(hw, cq->rq.len) & cq->rq.len_crit_mask ||
                    rd32(hw, cq->sq.len) & cq->sq.len_crit_mask) {
-                       ice_debug(hw, ICE_DBG_AQ_MSG,
-                                 "Critical FW error.\n");
+                       ice_debug(hw, ICE_DBG_AQ_MSG, "Critical FW error.\n");
                        status = ICE_ERR_AQ_FW_CRITICAL;
                } else {
-                       ice_debug(hw, ICE_DBG_AQ_MSG,
-                                 "Control Send Queue Writeback timeout.\n");
+                       ice_debug(hw, ICE_DBG_AQ_MSG, "Control Send Queue Writeback timeout.\n");
                        status = ICE_ERR_AQ_TIMEOUT;
                }
        }
@@ -1058,7 +1103,7 @@ sq_send_command_error:
  * ice_sq_send_cmd - send command to Control Queue (ATQ)
  * @hw: pointer to the HW struct
  * @cq: pointer to the specific Control queue
- * @desc: prefilled descriptor describing the command (non DMA mem)
+ * @desc: prefilled descriptor describing the command
  * @buf: buffer to use for indirect commands (or NULL for direct commands)
  * @buf_size: size of buffer for indirect commands (or 0 for direct commands)
  * @cd: pointer to command details structure
@@ -1115,6 +1160,7 @@ ice_clean_rq_elem(struct ice_hw *hw, struct ice_ctl_q_info *cq,
                  struct ice_rq_event_info *e, u16 *pending)
 {
        u16 ntc = cq->rq.next_to_clean;
+       enum ice_aq_err rq_last_status;
        enum ice_status ret_code = ICE_SUCCESS;
        struct ice_aq_desc *desc;
        struct ice_dma_mem *bi;
@@ -1130,8 +1176,7 @@ ice_clean_rq_elem(struct ice_hw *hw, struct ice_ctl_q_info *cq,
        ice_acquire_lock(&cq->rq_lock);
 
        if (!cq->rq.count) {
-               ice_debug(hw, ICE_DBG_AQ_MSG,
-                         "Control Receive queue not initialized.\n");
+               ice_debug(hw, ICE_DBG_AQ_MSG, "Control Receive queue not initialized.\n");
                ret_code = ICE_ERR_AQ_EMPTY;
                goto clean_rq_elem_err;
        }
@@ -1149,14 +1194,12 @@ ice_clean_rq_elem(struct ice_hw *hw, struct ice_ctl_q_info *cq,
        desc = ICE_CTL_Q_DESC(cq->rq, ntc);
        desc_idx = ntc;
 
-       cq->rq_last_status = (enum ice_aq_err)LE16_TO_CPU(desc->retval);
+       rq_last_status = (enum ice_aq_err)LE16_TO_CPU(desc->retval);
        flags = LE16_TO_CPU(desc->flags);
        if (flags & ICE_AQ_FLAG_ERR) {
                ret_code = ICE_ERR_AQ_ERROR;
-               ice_debug(hw, ICE_DBG_AQ_MSG,
-                         "Control Receive Queue Event 0x%04X received with error 0x%X\n",
-                         LE16_TO_CPU(desc->opcode),
-                         cq->rq_last_status);
+               ice_debug(hw, ICE_DBG_AQ_MSG, "Control Receive Queue Event 0x%04X received with error 0x%X\n",
+                         LE16_TO_CPU(desc->opcode), rq_last_status);
        }
        ice_memcpy(&e->desc, desc, sizeof(e->desc), ICE_DMA_TO_NONDMA);
        datalen = LE16_TO_CPU(desc->datalen);
@@ -1167,8 +1210,7 @@ ice_clean_rq_elem(struct ice_hw *hw, struct ice_ctl_q_info *cq,
 
        ice_debug(hw, ICE_DBG_AQ_DESC, "ARQ: desc and buffer:\n");
 
-       ice_debug_cq(hw, (void *)desc, e->msg_buf,
-                    cq->rq_buf_size);
+       ice_debug_cq(hw, (void *)desc, e->msg_buf, cq->rq_buf_size);
 
        /* Restore the original datalen and buffer address in the desc,
         * FW updates datalen to indicate the event message size