From d9237ae22731d6968a0667d32953ebce27c21a0a Mon Sep 17 00:00:00 2001 From: Rasesh Mody Date: Fri, 17 Mar 2017 23:50:21 -0700 Subject: [PATCH] net/qede/base: fix numbering L2 VF queues There are some constellations where Due to lack of resource allocation in MFW, There would be an insufficient number of L2 queues for all the VFs. This introduces a new feature ECORE_VF_L2_QUE which correctly numbers the number of VF queues. Notice it might be larger than the actual number of VFs in configuration space, in which case its the ecore client responsibility not to try activating that many. As part of the fix, also correct the nubmering of the VF queues. As their numbering is dependent on the SBs of the PF, which might only be partially used by L2 [as half would be assigned for RDMA which doesn't require L2 queues], we make the numbering consecutive with that of the L2 queues only. Fixes: ec94dbc57362 ("qede: add base driver") Signed-off-by: Rasesh Mody --- drivers/net/qede/base/ecore.h | 1 + drivers/net/qede/base/ecore_dev.c | 19 +++++++++++++---- drivers/net/qede/base/ecore_int.c | 35 +++++++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h index b41ff4a2c3..b2f4910dd9 100644 --- a/drivers/net/qede/base/ecore.h +++ b/drivers/net/qede/base/ecore.h @@ -288,6 +288,7 @@ enum ecore_feature { ECORE_RDMA_CNQ, ECORE_ISCSI_CQ, ECORE_FCOE_CQ, + ECORE_VF_L2_QUE, ECORE_MAX_FEATURES, }; diff --git a/drivers/net/qede/base/ecore_dev.c b/drivers/net/qede/base/ecore_dev.c index 5555174574..b5873bde20 100644 --- a/drivers/net/qede/base/ecore_dev.c +++ b/drivers/net/qede/base/ecore_dev.c @@ -2057,6 +2057,7 @@ static void get_function_id(struct ecore_hwfn *p_hwfn) static void ecore_hw_set_feat(struct ecore_hwfn *p_hwfn) { u32 *feat_num = p_hwfn->hw_info.feat_num; + struct ecore_sb_cnt_info sb_cnt_info; int num_features = 1; /* L2 Queues require each: 1 status block. 1 L2 queue */ @@ -2065,11 +2066,21 @@ static void ecore_hw_set_feat(struct ecore_hwfn *p_hwfn) RESC_NUM(p_hwfn, ECORE_SB) / num_features, RESC_NUM(p_hwfn, ECORE_L2_QUEUE)); + OSAL_MEM_ZERO(&sb_cnt_info, sizeof(sb_cnt_info)); + ecore_int_get_num_sbs(p_hwfn, &sb_cnt_info); + feat_num[ECORE_VF_L2_QUE] = + OSAL_MIN_T(u32, + RESC_NUM(p_hwfn, ECORE_L2_QUEUE) - + FEAT_NUM(p_hwfn, ECORE_PF_L2_QUE), + sb_cnt_info.sb_iov_cnt); + DP_VERBOSE(p_hwfn, ECORE_MSG_PROBE, - "#PF_L2_QUEUES=%d #ROCE_CNQ=%d #SBS=%d num_features=%d\n", - feat_num[ECORE_PF_L2_QUE], - feat_num[ECORE_RDMA_CNQ], - RESC_NUM(p_hwfn, ECORE_SB), num_features); + "#PF_L2_QUEUES=%d VF_L2_QUEUES=%d #ROCE_CNQ=%d #SBS=%d num_features=%d\n", + (int)FEAT_NUM(p_hwfn, ECORE_PF_L2_QUE), + (int)FEAT_NUM(p_hwfn, ECORE_VF_L2_QUE), + (int)FEAT_NUM(p_hwfn, ECORE_RDMA_CNQ), + RESC_NUM(p_hwfn, ECORE_SB), + num_features); } static enum resource_id_enum diff --git a/drivers/net/qede/base/ecore_int.c b/drivers/net/qede/base/ecore_int.c index 96f283ba91..1a157a58ec 100644 --- a/drivers/net/qede/base/ecore_int.c +++ b/drivers/net/qede/base/ecore_int.c @@ -1964,6 +1964,31 @@ enum _ecore_status_t ecore_int_igu_read_cam(struct ecore_hwfn *p_hwfn, } } } + + /* There's a possibility the igu_sb_cnt_iov doesn't properly reflect + * the number of VF SBs [especially for first VF on engine, as we can't + * diffrentiate between empty entries and its entries]. + * Since we don't really support more SBs than VFs today, prevent any + * such configuration by sanitizing the number of SBs to equal the + * number of VFs. + */ + if (IS_PF_SRIOV(p_hwfn)) { + u16 total_vfs = p_hwfn->p_dev->p_iov_info->total_vfs; + + if (total_vfs < p_igu_info->free_blks) { + DP_VERBOSE(p_hwfn, (ECORE_MSG_INTR | ECORE_MSG_IOV), + "Limiting number of SBs for IOV - %04x --> %04x\n", + p_igu_info->free_blks, + p_hwfn->p_dev->p_iov_info->total_vfs); + p_igu_info->free_blks = total_vfs; + } else if (total_vfs > p_igu_info->free_blks) { + DP_NOTICE(p_hwfn, true, + "IGU has only %04x SBs for VFs while the device has %04x VFs\n", + p_igu_info->free_blks, total_vfs); + return ECORE_INVAL; + } + } + p_igu_info->igu_sb_cnt_iov = p_igu_info->free_blks; DP_VERBOSE(p_hwfn, ECORE_MSG_INTR, @@ -2101,8 +2126,14 @@ u16 ecore_int_queue_id_from_sb_id(struct ecore_hwfn *p_hwfn, u16 sb_id) (sb_id < p_info->igu_base_sb + p_info->igu_sb_cnt)) { return sb_id - p_info->igu_base_sb; } else if ((sb_id >= p_info->igu_base_sb_iov) && - (sb_id < p_info->igu_base_sb_iov + p_info->igu_sb_cnt_iov)) { - return sb_id - p_info->igu_base_sb_iov + p_info->igu_sb_cnt; + (sb_id < p_info->igu_base_sb_iov + + p_info->igu_sb_cnt_iov)) { + /* We want the first VF queue to be adjacent to the + * last PF queue. Since L2 queues can be partial to + * SBs, we'll use the feature instead. + */ + return sb_id - p_info->igu_base_sb_iov + + FEAT_NUM(p_hwfn, ECORE_PF_L2_QUE); } else { DP_NOTICE(p_hwfn, true, "SB %d not in range for function\n", sb_id); -- 2.20.1