net/qede/base: prevent race condition during unload
[dpdk.git] / drivers / net / qede / base / ecore_dev.c
index d5a8a90..d8e4ca2 100644 (file)
@@ -146,8 +146,11 @@ void ecore_resc_free(struct ecore_dev *p_dev)
 {
        int i;
 
-       if (IS_VF(p_dev))
+       if (IS_VF(p_dev)) {
+               for_each_hwfn(p_dev, i)
+                       ecore_l2_free(&p_dev->hwfns[i]);
                return;
+       }
 
        OSAL_FREE(p_dev, p_dev->fw_data);
 
@@ -163,6 +166,7 @@ void ecore_resc_free(struct ecore_dev *p_dev)
                ecore_consq_free(p_hwfn);
                ecore_int_free(p_hwfn);
                ecore_iov_free(p_hwfn);
+               ecore_l2_free(p_hwfn);
                ecore_dmae_info_free(p_hwfn);
                ecore_dcbx_info_free(p_hwfn, p_hwfn->p_dcbx_info);
                /* @@@TBD Flush work-queue ? */
@@ -839,8 +843,14 @@ enum _ecore_status_t ecore_resc_alloc(struct ecore_dev *p_dev)
        enum _ecore_status_t rc = ECORE_SUCCESS;
        int i;
 
-       if (IS_VF(p_dev))
+       if (IS_VF(p_dev)) {
+               for_each_hwfn(p_dev, i) {
+                       rc = ecore_l2_alloc(&p_dev->hwfns[i]);
+                       if (rc != ECORE_SUCCESS)
+                               return rc;
+               }
                return rc;
+       }
 
        p_dev->fw_data = OSAL_ZALLOC(p_dev, GFP_KERNEL,
                                     sizeof(*p_dev->fw_data));
@@ -961,6 +971,10 @@ enum _ecore_status_t ecore_resc_alloc(struct ecore_dev *p_dev)
                if (rc)
                        goto alloc_err;
 
+               rc = ecore_l2_alloc(p_hwfn);
+               if (rc != ECORE_SUCCESS)
+                       goto alloc_err;
+
                /* DMA info initialization */
                rc = ecore_dmae_info_alloc(p_hwfn);
                if (rc) {
@@ -999,8 +1013,11 @@ void ecore_resc_setup(struct ecore_dev *p_dev)
 {
        int i;
 
-       if (IS_VF(p_dev))
+       if (IS_VF(p_dev)) {
+               for_each_hwfn(p_dev, i)
+                       ecore_l2_setup(&p_dev->hwfns[i]);
                return;
+       }
 
        for_each_hwfn(p_dev, i) {
                struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
@@ -1018,6 +1035,7 @@ void ecore_resc_setup(struct ecore_dev *p_dev)
 
                ecore_int_setup(p_hwfn, p_hwfn->p_main_ptt);
 
+               ecore_l2_setup(p_hwfn);
                ecore_iov_setup(p_hwfn, p_hwfn->p_main_ptt);
        }
 }
@@ -2032,7 +2050,7 @@ enum _ecore_status_t ecore_hw_init(struct ecore_dev *p_dev,
 
                if (mfw_rc != ECORE_SUCCESS) {
                        DP_NOTICE(p_hwfn, true,
-                                 "Failed sending LOAD_DONE command\n");
+                                 "Failed sending LOAD_DONE command\n");
                        return mfw_rc;
                }
 
@@ -2121,32 +2139,77 @@ void ecore_hw_timers_stop_all(struct ecore_dev *p_dev)
        }
 }
 
+static enum _ecore_status_t ecore_verify_reg_val(struct ecore_hwfn *p_hwfn,
+                                                struct ecore_ptt *p_ptt,
+                                                u32 addr, u32 expected_val)
+{
+       u32 val = ecore_rd(p_hwfn, p_ptt, addr);
+
+       if (val != expected_val) {
+               DP_NOTICE(p_hwfn, true,
+                         "Value at address 0x%08x is 0x%08x while the expected value is 0x%08x\n",
+                         addr, val, expected_val);
+               return ECORE_UNKNOWN_ERROR;
+       }
+
+       return ECORE_SUCCESS;
+}
+
 enum _ecore_status_t ecore_hw_stop(struct ecore_dev *p_dev)
 {
-       enum _ecore_status_t rc = ECORE_SUCCESS, t_rc;
+       struct ecore_hwfn *p_hwfn;
+       struct ecore_ptt *p_ptt;
+       enum _ecore_status_t rc, rc2 = ECORE_SUCCESS;
        int j;
 
        for_each_hwfn(p_dev, j) {
-               struct ecore_hwfn *p_hwfn = &p_dev->hwfns[j];
-               struct ecore_ptt *p_ptt = p_hwfn->p_main_ptt;
+               p_hwfn = &p_dev->hwfns[j];
+               p_ptt = p_hwfn->p_main_ptt;
 
                DP_VERBOSE(p_hwfn, ECORE_MSG_IFDOWN, "Stopping hw/fw\n");
 
                if (IS_VF(p_dev)) {
                        ecore_vf_pf_int_cleanup(p_hwfn);
+                       rc = ecore_vf_pf_reset(p_hwfn);
+                       if (rc != ECORE_SUCCESS) {
+                               DP_NOTICE(p_hwfn, true,
+                                         "ecore_vf_pf_reset failed. rc = %d.\n",
+                                         rc);
+                               rc2 = ECORE_UNKNOWN_ERROR;
+                       }
                        continue;
                }
 
                /* mark the hw as uninitialized... */
                p_hwfn->hw_init_done = false;
 
+               /* Send unload command to MCP */
+               if (!p_dev->recov_in_prog) {
+                       rc = ecore_mcp_unload_req(p_hwfn, p_ptt);
+                       if (rc != ECORE_SUCCESS) {
+                               DP_NOTICE(p_hwfn, true,
+                                         "Failed sending a UNLOAD_REQ command. rc = %d.\n",
+                                         rc);
+                               rc2 = ECORE_UNKNOWN_ERROR;
+                       }
+               }
+
+               OSAL_DPC_SYNC(p_hwfn);
+
+               /* After this point no MFW attentions are expected, e.g. prevent
+                * race between pf stop and dcbx pf update.
+                */
+
                rc = ecore_sp_pf_stop(p_hwfn);
-               if (rc)
+               if (rc != ECORE_SUCCESS) {
                        DP_NOTICE(p_hwfn, true,
-                                 "Failed to close PF against FW. Continue to stop HW to prevent illegal host access by the device\n");
+                                 "Failed to close PF against FW [rc = %d]. Continue to stop HW to prevent illegal host access by the device.\n",
+                                 rc);
+                       rc2 = ECORE_UNKNOWN_ERROR;
+               }
 
                /* perform debug action after PF stop was sent */
-               OSAL_AFTER_PF_STOP((void *)p_hwfn->p_dev, p_hwfn->my_id);
+               OSAL_AFTER_PF_STOP((void *)p_dev, p_hwfn->my_id);
 
                /* close NIG to BRB gate */
                ecore_wr(p_hwfn, p_ptt,
@@ -2173,20 +2236,48 @@ enum _ecore_status_t ecore_hw_stop(struct ecore_dev *p_dev)
                ecore_int_igu_init_pure_rt(p_hwfn, p_ptt, false, true);
                /* Need to wait 1ms to guarantee SBs are cleared */
                OSAL_MSLEEP(1);
-       }
+
+               if (!p_dev->recov_in_prog) {
+                       ecore_verify_reg_val(p_hwfn, p_ptt,
+                                            QM_REG_USG_CNT_PF_TX, 0);
+                       ecore_verify_reg_val(p_hwfn, p_ptt,
+                                            QM_REG_USG_CNT_PF_OTHER, 0);
+                       /* @@@TBD - assert on incorrect xCFC values (10.b) */
+               }
+
+               /* Disable PF in HW blocks */
+               ecore_wr(p_hwfn, p_ptt, DORQ_REG_PF_DB_ENABLE, 0);
+               ecore_wr(p_hwfn, p_ptt, QM_REG_PF_EN, 0);
+
+               if (!p_dev->recov_in_prog) {
+                       ecore_mcp_unload_done(p_hwfn, p_ptt);
+                       if (rc != ECORE_SUCCESS) {
+                               DP_NOTICE(p_hwfn, true,
+                                         "Failed sending a UNLOAD_DONE command. rc = %d.\n",
+                                         rc);
+                               rc2 = ECORE_UNKNOWN_ERROR;
+                       }
+               }
+       } /* hwfn loop */
 
        if (IS_PF(p_dev)) {
+               p_hwfn = ECORE_LEADING_HWFN(p_dev);
+               p_ptt = ECORE_LEADING_HWFN(p_dev)->p_main_ptt;
+
                /* Disable DMAE in PXP - in CMT, this should only be done for
                 * first hw-function, and only after all transactions have
                 * stopped for all active hw-functions.
                 */
-               t_rc = ecore_change_pci_hwfn(&p_dev->hwfns[0],
-                                            p_dev->hwfns[0].p_main_ptt, false);
-               if (t_rc != ECORE_SUCCESS)
-                       rc = t_rc;
+               rc = ecore_change_pci_hwfn(p_hwfn, p_ptt, false);
+               if (rc != ECORE_SUCCESS) {
+                       DP_NOTICE(p_hwfn, true,
+                                 "ecore_change_pci_hwfn failed. rc = %d.\n",
+                                 rc);
+                       rc2 = ECORE_UNKNOWN_ERROR;
+               }
        }
 
-       return rc;
+       return rc2;
 }
 
 void ecore_hw_stop_fastpath(struct ecore_dev *p_dev)
@@ -2247,84 +2338,6 @@ void ecore_hw_start_fastpath(struct ecore_hwfn *p_hwfn)
                 NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF, 0x0);
 }
 
-static enum _ecore_status_t ecore_reg_assert(struct ecore_hwfn *p_hwfn,
-                                            struct ecore_ptt *p_ptt, u32 reg,
-                                            bool expected)
-{
-       u32 assert_val = ecore_rd(p_hwfn, p_ptt, reg);
-
-       if (assert_val != expected) {
-               DP_NOTICE(p_hwfn, true, "Value at address 0x%08x != 0x%08x\n",
-                         reg, expected);
-               return ECORE_UNKNOWN_ERROR;
-       }
-
-       return 0;
-}
-
-enum _ecore_status_t ecore_hw_reset(struct ecore_dev *p_dev)
-{
-       enum _ecore_status_t rc = ECORE_SUCCESS;
-       u32 unload_resp, unload_param;
-       int i;
-
-       for_each_hwfn(p_dev, i) {
-               struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
-
-               if (IS_VF(p_dev)) {
-                       rc = ecore_vf_pf_reset(p_hwfn);
-                       if (rc)
-                               return rc;
-                       continue;
-               }
-
-               DP_VERBOSE(p_hwfn, ECORE_MSG_IFDOWN, "Resetting hw/fw\n");
-
-               /* Check for incorrect states */
-               if (!p_dev->recov_in_prog) {
-                       ecore_reg_assert(p_hwfn, p_hwfn->p_main_ptt,
-                                        QM_REG_USG_CNT_PF_TX, 0);
-                       ecore_reg_assert(p_hwfn, p_hwfn->p_main_ptt,
-                                        QM_REG_USG_CNT_PF_OTHER, 0);
-                       /* @@@TBD - assert on incorrect xCFC values (10.b) */
-               }
-
-               /* Disable PF in HW blocks */
-               ecore_wr(p_hwfn, p_hwfn->p_main_ptt, DORQ_REG_PF_DB_ENABLE, 0);
-               ecore_wr(p_hwfn, p_hwfn->p_main_ptt, QM_REG_PF_EN, 0);
-
-               if (p_dev->recov_in_prog) {
-                       DP_VERBOSE(p_hwfn, ECORE_MSG_IFDOWN,
-                                  "Recovery is in progress -> skip sending unload_req/done\n");
-                       break;
-               }
-
-               /* Send unload command to MCP */
-               rc = ecore_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
-                                  DRV_MSG_CODE_UNLOAD_REQ,
-                                  DRV_MB_PARAM_UNLOAD_WOL_MCP,
-                                  &unload_resp, &unload_param);
-               if (rc != ECORE_SUCCESS) {
-                       DP_NOTICE(p_hwfn, true,
-                                 "ecore_hw_reset: UNLOAD_REQ failed\n");
-                       /* @@TBD - what to do? for now, assume ENG. */
-                       unload_resp = FW_MSG_CODE_DRV_UNLOAD_ENGINE;
-               }
-
-               rc = ecore_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
-                                  DRV_MSG_CODE_UNLOAD_DONE,
-                                  0, &unload_resp, &unload_param);
-               if (rc != ECORE_SUCCESS) {
-                       DP_NOTICE(p_hwfn,
-                                 true, "ecore_hw_reset: UNLOAD_DONE failed\n");
-                       /* @@@TBD - Should it really ASSERT here ? */
-                       return rc;
-               }
-       }
-
-       return rc;
-}
-
 /* Free hwfn memory and resources acquired in hw_hwfn_prepare */
 static void ecore_hw_hwfn_free(struct ecore_hwfn *p_hwfn)
 {
@@ -2420,64 +2433,109 @@ static void ecore_hw_set_feat(struct ecore_hwfn *p_hwfn)
                   RESC_NUM(p_hwfn, ECORE_SB));
 }
 
-static enum resource_id_enum
-ecore_hw_get_mfw_res_id(enum ecore_resources res_id)
+const char *ecore_hw_get_resc_name(enum ecore_resources res_id)
 {
-       enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID;
-
        switch (res_id) {
        case ECORE_SB:
-               mfw_res_id = RESOURCE_NUM_SB_E;
-               break;
+               return "SB";
        case ECORE_L2_QUEUE:
-               mfw_res_id = RESOURCE_NUM_L2_QUEUE_E;
-               break;
+               return "L2_QUEUE";
        case ECORE_VPORT:
-               mfw_res_id = RESOURCE_NUM_VPORT_E;
-               break;
+               return "VPORT";
        case ECORE_RSS_ENG:
-               mfw_res_id = RESOURCE_NUM_RSS_ENGINES_E;
-               break;
+               return "RSS_ENG";
        case ECORE_PQ:
-               mfw_res_id = RESOURCE_NUM_PQ_E;
-               break;
+               return "PQ";
        case ECORE_RL:
-               mfw_res_id = RESOURCE_NUM_RL_E;
-               break;
+               return "RL";
        case ECORE_MAC:
+               return "MAC";
        case ECORE_VLAN:
-               /* Each VFC resource can accommodate both a MAC and a VLAN */
-               mfw_res_id = RESOURCE_VFC_FILTER_E;
-               break;
+               return "VLAN";
+       case ECORE_RDMA_CNQ_RAM:
+               return "RDMA_CNQ_RAM";
        case ECORE_ILT:
-               mfw_res_id = RESOURCE_ILT_E;
-               break;
+               return "ILT";
        case ECORE_LL2_QUEUE:
-               mfw_res_id = RESOURCE_LL2_QUEUE_E;
-               break;
-       case ECORE_RDMA_CNQ_RAM:
+               return "LL2_QUEUE";
        case ECORE_CMDQS_CQS:
-               /* CNQ/CMDQS are the same resource */
-               mfw_res_id = RESOURCE_CQS_E;
-               break;
+               return "CMDQS_CQS";
        case ECORE_RDMA_STATS_QUEUE:
-               mfw_res_id = RESOURCE_RDMA_STATS_QUEUE_E;
-               break;
+               return "RDMA_STATS_QUEUE";
        case ECORE_BDQ:
-               mfw_res_id = RESOURCE_BDQ_E;
-               break;
+               return "BDQ";
        default:
-               break;
+               return "UNKNOWN_RESOURCE";
+       }
+}
+
+static enum _ecore_status_t
+__ecore_hw_set_soft_resc_size(struct ecore_hwfn *p_hwfn,
+                             enum ecore_resources res_id, u32 resc_max_val,
+                             u32 *p_mcp_resp)
+{
+       enum _ecore_status_t rc;
+
+       rc = ecore_mcp_set_resc_max_val(p_hwfn, p_hwfn->p_main_ptt, res_id,
+                                       resc_max_val, p_mcp_resp);
+       if (rc != ECORE_SUCCESS) {
+               DP_NOTICE(p_hwfn, true,
+                         "MFW response failure for a max value setting of resource %d [%s]\n",
+                         res_id, ecore_hw_get_resc_name(res_id));
+               return rc;
+       }
+
+       if (*p_mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_OK)
+               DP_INFO(p_hwfn,
+                       "Failed to set the max value of resource %d [%s]. mcp_resp = 0x%08x.\n",
+                       res_id, ecore_hw_get_resc_name(res_id), *p_mcp_resp);
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t
+ecore_hw_set_soft_resc_size(struct ecore_hwfn *p_hwfn)
+{
+       bool b_ah = ECORE_IS_AH(p_hwfn->p_dev);
+       u32 resc_max_val, mcp_resp;
+       u8 res_id;
+       enum _ecore_status_t rc;
+
+       for (res_id = 0; res_id < ECORE_MAX_RESC; res_id++) {
+               /* @DPDK */
+               switch (res_id) {
+               case ECORE_LL2_QUEUE:
+               case ECORE_RDMA_CNQ_RAM:
+               case ECORE_RDMA_STATS_QUEUE:
+               case ECORE_BDQ:
+                       resc_max_val = 0;
+                       break;
+               default:
+                       continue;
+               }
+
+               rc = __ecore_hw_set_soft_resc_size(p_hwfn, res_id,
+                                                  resc_max_val, &mcp_resp);
+               if (rc != ECORE_SUCCESS)
+                       return rc;
+
+               /* There's no point to continue to the next resource if the
+                * command is not supported by the MFW.
+                * We do continue if the command is supported but the resource
+                * is unknown to the MFW. Such a resource will be later
+                * configured with the default allocation values.
+                */
+               if (mcp_resp == FW_MSG_CODE_UNSUPPORTED)
+                       return ECORE_NOTIMPL;
        }
 
-       return mfw_res_id;
+       return ECORE_SUCCESS;
 }
 
 static
 enum _ecore_status_t ecore_hw_get_dflt_resc(struct ecore_hwfn *p_hwfn,
                                            enum ecore_resources res_id,
-                                           u32 *p_resc_num,
-                                           u32 *p_resc_start)
+                                           u32 *p_resc_num, u32 *p_resc_start)
 {
        u8 num_funcs = p_hwfn->num_funcs_on_engine;
        bool b_ah = ECORE_IS_AH(p_hwfn->p_dev);
@@ -2553,56 +2611,19 @@ enum _ecore_status_t ecore_hw_get_dflt_resc(struct ecore_hwfn *p_hwfn,
        return ECORE_SUCCESS;
 }
 
-static const char *ecore_hw_get_resc_name(enum ecore_resources res_id)
-{
-       switch (res_id) {
-       case ECORE_SB:
-               return "SB";
-       case ECORE_L2_QUEUE:
-               return "L2_QUEUE";
-       case ECORE_VPORT:
-               return "VPORT";
-       case ECORE_RSS_ENG:
-               return "RSS_ENG";
-       case ECORE_PQ:
-               return "PQ";
-       case ECORE_RL:
-               return "RL";
-       case ECORE_MAC:
-               return "MAC";
-       case ECORE_VLAN:
-               return "VLAN";
-       case ECORE_RDMA_CNQ_RAM:
-               return "RDMA_CNQ_RAM";
-       case ECORE_ILT:
-               return "ILT";
-       case ECORE_LL2_QUEUE:
-               return "LL2_QUEUE";
-       case ECORE_CMDQS_CQS:
-               return "CMDQS_CQS";
-       case ECORE_RDMA_STATS_QUEUE:
-               return "RDMA_STATS_QUEUE";
-       case ECORE_BDQ:
-               return "BDQ";
-       default:
-               return "UNKNOWN_RESOURCE";
-       }
-}
-
-static enum _ecore_status_t ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn,
-                                                  enum ecore_resources res_id,
-                                                  bool drv_resc_alloc)
+static enum _ecore_status_t
+__ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn, enum ecore_resources res_id,
+                        bool drv_resc_alloc)
 {
-       u32 dflt_resc_num = 0, dflt_resc_start = 0, mcp_resp, mcp_param;
-       u32 *p_resc_num, *p_resc_start;
-       struct resource_info resc_info;
+       u32 dflt_resc_num = 0, dflt_resc_start = 0;
+       u32 mcp_resp, *p_resc_num, *p_resc_start;
        enum _ecore_status_t rc;
 
        p_resc_num = &RESC_NUM(p_hwfn, res_id);
        p_resc_start = &RESC_START(p_hwfn, res_id);
 
-       rc = ecore_hw_get_dflt_resc(p_hwfn, res_id,
-                                   &dflt_resc_num, &dflt_resc_start);
+       rc = ecore_hw_get_dflt_resc(p_hwfn, res_id, &dflt_resc_num,
+                                   &dflt_resc_start);
        if (rc != ECORE_SUCCESS) {
                DP_ERR(p_hwfn,
                       "Failed to get default amount for resource %d [%s]\n",
@@ -2618,17 +2639,8 @@ static enum _ecore_status_t ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn,
        }
 #endif
 
-       OSAL_MEM_ZERO(&resc_info, sizeof(resc_info));
-       resc_info.res_id = ecore_hw_get_mfw_res_id(res_id);
-       if (resc_info.res_id == RESOURCE_NUM_INVALID) {
-               DP_ERR(p_hwfn,
-                      "Failed to match resource %d with MFW resources\n",
-                      res_id);
-               return ECORE_INVAL;
-       }
-
-       rc = ecore_mcp_get_resc_info(p_hwfn, p_hwfn->p_main_ptt, &resc_info,
-                                    &mcp_resp, &mcp_param);
+       rc = ecore_mcp_get_resc_info(p_hwfn, p_hwfn->p_main_ptt, res_id,
+                                    &mcp_resp, p_resc_num, p_resc_start);
        if (rc != ECORE_SUCCESS) {
                DP_NOTICE(p_hwfn, true,
                          "MFW response failure for an allocation request for"
@@ -2642,13 +2654,11 @@ static enum _ecore_status_t ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn,
         * - There is an internal error in the MFW while processing the request
         * - The resource ID is unknown to the MFW
         */
-       if (mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_OK &&
-           mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_DEPRECATED) {
-               /* @DPDK */
+       if (mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_OK) {
                DP_INFO(p_hwfn,
-                       "Resource %d [%s]: No allocation info was received"
-                       " [mcp_resp 0x%x]. Applying default values"
-                       " [num %d, start %d].\n",
+                       "Failed to receive allocation info for resource %d [%s]."
+                       " mcp_resp = 0x%x. Applying default values"
+                       " [%d,%d].\n",
                        res_id, ecore_hw_get_resc_name(res_id), mcp_resp,
                        dflt_resc_num, dflt_resc_start);
 
@@ -2660,16 +2670,13 @@ static enum _ecore_status_t ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn,
        /* TBD - remove this when revising the handling of the SB resource */
        if (res_id == ECORE_SB) {
                /* Excluding the slowpath SB */
-               resc_info.size -= 1;
-               resc_info.offset -= p_hwfn->enabled_func_idx;
+               *p_resc_num -= 1;
+               *p_resc_start -= p_hwfn->enabled_func_idx;
        }
 
-       *p_resc_num = resc_info.size;
-       *p_resc_start = resc_info.offset;
-
        if (*p_resc_num != dflt_resc_num || *p_resc_start != dflt_resc_start) {
                DP_INFO(p_hwfn,
-                       "Resource %d [%s]: MFW allocation [num %d, start %d] differs from default values [num %d, start %d]%s\n",
+                       "MFW allocation for resource %d [%s] differs from default values [%d,%d vs. %d,%d]%s\n",
                        res_id, ecore_hw_get_resc_name(res_id), *p_resc_num,
                        *p_resc_start, dflt_resc_num, dflt_resc_start,
                        drv_resc_alloc ? " - Applying default values" : "");
@@ -2682,12 +2689,32 @@ out:
        return ECORE_SUCCESS;
 }
 
+static enum _ecore_status_t ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn,
+                                                  bool drv_resc_alloc)
+{
+       enum _ecore_status_t rc;
+       u8 res_id;
+
+       for (res_id = 0; res_id < ECORE_MAX_RESC; res_id++) {
+               rc = __ecore_hw_set_resc_info(p_hwfn, res_id, drv_resc_alloc);
+               if (rc != ECORE_SUCCESS)
+                       return rc;
+       }
+
+       return ECORE_SUCCESS;
+}
+
+#define ECORE_RESC_ALLOC_LOCK_RETRY_CNT                10
+#define ECORE_RESC_ALLOC_LOCK_RETRY_INTVL_US   10000 /* 10 msec */
+
 static enum _ecore_status_t ecore_hw_get_resc(struct ecore_hwfn *p_hwfn,
                                              bool drv_resc_alloc)
 {
+       struct ecore_resc_unlock_params resc_unlock_params;
+       struct ecore_resc_lock_params resc_lock_params;
        bool b_ah = ECORE_IS_AH(p_hwfn->p_dev);
-       enum _ecore_status_t rc;
        u8 res_id;
+       enum _ecore_status_t rc;
 #ifndef ASIC_ONLY
        u32 *resc_start = p_hwfn->hw_info.resc_start;
        u32 *resc_num = p_hwfn->hw_info.resc_num;
@@ -2700,10 +2727,62 @@ static enum _ecore_status_t ecore_hw_get_resc(struct ecore_hwfn *p_hwfn,
        u32 roce_min_ilt_lines = PXP_NUM_ILT_RECORDS_BB / MAX_NUM_PFS_BB;
 #endif
 
-       for (res_id = 0; res_id < ECORE_MAX_RESC; res_id++) {
-               rc = ecore_hw_set_resc_info(p_hwfn, res_id, drv_resc_alloc);
+       /* Setting the max values of the soft resources and the following
+        * resources allocation queries should be atomic. Since several PFs can
+        * run in parallel - a resource lock is needed.
+        * If either the resource lock or resource set value commands are not
+        * supported - skip the the max values setting, release the lock if
+        * needed, and proceed to the queries. Other failures, including a
+        * failure to acquire the lock, will cause this function to fail.
+        * Old drivers that don't acquire the lock can run in parallel, and
+        * their allocation values won't be affected by the updated max values.
+        */
+       OSAL_MEM_ZERO(&resc_lock_params, sizeof(resc_lock_params));
+       resc_lock_params.resource = ECORE_RESC_LOCK_RESC_ALLOC;
+       resc_lock_params.retry_num = ECORE_RESC_ALLOC_LOCK_RETRY_CNT;
+       resc_lock_params.retry_interval = ECORE_RESC_ALLOC_LOCK_RETRY_INTVL_US;
+       resc_lock_params.sleep_b4_retry = true;
+       OSAL_MEM_ZERO(&resc_unlock_params, sizeof(resc_unlock_params));
+       resc_unlock_params.resource = ECORE_RESC_LOCK_RESC_ALLOC;
+
+       rc = ecore_mcp_resc_lock(p_hwfn, p_hwfn->p_main_ptt, &resc_lock_params);
+       if (rc != ECORE_SUCCESS && rc != ECORE_NOTIMPL) {
+               return rc;
+       } else if (rc == ECORE_NOTIMPL) {
+               DP_INFO(p_hwfn,
+                       "Skip the max values setting of the soft resources since the resource lock is not supported by the MFW\n");
+       } else if (rc == ECORE_SUCCESS && !resc_lock_params.b_granted) {
+               DP_NOTICE(p_hwfn, false,
+                         "Failed to acquire the resource lock for the resource allocation commands\n");
+               rc = ECORE_BUSY;
+               goto unlock_and_exit;
+       } else {
+               rc = ecore_hw_set_soft_resc_size(p_hwfn);
+               if (rc != ECORE_SUCCESS && rc != ECORE_NOTIMPL) {
+                       DP_NOTICE(p_hwfn, false,
+                                 "Failed to set the max values of the soft resources\n");
+                       goto unlock_and_exit;
+               } else if (rc == ECORE_NOTIMPL) {
+                       DP_INFO(p_hwfn,
+                               "Skip the max values setting of the soft resources since it is not supported by the MFW\n");
+                       rc = ecore_mcp_resc_unlock(p_hwfn, p_hwfn->p_main_ptt,
+                                                  &resc_unlock_params);
+                       if (rc != ECORE_SUCCESS)
+                               DP_INFO(p_hwfn,
+                                       "Failed to release the resource lock for the resource allocation commands\n");
+               }
+       }
+
+       rc = ecore_hw_set_resc_info(p_hwfn, drv_resc_alloc);
+       if (rc != ECORE_SUCCESS)
+               goto unlock_and_exit;
+
+       if (resc_lock_params.b_granted && !resc_unlock_params.b_released) {
+               rc = ecore_mcp_resc_unlock(p_hwfn, p_hwfn->p_main_ptt,
+                                          &resc_unlock_params);
                if (rc != ECORE_SUCCESS)
-                       return rc;
+                       DP_INFO(p_hwfn,
+                               "Failed to release the resource lock for the resource allocation commands\n");
        }
 
 #ifndef ASIC_ONLY
@@ -2756,6 +2835,10 @@ static enum _ecore_status_t ecore_hw_get_resc(struct ecore_hwfn *p_hwfn,
                           RESC_START(p_hwfn, res_id));
 
        return ECORE_SUCCESS;
+
+unlock_and_exit:
+       ecore_mcp_resc_unlock(p_hwfn, p_hwfn->p_main_ptt, &resc_unlock_params);
+       return rc;
 }
 
 static enum _ecore_status_t