net/qede/base: interchangeably use SB between PF and VF

Status Block reallocation - allow a PF and its child VF to change SB
between them using new base driver APIs.

The changes that are inside base driver flows are:

New APIs ecore_int_igu_reset_cam() and ecore_int_igu_reset_cam_default()
added to reset IGU CAM.
 a. During hw_prepare(), driver would re-initialize the IGU CAM.
 b. During hw_stop(), driver would initialize the IGU CAM to default.

Use igu_sb_id instead of sb_idx [protocol index] to allow setting of
the timer-resolution in CAU[coalescing algorithm unit] for all SBs,
sb_idx could limit SBs 0-11 only to be able change their timer-resolution.

Signed-off-by: Rasesh Mody <rasesh.mody@cavium.com>
This commit is contained in:
Rasesh Mody 2017-09-18 18:29:47 -07:00 committed by Ferruh Yigit
parent a90c566f43
commit 6e4fcea92f
12 changed files with 809 additions and 398 deletions

View File

@ -279,7 +279,6 @@ struct ecore_qm_iids {
* is received from MFW.
*/
enum ecore_resources {
ECORE_SB,
ECORE_L2_QUEUE,
ECORE_VPORT,
ECORE_RSS_ENG,
@ -293,7 +292,13 @@ enum ecore_resources {
ECORE_CMDQS_CQS,
ECORE_RDMA_STATS_QUEUE,
ECORE_BDQ,
ECORE_MAX_RESC, /* must be last */
/* This is needed only internally for matching against the IGU.
* In case of legacy MFW, would be set to `0'.
*/
ECORE_SB,
ECORE_MAX_RESC,
};
/* Features that require resources, given as input to the resource management
@ -556,10 +561,6 @@ struct ecore_hwfn {
bool b_rdma_enabled_in_prs;
u32 rdma_prs_search_reg;
/* Array of sb_info of all status blocks */
struct ecore_sb_info *sbs_info[MAX_SB_PER_PF_MIMD];
u16 num_sbs;
struct ecore_cxt_mngr *p_cxt_mngr;
/* Flag indicating whether interrupts are enabled or not*/

View File

@ -1232,7 +1232,7 @@ static enum _ecore_status_t ecore_hw_init_chip(struct ecore_hwfn *p_hwfn,
static void ecore_init_cau_rt_data(struct ecore_dev *p_dev)
{
u32 offset = CAU_REG_SB_VAR_MEMORY_RT_OFFSET;
int i, sb_id;
int i, igu_sb_id;
for_each_hwfn(p_dev, i) {
struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
@ -1242,16 +1242,18 @@ static void ecore_init_cau_rt_data(struct ecore_dev *p_dev)
p_igu_info = p_hwfn->hw_info.p_igu_info;
for (sb_id = 0; sb_id < ECORE_MAPPING_MEMORY_SIZE(p_dev);
sb_id++) {
p_block = &p_igu_info->igu_map.igu_blocks[sb_id];
for (igu_sb_id = 0;
igu_sb_id < ECORE_MAPPING_MEMORY_SIZE(p_dev);
igu_sb_id++) {
p_block = &p_igu_info->entry[igu_sb_id];
if (!p_block->is_pf)
continue;
ecore_init_cau_sb_entry(p_hwfn, &sb_entry,
p_block->function_id, 0, 0);
STORE_RT_REG_AGG(p_hwfn, offset + sb_id * 2, sb_entry);
STORE_RT_REG_AGG(p_hwfn, offset + igu_sb_id * 2,
sb_entry);
}
}
}
@ -2255,6 +2257,13 @@ enum _ecore_status_t ecore_hw_stop(struct ecore_dev *p_dev)
ecore_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0);
ecore_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0);
ecore_int_igu_init_pure_rt(p_hwfn, p_ptt, false, true);
rc = ecore_int_igu_reset_cam_default(p_hwfn, p_ptt);
if (rc != ECORE_SUCCESS) {
DP_NOTICE(p_hwfn, true,
"Failed to return IGU CAM to default\n");
rc2 = ECORE_UNKNOWN_ERROR;
}
/* Need to wait 1ms to guarantee SBs are cleared */
OSAL_MSLEEP(1);
@ -2423,31 +2432,32 @@ 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;
u32 non_l2_sbs = 0;
OSAL_MEM_ZERO(&sb_cnt, sizeof(sb_cnt));
ecore_int_get_num_sbs(p_hwfn, &sb_cnt);
/* L2 Queues require each: 1 status block. 1 L2 queue */
if (ECORE_IS_L2_PERSONALITY(p_hwfn)) {
struct ecore_sb_cnt_info sb_cnt_info;
OSAL_MEM_ZERO(&sb_cnt_info, sizeof(sb_cnt_info));
ecore_int_get_num_sbs(p_hwfn, &sb_cnt_info);
/* Start by allocating VF queues, then PF's */
feat_num[ECORE_VF_L2_QUE] =
OSAL_MIN_T(u32,
RESC_NUM(p_hwfn, ECORE_L2_QUEUE),
sb_cnt_info.sb_iov_cnt);
sb_cnt.iov_cnt);
feat_num[ECORE_PF_L2_QUE] =
OSAL_MIN_T(u32,
RESC_NUM(p_hwfn, ECORE_SB) - non_l2_sbs,
sb_cnt.cnt - non_l2_sbs,
RESC_NUM(p_hwfn, ECORE_L2_QUEUE) -
FEAT_NUM(p_hwfn, ECORE_VF_L2_QUE));
}
feat_num[ECORE_FCOE_CQ] = OSAL_MIN_T(u32, RESC_NUM(p_hwfn, ECORE_SB),
RESC_NUM(p_hwfn, ECORE_CMDQS_CQS));
feat_num[ECORE_ISCSI_CQ] = OSAL_MIN_T(u32, RESC_NUM(p_hwfn, ECORE_SB),
RESC_NUM(p_hwfn, ECORE_CMDQS_CQS));
feat_num[ECORE_FCOE_CQ] = OSAL_MIN_T(u32, sb_cnt.cnt,
RESC_NUM(p_hwfn,
ECORE_CMDQS_CQS));
feat_num[ECORE_ISCSI_CQ] = OSAL_MIN_T(u32, sb_cnt.cnt,
RESC_NUM(p_hwfn,
ECORE_CMDQS_CQS));
DP_VERBOSE(p_hwfn, ECORE_MSG_PROBE,
"#PF_L2_QUEUE=%d VF_L2_QUEUES=%d #ROCE_CNQ=%d #FCOE_CQ=%d #ISCSI_CQ=%d #SB=%d\n",
@ -2456,14 +2466,12 @@ static void ecore_hw_set_feat(struct ecore_hwfn *p_hwfn)
(int)FEAT_NUM(p_hwfn, ECORE_RDMA_CNQ),
(int)FEAT_NUM(p_hwfn, ECORE_FCOE_CQ),
(int)FEAT_NUM(p_hwfn, ECORE_ISCSI_CQ),
RESC_NUM(p_hwfn, ECORE_SB));
(int)sb_cnt.cnt);
}
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:
@ -2490,6 +2498,8 @@ const char *ecore_hw_get_resc_name(enum ecore_resources res_id)
return "RDMA_STATS_QUEUE";
case ECORE_BDQ:
return "BDQ";
case ECORE_SB:
return "SB";
default:
return "UNKNOWN_RESOURCE";
}
@ -2565,14 +2575,8 @@ enum _ecore_status_t ecore_hw_get_dflt_resc(struct ecore_hwfn *p_hwfn,
{
u8 num_funcs = p_hwfn->num_funcs_on_engine;
bool b_ah = ECORE_IS_AH(p_hwfn->p_dev);
struct ecore_sb_cnt_info sb_cnt_info;
switch (res_id) {
case ECORE_SB:
OSAL_MEM_ZERO(&sb_cnt_info, sizeof(sb_cnt_info));
ecore_int_get_num_sbs(p_hwfn, &sb_cnt_info);
*p_resc_num = sb_cnt_info.sb_cnt;
break;
case ECORE_L2_QUEUE:
*p_resc_num = (b_ah ? MAX_NUM_L2_QUEUES_K2 :
MAX_NUM_L2_QUEUES_BB) / num_funcs;
@ -2629,6 +2633,12 @@ enum _ecore_status_t ecore_hw_get_dflt_resc(struct ecore_hwfn *p_hwfn,
if (!*p_resc_num)
*p_resc_start = 0;
break;
case ECORE_SB:
/* Since we want its value to reflect whether MFW supports
* the new scheme, have a default of 0.
*/
*p_resc_num = 0;
break;
default:
*p_resc_start = *p_resc_num * p_hwfn->enabled_func_idx;
break;
@ -2693,14 +2703,9 @@ __ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn, enum ecore_resources res_id,
goto out;
}
/* TBD - remove this when revising the handling of the SB resource */
if (res_id == ECORE_SB) {
/* Excluding the slowpath SB */
*p_resc_num -= 1;
*p_resc_start -= p_hwfn->enabled_func_idx;
}
if (*p_resc_num != dflt_resc_num || *p_resc_start != dflt_resc_start) {
if ((*p_resc_num != dflt_resc_num ||
*p_resc_start != dflt_resc_start) &&
res_id != ECORE_SB) {
DP_INFO(p_hwfn,
"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,
@ -2850,6 +2855,10 @@ static enum _ecore_status_t ecore_hw_get_resc(struct ecore_hwfn *p_hwfn,
return ECORE_INVAL;
}
/* This will also learn the number of SBs from MFW */
if (ecore_int_igu_reset_cam(p_hwfn, p_hwfn->p_main_ptt))
return ECORE_INVAL;
ecore_hw_set_feat(p_hwfn);
DP_VERBOSE(p_hwfn, ECORE_MSG_PROBE,
@ -4540,7 +4549,7 @@ enum _ecore_status_t ecore_set_rxq_coalesce(struct ecore_hwfn *p_hwfn,
timeset = (u8)(coalesce >> timer_res);
rc = ecore_int_set_timer_res(p_hwfn, p_ptt, timer_res,
p_cid->abs.sb_idx, false);
p_cid->sb_igu_id, false);
if (rc != ECORE_SUCCESS)
goto out;
@ -4581,7 +4590,7 @@ enum _ecore_status_t ecore_set_txq_coalesce(struct ecore_hwfn *p_hwfn,
timeset = (u8)(coalesce >> timer_res);
rc = ecore_int_set_timer_res(p_hwfn, p_ptt, timer_res,
p_cid->abs.sb_idx, true);
p_cid->sb_igu_id, true);
if (rc != ECORE_SUCCESS)
goto out;

View File

@ -1369,6 +1369,49 @@ void ecore_init_cau_sb_entry(struct ecore_hwfn *p_hwfn,
SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE1, cau_state);
}
static void _ecore_int_cau_conf_pi(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
u16 igu_sb_id, u32 pi_index,
enum ecore_coalescing_fsm coalescing_fsm,
u8 timeset)
{
struct cau_pi_entry pi_entry;
u32 sb_offset, pi_offset;
if (IS_VF(p_hwfn->p_dev))
return;/* @@@TBD MichalK- VF CAU... */
sb_offset = igu_sb_id * PIS_PER_SB;
OSAL_MEMSET(&pi_entry, 0, sizeof(struct cau_pi_entry));
SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_PI_TIMESET, timeset);
if (coalescing_fsm == ECORE_COAL_RX_STATE_MACHINE)
SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 0);
else
SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 1);
pi_offset = sb_offset + pi_index;
if (p_hwfn->hw_init_done) {
ecore_wr(p_hwfn, p_ptt,
CAU_REG_PI_MEMORY + pi_offset * sizeof(u32),
*((u32 *)&(pi_entry)));
} else {
STORE_RT_REG(p_hwfn,
CAU_REG_PI_MEMORY_RT_OFFSET + pi_offset,
*((u32 *)&(pi_entry)));
}
}
void ecore_int_cau_conf_pi(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
struct ecore_sb_info *p_sb, u32 pi_index,
enum ecore_coalescing_fsm coalescing_fsm,
u8 timeset)
{
_ecore_int_cau_conf_pi(p_hwfn, p_ptt, p_sb->igu_sb_id,
pi_index, coalescing_fsm, timeset);
}
void ecore_int_cau_conf_sb(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
dma_addr_t sb_phys, u16 igu_sb_id,
@ -1420,8 +1463,9 @@ void ecore_int_cau_conf_sb(struct ecore_hwfn *p_hwfn,
else
timer_res = 2;
timeset = (u8)(p_hwfn->p_dev->rx_coalesce_usecs >> timer_res);
ecore_int_cau_conf_pi(p_hwfn, p_ptt, igu_sb_id, RX_PI,
ECORE_COAL_RX_STATE_MACHINE, timeset);
_ecore_int_cau_conf_pi(p_hwfn, p_ptt, igu_sb_id, RX_PI,
ECORE_COAL_RX_STATE_MACHINE,
timeset);
if (p_hwfn->p_dev->tx_coalesce_usecs <= 0x7F)
timer_res = 0;
@ -1431,46 +1475,14 @@ void ecore_int_cau_conf_sb(struct ecore_hwfn *p_hwfn,
timer_res = 2;
timeset = (u8)(p_hwfn->p_dev->tx_coalesce_usecs >> timer_res);
for (i = 0; i < num_tc; i++) {
ecore_int_cau_conf_pi(p_hwfn, p_ptt,
igu_sb_id, TX_PI(i),
ECORE_COAL_TX_STATE_MACHINE,
timeset);
_ecore_int_cau_conf_pi(p_hwfn, p_ptt,
igu_sb_id, TX_PI(i),
ECORE_COAL_TX_STATE_MACHINE,
timeset);
}
}
}
void ecore_int_cau_conf_pi(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
u16 igu_sb_id, u32 pi_index,
enum ecore_coalescing_fsm coalescing_fsm, u8 timeset)
{
struct cau_pi_entry pi_entry;
u32 sb_offset, pi_offset;
if (IS_VF(p_hwfn->p_dev))
return; /* @@@TBD MichalK- VF CAU... */
sb_offset = igu_sb_id * PIS_PER_SB;
OSAL_MEMSET(&pi_entry, 0, sizeof(struct cau_pi_entry));
SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_PI_TIMESET, timeset);
if (coalescing_fsm == ECORE_COAL_RX_STATE_MACHINE)
SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 0);
else
SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 1);
pi_offset = sb_offset + pi_index;
if (p_hwfn->hw_init_done) {
ecore_wr(p_hwfn, p_ptt,
CAU_REG_PI_MEMORY + pi_offset * sizeof(u32),
*((u32 *)&(pi_entry)));
} else {
STORE_RT_REG(p_hwfn,
CAU_REG_PI_MEMORY_RT_OFFSET + pi_offset,
*((u32 *)&(pi_entry)));
}
}
void ecore_int_sb_setup(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt, struct ecore_sb_info *sb_info)
{
@ -1483,16 +1495,50 @@ void ecore_int_sb_setup(struct ecore_hwfn *p_hwfn,
sb_info->igu_sb_id, 0, 0);
}
/**
* @brief ecore_get_igu_sb_id - given a sw sb_id return the
* igu_sb_id
*
* @param p_hwfn
* @param sb_id
*
* @return u16
*/
static u16 ecore_get_igu_sb_id(struct ecore_hwfn *p_hwfn, u16 sb_id)
struct ecore_igu_block *
ecore_get_igu_free_sb(struct ecore_hwfn *p_hwfn, bool b_is_pf)
{
struct ecore_igu_block *p_block;
u16 igu_id;
for (igu_id = 0; igu_id < ECORE_MAPPING_MEMORY_SIZE(p_hwfn->p_dev);
igu_id++) {
p_block = &p_hwfn->hw_info.p_igu_info->entry[igu_id];
if (!(p_block->status & ECORE_IGU_STATUS_VALID) ||
!(p_block->status & ECORE_IGU_STATUS_FREE))
continue;
if (!!(p_block->status & ECORE_IGU_STATUS_PF) ==
b_is_pf)
return p_block;
}
return OSAL_NULL;
}
static u16 ecore_get_pf_igu_sb_id(struct ecore_hwfn *p_hwfn,
u16 vector_id)
{
struct ecore_igu_block *p_block;
u16 igu_id;
for (igu_id = 0; igu_id < ECORE_MAPPING_MEMORY_SIZE(p_hwfn->p_dev);
igu_id++) {
p_block = &p_hwfn->hw_info.p_igu_info->entry[igu_id];
if (!(p_block->status & ECORE_IGU_STATUS_VALID) ||
!p_block->is_pf ||
p_block->vector_number != vector_id)
continue;
return igu_id;
}
return ECORE_SB_INVALID_IDX;
}
u16 ecore_get_igu_sb_id(struct ecore_hwfn *p_hwfn, u16 sb_id)
{
u16 igu_sb_id;
@ -1500,11 +1546,15 @@ static u16 ecore_get_igu_sb_id(struct ecore_hwfn *p_hwfn, u16 sb_id)
if (sb_id == ECORE_SP_SB_ID)
igu_sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id;
else if (IS_PF(p_hwfn->p_dev))
igu_sb_id = sb_id + p_hwfn->hw_info.p_igu_info->igu_base_sb;
igu_sb_id = ecore_get_pf_igu_sb_id(p_hwfn, sb_id + 1);
else
igu_sb_id = ecore_vf_get_igu_sb_id(p_hwfn, sb_id);
if (sb_id == ECORE_SP_SB_ID)
if (igu_sb_id == ECORE_SB_INVALID_IDX)
DP_NOTICE(p_hwfn, true,
"Slowpath SB vector %04x doesn't exist\n",
sb_id);
else if (sb_id == ECORE_SP_SB_ID)
DP_VERBOSE(p_hwfn, ECORE_MSG_INTR,
"Slowpath SB index in IGU is 0x%04x\n", igu_sb_id);
else
@ -1525,9 +1575,24 @@ enum _ecore_status_t ecore_int_sb_init(struct ecore_hwfn *p_hwfn,
sb_info->igu_sb_id = ecore_get_igu_sb_id(p_hwfn, sb_id);
if (sb_info->igu_sb_id == ECORE_SB_INVALID_IDX)
return ECORE_INVAL;
/* Let the igu info reference the client's SB info */
if (sb_id != ECORE_SP_SB_ID) {
p_hwfn->sbs_info[sb_id] = sb_info;
p_hwfn->num_sbs++;
if (IS_PF(p_hwfn->p_dev)) {
struct ecore_igu_info *p_info;
struct ecore_igu_block *p_block;
p_info = p_hwfn->hw_info.p_igu_info;
p_block = &p_info->entry[sb_info->igu_sb_id];
p_block->sb_info = sb_info;
p_block->status &= ~ECORE_IGU_STATUS_FREE;
p_info->usage.free_cnt--;
} else {
ecore_vf_set_sb_info(p_hwfn, sb_id, sb_info);
}
}
#ifdef ECORE_CONFIG_DIRECT_HWFN
sb_info->p_hwfn = p_hwfn;
@ -1559,20 +1624,35 @@ enum _ecore_status_t ecore_int_sb_release(struct ecore_hwfn *p_hwfn,
struct ecore_sb_info *sb_info,
u16 sb_id)
{
if (sb_id == ECORE_SP_SB_ID) {
DP_ERR(p_hwfn, "Do Not free sp sb using this function");
return ECORE_INVAL;
}
struct ecore_igu_info *p_info;
struct ecore_igu_block *p_block;
if (sb_info == OSAL_NULL)
return ECORE_SUCCESS;
/* zero status block and ack counter */
sb_info->sb_ack = 0;
OSAL_MEMSET(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt));
if (p_hwfn->sbs_info[sb_id] != OSAL_NULL) {
p_hwfn->sbs_info[sb_id] = OSAL_NULL;
p_hwfn->num_sbs--;
if (IS_VF(p_hwfn->p_dev)) {
ecore_vf_set_sb_info(p_hwfn, sb_id, OSAL_NULL);
return ECORE_SUCCESS;
}
p_info = p_hwfn->hw_info.p_igu_info;
p_block = &p_info->entry[sb_info->igu_sb_id];
/* Vector 0 is reserved to Default SB */
if (p_block->vector_number == 0) {
DP_ERR(p_hwfn, "Do Not free sp sb using this function");
return ECORE_INVAL;
}
/* Lose reference to client's SB info, and fix counters */
p_block->sb_info = OSAL_NULL;
p_block->status |= ECORE_IGU_STATUS_FREE;
p_info->usage.free_cnt++;
return ECORE_SUCCESS;
}
@ -1778,11 +1858,13 @@ void ecore_int_igu_disable_int(struct ecore_hwfn *p_hwfn,
#define IGU_CLEANUP_SLEEP_LENGTH (1000)
static void ecore_int_igu_cleanup_sb(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
u32 sb_id, bool cleanup_set, u16 opaque_fid)
struct ecore_ptt *p_ptt,
u32 igu_sb_id,
bool cleanup_set,
u16 opaque_fid)
{
u32 cmd_ctrl = 0, val = 0, sb_bit = 0, sb_bit_addr = 0, data = 0;
u32 pxp_addr = IGU_CMD_INT_ACK_BASE + sb_id;
u32 pxp_addr = IGU_CMD_INT_ACK_BASE + igu_sb_id;
u32 sleep_cnt = IGU_CLEANUP_SLEEP_LENGTH;
u8 type = 0; /* FIXME MichalS type??? */
@ -1813,8 +1895,8 @@ static void ecore_int_igu_cleanup_sb(struct ecore_hwfn *p_hwfn,
OSAL_MMIOWB(p_hwfn->p_dev);
/* calculate where to read the status bit from */
sb_bit = 1 << (sb_id % 32);
sb_bit_addr = sb_id / 32 * sizeof(u32);
sb_bit = 1 << (igu_sb_id % 32);
sb_bit_addr = igu_sb_id / 32 * sizeof(u32);
sb_bit_addr += IGU_REG_CLEANUP_STATUS_0 + (0x80 * type);
@ -1829,21 +1911,28 @@ static void ecore_int_igu_cleanup_sb(struct ecore_hwfn *p_hwfn,
if (!sleep_cnt)
DP_NOTICE(p_hwfn, true,
"Timeout waiting for clear status 0x%08x [for sb %d]\n",
val, sb_id);
val, igu_sb_id);
}
void ecore_int_igu_init_pure_rt_single(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
u32 sb_id, u16 opaque, bool b_set)
u16 igu_sb_id, u16 opaque, bool b_set)
{
struct ecore_igu_block *p_block;
int pi, i;
p_block = &p_hwfn->hw_info.p_igu_info->entry[igu_sb_id];
DP_VERBOSE(p_hwfn, ECORE_MSG_INTR,
"Cleaning SB [%04x]: func_id= %d is_pf = %d vector_num = 0x%0x\n",
igu_sb_id, p_block->function_id, p_block->is_pf,
p_block->vector_number);
/* Set */
if (b_set)
ecore_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 1, opaque);
ecore_int_igu_cleanup_sb(p_hwfn, p_ptt, igu_sb_id, 1, opaque);
/* Clear */
ecore_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 0, opaque);
ecore_int_igu_cleanup_sb(p_hwfn, p_ptt, igu_sb_id, 0, opaque);
/* Wait for the IGU SB to cleanup */
for (i = 0; i < IGU_CLEANUP_SLEEP_LENGTH; i++) {
@ -1851,8 +1940,8 @@ void ecore_int_igu_init_pure_rt_single(struct ecore_hwfn *p_hwfn,
val = ecore_rd(p_hwfn, p_ptt,
IGU_REG_WRITE_DONE_PENDING +
((sb_id / 32) * 4));
if (val & (1 << (sb_id % 32)))
((igu_sb_id / 32) * 4));
if (val & (1 << (igu_sb_id % 32)))
OSAL_UDELAY(10);
else
break;
@ -1860,21 +1949,22 @@ void ecore_int_igu_init_pure_rt_single(struct ecore_hwfn *p_hwfn,
if (i == IGU_CLEANUP_SLEEP_LENGTH)
DP_NOTICE(p_hwfn, true,
"Failed SB[0x%08x] still appearing in WRITE_DONE_PENDING\n",
sb_id);
igu_sb_id);
/* Clear the CAU for the SB */
for (pi = 0; pi < 12; pi++)
ecore_wr(p_hwfn, p_ptt,
CAU_REG_PI_MEMORY + (sb_id * 12 + pi) * 4, 0);
CAU_REG_PI_MEMORY + (igu_sb_id * 12 + pi) * 4, 0);
}
void ecore_int_igu_init_pure_rt(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
bool b_set, bool b_slowpath)
{
u32 igu_base_sb = p_hwfn->hw_info.p_igu_info->igu_base_sb;
u32 igu_sb_cnt = p_hwfn->hw_info.p_igu_info->igu_sb_cnt;
u32 sb_id = 0, val = 0;
struct ecore_igu_info *p_info = p_hwfn->hw_info.p_igu_info;
struct ecore_igu_block *p_block;
u16 igu_sb_id = 0;
u32 val = 0;
/* @@@TBD MichalK temporary... should be moved to init-tool... */
val = ecore_rd(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION);
@ -1883,53 +1973,204 @@ void ecore_int_igu_init_pure_rt(struct ecore_hwfn *p_hwfn,
ecore_wr(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION, val);
/* end temporary */
DP_VERBOSE(p_hwfn, ECORE_MSG_INTR,
"IGU cleaning SBs [%d,...,%d]\n",
igu_base_sb, igu_base_sb + igu_sb_cnt - 1);
for (igu_sb_id = 0;
igu_sb_id < ECORE_MAPPING_MEMORY_SIZE(p_hwfn->p_dev);
igu_sb_id++) {
p_block = &p_info->entry[igu_sb_id];
for (sb_id = igu_base_sb; sb_id < igu_base_sb + igu_sb_cnt; sb_id++)
ecore_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id,
if (!(p_block->status & ECORE_IGU_STATUS_VALID) ||
!p_block->is_pf ||
(p_block->status & ECORE_IGU_STATUS_DSB))
continue;
ecore_int_igu_init_pure_rt_single(p_hwfn, p_ptt, igu_sb_id,
p_hwfn->hw_info.opaque_fid,
b_set);
}
if (!b_slowpath)
return;
sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id;
DP_VERBOSE(p_hwfn, ECORE_MSG_INTR,
"IGU cleaning slowpath SB [%d]\n", sb_id);
ecore_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id,
p_hwfn->hw_info.opaque_fid, b_set);
if (b_slowpath)
ecore_int_igu_init_pure_rt_single(p_hwfn, p_ptt,
p_info->igu_dsb_id,
p_hwfn->hw_info.opaque_fid,
b_set);
}
static u32 ecore_int_igu_read_cam_block(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt, u16 sb_id)
int ecore_int_igu_reset_cam(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt)
{
struct ecore_igu_info *p_info = p_hwfn->hw_info.p_igu_info;
struct ecore_igu_block *p_block;
int pf_sbs, vf_sbs;
u16 igu_sb_id;
u32 val, rval;
if (!RESC_NUM(p_hwfn, ECORE_SB)) {
/* We're using an old MFW - have to prevent any switching
* of SBs between PF and VFs as later driver wouldn't be
* able to tell which belongs to which.
*/
p_info->b_allow_pf_vf_change = false;
} else {
/* Use the numbers the MFW have provided -
* don't forget MFW accounts for the default SB as well.
*/
p_info->b_allow_pf_vf_change = true;
if (p_info->usage.cnt != RESC_NUM(p_hwfn, ECORE_SB) - 1) {
DP_INFO(p_hwfn,
"MFW notifies of 0x%04x PF SBs; IGU indicates of only 0x%04x\n",
RESC_NUM(p_hwfn, ECORE_SB) - 1,
p_info->usage.cnt);
p_info->usage.cnt = RESC_NUM(p_hwfn, ECORE_SB) - 1;
}
/* TODO - how do we learn about VF SBs from MFW? */
if (IS_PF_SRIOV(p_hwfn)) {
u16 vfs = p_hwfn->p_dev->p_iov_info->total_vfs;
if (vfs != p_info->usage.iov_cnt)
DP_VERBOSE(p_hwfn, ECORE_MSG_INTR,
"0x%04x VF SBs in IGU CAM != PCI configuration 0x%04x\n",
p_info->usage.iov_cnt, vfs);
/* At this point we know how many SBs we have totally
* in IGU + number of PF SBs. So we can validate that
* we'd have sufficient for VF.
*/
if (vfs > p_info->usage.free_cnt +
p_info->usage.free_cnt_iov -
p_info->usage.cnt) {
DP_NOTICE(p_hwfn, true,
"Not enough SBs for VFs - 0x%04x SBs, from which %04x PFs and %04x are required\n",
p_info->usage.free_cnt +
p_info->usage.free_cnt_iov,
p_info->usage.cnt, vfs);
return ECORE_INVAL;
}
}
}
/* Cap the number of VFs SBs by the number of VFs */
if (IS_PF_SRIOV(p_hwfn))
p_info->usage.iov_cnt = p_hwfn->p_dev->p_iov_info->total_vfs;
/* Mark all SBs as free, now in the right PF/VFs division */
p_info->usage.free_cnt = p_info->usage.cnt;
p_info->usage.free_cnt_iov = p_info->usage.iov_cnt;
p_info->usage.orig = p_info->usage.cnt;
p_info->usage.iov_orig = p_info->usage.iov_cnt;
/* We now proceed to re-configure the IGU cam to reflect the initial
* configuration. We can start with the Default SB.
*/
pf_sbs = p_info->usage.cnt;
vf_sbs = p_info->usage.iov_cnt;
for (igu_sb_id = p_info->igu_dsb_id;
igu_sb_id < ECORE_MAPPING_MEMORY_SIZE(p_hwfn->p_dev);
igu_sb_id++) {
p_block = &p_info->entry[igu_sb_id];
val = 0;
if (!(p_block->status & ECORE_IGU_STATUS_VALID))
continue;
if (p_block->status & ECORE_IGU_STATUS_DSB) {
p_block->function_id = p_hwfn->rel_pf_id;
p_block->is_pf = 1;
p_block->vector_number = 0;
p_block->status = ECORE_IGU_STATUS_VALID |
ECORE_IGU_STATUS_PF |
ECORE_IGU_STATUS_DSB;
} else if (pf_sbs) {
pf_sbs--;
p_block->function_id = p_hwfn->rel_pf_id;
p_block->is_pf = 1;
p_block->vector_number = p_info->usage.cnt - pf_sbs;
p_block->status = ECORE_IGU_STATUS_VALID |
ECORE_IGU_STATUS_PF |
ECORE_IGU_STATUS_FREE;
} else if (vf_sbs) {
p_block->function_id =
p_hwfn->p_dev->p_iov_info->first_vf_in_pf +
p_info->usage.iov_cnt - vf_sbs;
p_block->is_pf = 0;
p_block->vector_number = 0;
p_block->status = ECORE_IGU_STATUS_VALID |
ECORE_IGU_STATUS_FREE;
vf_sbs--;
} else {
p_block->function_id = 0;
p_block->is_pf = 0;
p_block->vector_number = 0;
}
SET_FIELD(val, IGU_MAPPING_LINE_FUNCTION_NUMBER,
p_block->function_id);
SET_FIELD(val, IGU_MAPPING_LINE_PF_VALID, p_block->is_pf);
SET_FIELD(val, IGU_MAPPING_LINE_VECTOR_NUMBER,
p_block->vector_number);
/* VF entries would be enabled when VF is initializaed */
SET_FIELD(val, IGU_MAPPING_LINE_VALID, p_block->is_pf);
rval = ecore_rd(p_hwfn, p_ptt,
IGU_REG_MAPPING_MEMORY +
sizeof(u32) * igu_sb_id);
if (rval != val) {
ecore_wr(p_hwfn, p_ptt,
IGU_REG_MAPPING_MEMORY +
sizeof(u32) * igu_sb_id,
val);
DP_VERBOSE(p_hwfn, ECORE_MSG_INTR,
"IGU reset: [SB 0x%04x] func_id = %d is_pf = %d vector_num = 0x%x [%08x -> %08x]\n",
igu_sb_id, p_block->function_id,
p_block->is_pf, p_block->vector_number,
rval, val);
}
}
return 0;
}
int ecore_int_igu_reset_cam_default(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt)
{
struct ecore_sb_cnt_info *p_cnt = &p_hwfn->hw_info.p_igu_info->usage;
/* Return all the usage indications to default prior to the reset;
* The reset expects the !orig to reflect the initial status of the
* SBs, and would re-calculate the originals based on those.
*/
p_cnt->cnt = p_cnt->orig;
p_cnt->free_cnt = p_cnt->orig;
p_cnt->iov_cnt = p_cnt->iov_orig;
p_cnt->free_cnt_iov = p_cnt->iov_orig;
p_cnt->orig = 0;
p_cnt->iov_orig = 0;
/* TODO - we probably need to re-configure the CAU as well... */
return ecore_int_igu_reset_cam(p_hwfn, p_ptt);
}
static void ecore_int_igu_read_cam_block(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
u16 igu_sb_id)
{
u32 val = ecore_rd(p_hwfn, p_ptt,
IGU_REG_MAPPING_MEMORY + sizeof(u32) * sb_id);
IGU_REG_MAPPING_MEMORY + sizeof(u32) * igu_sb_id);
struct ecore_igu_block *p_block;
p_block = &p_hwfn->hw_info.p_igu_info->igu_map.igu_blocks[sb_id];
/* stop scanning when hit first invalid PF entry */
if (!GET_FIELD(val, IGU_MAPPING_LINE_VALID) &&
GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID))
goto out;
p_block = &p_hwfn->hw_info.p_igu_info->entry[igu_sb_id];
/* Fill the block information */
p_block->status = ECORE_IGU_STATUS_VALID;
p_block->function_id = GET_FIELD(val, IGU_MAPPING_LINE_FUNCTION_NUMBER);
p_block->is_pf = GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID);
p_block->vector_number = GET_FIELD(val, IGU_MAPPING_LINE_VECTOR_NUMBER);
DP_VERBOSE(p_hwfn, ECORE_MSG_INTR,
"IGU_BLOCK: [SB 0x%04x, Value in CAM 0x%08x] func_id = %d"
" is_pf = %d vector_num = 0x%x\n",
sb_id, val, p_block->function_id, p_block->is_pf,
p_block->vector_number);
out:
return val;
p_block->igu_sb_id = igu_sb_id;
}
enum _ecore_status_t ecore_int_igu_read_cam(struct ecore_hwfn *p_hwfn,
@ -1937,140 +2178,217 @@ enum _ecore_status_t ecore_int_igu_read_cam(struct ecore_hwfn *p_hwfn,
{
struct ecore_igu_info *p_igu_info;
struct ecore_igu_block *p_block;
u32 min_vf = 0, max_vf = 0, val;
u16 sb_id, last_iov_sb_id = 0;
u16 prev_sb_id = 0xFF;
u32 min_vf = 0, max_vf = 0;
u16 igu_sb_id;
p_hwfn->hw_info.p_igu_info = OSAL_ALLOC(p_hwfn->p_dev,
GFP_KERNEL,
sizeof(*p_igu_info));
p_hwfn->hw_info.p_igu_info = OSAL_ZALLOC(p_hwfn->p_dev,
GFP_KERNEL,
sizeof(*p_igu_info));
if (!p_hwfn->hw_info.p_igu_info)
return ECORE_NOMEM;
OSAL_MEMSET(p_hwfn->hw_info.p_igu_info, 0, sizeof(*p_igu_info));
p_igu_info = p_hwfn->hw_info.p_igu_info;
/* Initialize base sb / sb cnt for PFs and VFs */
p_igu_info->igu_base_sb = 0xffff;
p_igu_info->igu_sb_cnt = 0;
p_igu_info->igu_dsb_id = 0xffff;
p_igu_info->igu_base_sb_iov = 0xffff;
/* Distinguish between existent and onn-existent default SB */
p_igu_info->igu_dsb_id = ECORE_SB_INVALID_IDX;
/* Find the range of VF ids whose SB belong to this PF */
if (p_hwfn->p_dev->p_iov_info) {
struct ecore_hw_sriov_info *p_iov = p_hwfn->p_dev->p_iov_info;
min_vf = p_iov->first_vf_in_pf;
max_vf = p_iov->first_vf_in_pf + p_iov->total_vfs;
}
for (sb_id = 0;
sb_id < ECORE_MAPPING_MEMORY_SIZE(p_hwfn->p_dev);
sb_id++) {
p_block = &p_igu_info->igu_map.igu_blocks[sb_id];
val = ecore_int_igu_read_cam_block(p_hwfn, p_ptt, sb_id);
if (!GET_FIELD(val, IGU_MAPPING_LINE_VALID) &&
GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID))
break;
if (p_block->is_pf) {
if (p_block->function_id == p_hwfn->rel_pf_id) {
p_block->status |= ECORE_IGU_STATUS_PF;
for (igu_sb_id = 0;
igu_sb_id < ECORE_MAPPING_MEMORY_SIZE(p_hwfn->p_dev);
igu_sb_id++) {
/* Read current entry; Notice it might not belong to this PF */
ecore_int_igu_read_cam_block(p_hwfn, p_ptt, igu_sb_id);
p_block = &p_igu_info->entry[igu_sb_id];
if (p_block->vector_number == 0) {
if (p_igu_info->igu_dsb_id == 0xffff)
p_igu_info->igu_dsb_id = sb_id;
} else {
if (p_igu_info->igu_base_sb == 0xffff) {
p_igu_info->igu_base_sb = sb_id;
} else if (prev_sb_id != sb_id - 1) {
DP_NOTICE(p_hwfn->p_dev, false,
"consecutive igu"
" vectors for HWFN"
" %x broken",
p_hwfn->rel_pf_id);
break;
}
prev_sb_id = sb_id;
/* we don't count the default */
(p_igu_info->igu_sb_cnt)++;
}
}
} else {
if ((p_block->function_id >= min_vf) &&
(p_block->function_id < max_vf)) {
/* Available for VFs of this PF */
if (p_igu_info->igu_base_sb_iov == 0xffff) {
p_igu_info->igu_base_sb_iov = sb_id;
} else if (last_iov_sb_id != sb_id - 1) {
if (!val)
DP_VERBOSE(p_hwfn->p_dev,
ECORE_MSG_INTR,
"First uninited IGU"
" CAM entry at"
" index 0x%04x\n",
sb_id);
else
DP_NOTICE(p_hwfn->p_dev, false,
"Consecutive igu"
" vectors for HWFN"
" %x vfs is broken"
" [jumps from %04x"
" to %04x]\n",
p_hwfn->rel_pf_id,
last_iov_sb_id,
sb_id);
break;
}
p_block->status |= ECORE_IGU_STATUS_FREE;
p_hwfn->hw_info.p_igu_info->free_blks++;
last_iov_sb_id = sb_id;
}
if ((p_block->is_pf) &&
(p_block->function_id == p_hwfn->rel_pf_id)) {
p_block->status = ECORE_IGU_STATUS_PF |
ECORE_IGU_STATUS_VALID |
ECORE_IGU_STATUS_FREE;
if (p_igu_info->igu_dsb_id != ECORE_SB_INVALID_IDX)
p_igu_info->usage.cnt++;
} else if (!(p_block->is_pf) &&
(p_block->function_id >= min_vf) &&
(p_block->function_id < max_vf)) {
/* Available for VFs of this PF */
p_block->status = ECORE_IGU_STATUS_VALID |
ECORE_IGU_STATUS_FREE;
if (p_igu_info->igu_dsb_id != ECORE_SB_INVALID_IDX)
p_igu_info->usage.iov_cnt++;
}
/* Mark the First entry belonging to the PF or its VFs
* as the default SB [we'll reset IGU prior to first usage].
*/
if ((p_block->status & ECORE_IGU_STATUS_VALID) &&
(p_igu_info->igu_dsb_id == ECORE_SB_INVALID_IDX)) {
p_igu_info->igu_dsb_id = igu_sb_id;
p_block->status |= ECORE_IGU_STATUS_DSB;
}
/* While this isn't suitable for all clients, limit number
* of prints by having each PF print only its entries with the
* exception of PF0 which would print everything.
*/
if ((p_block->status & ECORE_IGU_STATUS_VALID) ||
(p_hwfn->abs_pf_id == 0))
DP_VERBOSE(p_hwfn, ECORE_MSG_INTR,
"IGU_BLOCK: [SB 0x%04x] func_id = %d is_pf = %d vector_num = 0x%x\n",
igu_sb_id, p_block->function_id,
p_block->is_pf, p_block->vector_number);
}
/* 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,
"IGU igu_base_sb=0x%x [IOV 0x%x] igu_sb_cnt=%d [IOV 0x%x] "
"igu_dsb_id=0x%x\n",
p_igu_info->igu_base_sb, p_igu_info->igu_base_sb_iov,
p_igu_info->igu_sb_cnt, p_igu_info->igu_sb_cnt_iov,
p_igu_info->igu_dsb_id);
if (p_igu_info->igu_base_sb == 0xffff ||
p_igu_info->igu_dsb_id == 0xffff || p_igu_info->igu_sb_cnt == 0) {
if (p_igu_info->igu_dsb_id == ECORE_SB_INVALID_IDX) {
DP_NOTICE(p_hwfn, true,
"IGU CAM returned invalid values igu_base_sb=0x%x "
"igu_sb_cnt=%d igu_dsb_id=0x%x\n",
p_igu_info->igu_base_sb, p_igu_info->igu_sb_cnt,
"IGU CAM returned invalid values igu_dsb_id=0x%x\n",
p_igu_info->igu_dsb_id);
return ECORE_INVAL;
}
/* All non default SB are considered free at this point */
p_igu_info->usage.free_cnt = p_igu_info->usage.cnt;
p_igu_info->usage.free_cnt_iov = p_igu_info->usage.iov_cnt;
DP_VERBOSE(p_hwfn, ECORE_MSG_INTR,
"igu_dsb_id=0x%x, num Free SBs - PF: %04x VF: %04x [might change after resource allocation]\n",
p_igu_info->igu_dsb_id, p_igu_info->usage.cnt,
p_igu_info->usage.iov_cnt);
return ECORE_SUCCESS;
}
enum _ecore_status_t
ecore_int_igu_relocate_sb(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
u16 sb_id, bool b_to_vf)
{
struct ecore_igu_info *p_info = p_hwfn->hw_info.p_igu_info;
struct ecore_igu_block *p_block = OSAL_NULL;
u16 igu_sb_id = 0, vf_num = 0;
u32 val = 0;
if (IS_VF(p_hwfn->p_dev) || !IS_PF_SRIOV(p_hwfn))
return ECORE_INVAL;
if (sb_id == ECORE_SP_SB_ID)
return ECORE_INVAL;
if (!p_info->b_allow_pf_vf_change) {
DP_INFO(p_hwfn, "Can't relocate SBs as MFW is too old.\n");
return ECORE_INVAL;
}
/* If we're moving a SB from PF to VF, the client had to specify
* which vector it wants to move.
*/
if (b_to_vf) {
igu_sb_id = ecore_get_pf_igu_sb_id(p_hwfn, sb_id + 1);
if (igu_sb_id == ECORE_SB_INVALID_IDX)
return ECORE_INVAL;
}
/* If we're moving a SB from VF to PF, need to validate there isn't
* already a line configured for that vector.
*/
if (!b_to_vf) {
if (ecore_get_pf_igu_sb_id(p_hwfn, sb_id + 1) !=
ECORE_SB_INVALID_IDX)
return ECORE_INVAL;
}
/* We need to validate that the SB can actually be relocated.
* This would also handle the previous case where we've explicitly
* stated which IGU SB needs to move.
*/
for (; igu_sb_id < ECORE_MAPPING_MEMORY_SIZE(p_hwfn->p_dev);
igu_sb_id++) {
p_block = &p_info->entry[igu_sb_id];
if (!(p_block->status & ECORE_IGU_STATUS_VALID) ||
!(p_block->status & ECORE_IGU_STATUS_FREE) ||
(!!(p_block->status & ECORE_IGU_STATUS_PF) != b_to_vf)) {
if (b_to_vf)
return ECORE_INVAL;
else
continue;
}
break;
}
if (igu_sb_id == ECORE_MAPPING_MEMORY_SIZE(p_hwfn->p_dev)) {
DP_VERBOSE(p_hwfn, (ECORE_MSG_INTR | ECORE_MSG_IOV),
"Failed to find a free SB to move\n");
return ECORE_INVAL;
}
/* At this point, p_block points to the SB we want to relocate */
if (b_to_vf) {
p_block->status &= ~ECORE_IGU_STATUS_PF;
/* It doesn't matter which VF number we choose, since we're
* going to disable the line; But let's keep it in range.
*/
vf_num = (u16)p_hwfn->p_dev->p_iov_info->first_vf_in_pf;
p_block->function_id = (u8)vf_num;
p_block->is_pf = 0;
p_block->vector_number = 0;
p_info->usage.cnt--;
p_info->usage.free_cnt--;
p_info->usage.iov_cnt++;
p_info->usage.free_cnt_iov++;
/* TODO - if SBs aren't really the limiting factor,
* then it might not be accurate [in the since that
* we might not need decrement the feature].
*/
p_hwfn->hw_info.feat_num[ECORE_PF_L2_QUE]--;
p_hwfn->hw_info.feat_num[ECORE_VF_L2_QUE]++;
} else {
p_block->status |= ECORE_IGU_STATUS_PF;
p_block->function_id = p_hwfn->rel_pf_id;
p_block->is_pf = 1;
p_block->vector_number = sb_id + 1;
p_info->usage.cnt++;
p_info->usage.free_cnt++;
p_info->usage.iov_cnt--;
p_info->usage.free_cnt_iov--;
p_hwfn->hw_info.feat_num[ECORE_PF_L2_QUE]++;
p_hwfn->hw_info.feat_num[ECORE_VF_L2_QUE]--;
}
/* Update the IGU and CAU with the new configuration */
SET_FIELD(val, IGU_MAPPING_LINE_FUNCTION_NUMBER,
p_block->function_id);
SET_FIELD(val, IGU_MAPPING_LINE_PF_VALID, p_block->is_pf);
SET_FIELD(val, IGU_MAPPING_LINE_VALID, p_block->is_pf);
SET_FIELD(val, IGU_MAPPING_LINE_VECTOR_NUMBER,
p_block->vector_number);
ecore_wr(p_hwfn, p_ptt,
IGU_REG_MAPPING_MEMORY + sizeof(u32) * igu_sb_id,
val);
ecore_int_cau_conf_sb(p_hwfn, p_ptt, 0,
igu_sb_id, vf_num,
p_block->is_pf ? 0 : 1);
DP_VERBOSE(p_hwfn, ECORE_MSG_INTR,
"Relocation: [SB 0x%04x] func_id = %d is_pf = %d vector_num = 0x%x\n",
igu_sb_id, p_block->function_id,
p_block->is_pf, p_block->vector_number);
return ECORE_SUCCESS;
}
@ -2170,14 +2488,13 @@ void ecore_int_setup(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
void ecore_int_get_num_sbs(struct ecore_hwfn *p_hwfn,
struct ecore_sb_cnt_info *p_sb_cnt_info)
{
struct ecore_igu_info *info = p_hwfn->hw_info.p_igu_info;
struct ecore_igu_info *p_igu_info = p_hwfn->hw_info.p_igu_info;
if (!info || !p_sb_cnt_info)
if (!p_igu_info || !p_sb_cnt_info)
return;
p_sb_cnt_info->sb_cnt = info->igu_sb_cnt;
p_sb_cnt_info->sb_iov_cnt = info->igu_sb_cnt_iov;
p_sb_cnt_info->sb_free_blk = info->free_blks;
OSAL_MEMCPY(p_sb_cnt_info, &p_igu_info->usage,
sizeof(*p_sb_cnt_info));
}
void ecore_int_disable_post_isr_release(struct ecore_dev *p_dev)

View File

@ -21,31 +21,76 @@
#define SB_ALIGNED_SIZE(p_hwfn) \
ALIGNED_TYPE_SIZE(struct status_block, p_hwfn)
#define ECORE_SB_INVALID_IDX 0xffff
struct ecore_igu_block {
u8 status;
#define ECORE_IGU_STATUS_FREE 0x01
#define ECORE_IGU_STATUS_VALID 0x02
#define ECORE_IGU_STATUS_PF 0x04
#define ECORE_IGU_STATUS_DSB 0x08
u8 vector_number;
u8 function_id;
u8 is_pf;
};
struct ecore_igu_map {
struct ecore_igu_block igu_blocks[MAX_TOT_SB_PER_PATH];
/* Index inside IGU [meant for back reference] */
u16 igu_sb_id;
struct ecore_sb_info *sb_info;
};
struct ecore_igu_info {
struct ecore_igu_map igu_map;
struct ecore_igu_block entry[MAX_TOT_SB_PER_PATH];
u16 igu_dsb_id;
u16 igu_base_sb;
u16 igu_base_sb_iov;
u16 igu_sb_cnt;
u16 igu_sb_cnt_iov;
u16 free_blks;
/* The numbers can shift when using APIs to switch SBs between PF and
* VF.
*/
struct ecore_sb_cnt_info usage;
/* Determine whether we can shift SBs between VFs and PFs */
bool b_allow_pf_vf_change;
};
/**
* @brief - Make sure the IGU CAM reflects the resources provided by MFW
*
* @param p_hwfn
* @param p_ptt
*/
int ecore_int_igu_reset_cam(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt);
/**
* @brief - Make sure IGU CAM reflects the default resources once again,
* starting with a 'dirty' SW database.
* @param p_hwfn
* @param p_ptt
*/
int ecore_int_igu_reset_cam_default(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt);
/**
* @brief Translate the weakly-defined client sb-id into an IGU sb-id
*
* @param p_hwfn
* @param sb_id - user provided sb_id
*
* @return an index inside IGU CAM where the SB resides
*/
u16 ecore_get_igu_sb_id(struct ecore_hwfn *p_hwfn, u16 sb_id);
/**
* @brief return a pointer to an unused valid SB
*
* @param p_hwfn
* @param b_is_pf - true iff we want a SB belonging to a PF
*
* @return point to an igu_block, OSAL_NULL if none is available
*/
struct ecore_igu_block *
ecore_get_igu_free_sb(struct ecore_hwfn *p_hwfn, bool b_is_pf);
/* TODO Names of function may change... */
void ecore_int_igu_init_pure_rt(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
@ -125,9 +170,11 @@ u16 ecore_int_get_sp_sb_id(struct ecore_hwfn *p_hwfn);
* @param opaque - opaque fid of the sb owner.
* @param cleanup_set - set(1) / clear(0)
*/
void ecore_int_igu_init_pure_rt_single(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
u32 sb_id, u16 opaque, bool b_set);
void ecore_int_igu_init_pure_rt_single(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
u16 sb_id,
u16 opaque,
bool b_set);
/**
* @brief ecore_int_cau_conf - configure cau for a given status

View File

@ -48,9 +48,15 @@ struct ecore_sb_info_dbg {
};
struct ecore_sb_cnt_info {
int sb_cnt;
int sb_iov_cnt;
int sb_free_blk;
/* Original, current, and free SBs for PF */
int orig;
int cnt;
int free_cnt;
/* Original, current and free SBS for child VFs */
int iov_orig;
int iov_cnt;
int free_cnt_iov;
};
static OSAL_INLINE u16 ecore_sb_update_sb_idx(struct ecore_sb_info *sb_info)
@ -173,17 +179,17 @@ enum ecore_coalescing_fsm {
*
* @param p_hwfn
* @param p_ptt
* @param igu_sb_id
* @param p_sb
* @param pi_index
* @param state
* @param timeset
*/
void ecore_int_cau_conf_pi(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
u16 igu_sb_id,
u32 pi_index,
enum ecore_coalescing_fsm coalescing_fsm,
u8 timeset);
void ecore_int_cau_conf_pi(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt,
struct ecore_sb_info *p_sb,
u32 pi_index,
enum ecore_coalescing_fsm coalescing_fsm,
u8 timeset);
/**
*
@ -219,6 +225,7 @@ void ecore_int_igu_disable_int(struct ecore_hwfn *p_hwfn,
u64 ecore_int_igu_read_sisr_reg(struct ecore_hwfn *p_hwfn);
#define ECORE_SP_SB_ID 0xffff
/**
* @brief ecore_int_sb_init - Initializes the sb_info structure.
*
@ -324,4 +331,18 @@ enum _ecore_status_t ecore_int_get_sb_dbg(struct ecore_hwfn *p_hwfn,
struct ecore_sb_info *p_sb,
struct ecore_sb_info_dbg *p_info);
/**
* @brief - Move a free Status block between PF and child VF
*
* @param p_hwfn
* @param p_ptt
* @param sb_id - The PF fastpath vector to be moved [re-assigned if claiming
* from VF, given-up if moving to VF]
* @param b_to_vf - PF->VF == true, VF->PF == false
*
* @return ECORE_SUCCESS if SB successfully moved.
*/
enum _ecore_status_t
ecore_int_igu_relocate_sb(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
u16 sb_id, bool b_to_vf);
#endif

View File

@ -207,9 +207,15 @@ _ecore_eth_queue_to_cid(struct ecore_hwfn *p_hwfn,
p_cid->opaque_fid = opaque_fid;
p_cid->cid = cid;
p_cid->rel = *p_params;
p_cid->p_owner = p_hwfn;
/* Fill in parameters */
p_cid->rel.vport_id = p_params->vport_id;
p_cid->rel.queue_id = p_params->queue_id;
p_cid->rel.stats_id = p_params->stats_id;
p_cid->sb_igu_id = p_params->p_sb->igu_sb_id;
p_cid->sb_idx = p_params->sb_idx;
/* Fill-in bits related to VFs' queues if information was provided */
if (p_vf_params != OSAL_NULL) {
p_cid->vfid = p_vf_params->vfid;
@ -251,10 +257,6 @@ _ecore_eth_queue_to_cid(struct ecore_hwfn *p_hwfn,
p_cid->abs.stats_id = p_cid->rel.stats_id;
}
/* SBs relevant information was already provided as absolute */
p_cid->abs.sb = p_cid->rel.sb;
p_cid->abs.sb_idx = p_cid->rel.sb_idx;
out:
/* VF-images have provided the qid_usage_idx on their own.
* Otherwise, we need to allocate a unique one.
@ -273,7 +275,7 @@ _ecore_eth_queue_to_cid(struct ecore_hwfn *p_hwfn,
p_cid->rel.queue_id, p_cid->qid_usage_idx,
p_cid->abs.queue_id,
p_cid->rel.stats_id, p_cid->abs.stats_id,
p_cid->abs.sb, p_cid->abs.sb_idx);
p_cid->sb_igu_id, p_cid->sb_idx);
return p_cid;
@ -901,7 +903,7 @@ ecore_eth_rxq_start_ramrod(struct ecore_hwfn *p_hwfn,
DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
"opaque_fid=0x%x, cid=0x%x, rx_qzone=0x%x, vport_id=0x%x, sb_id=0x%x\n",
p_cid->opaque_fid, p_cid->cid, p_cid->abs.queue_id,
p_cid->abs.vport_id, p_cid->abs.sb);
p_cid->abs.vport_id, p_cid->sb_igu_id);
/* Get SPQ entry */
OSAL_MEMSET(&init_data, 0, sizeof(init_data));
@ -917,8 +919,8 @@ ecore_eth_rxq_start_ramrod(struct ecore_hwfn *p_hwfn,
p_ramrod = &p_ent->ramrod.rx_queue_start;
p_ramrod->sb_id = OSAL_CPU_TO_LE16(p_cid->abs.sb);
p_ramrod->sb_index = p_cid->abs.sb_idx;
p_ramrod->sb_id = OSAL_CPU_TO_LE16(p_cid->sb_igu_id);
p_ramrod->sb_index = p_cid->sb_idx;
p_ramrod->vport_id = p_cid->abs.vport_id;
p_ramrod->stats_counter_id = p_cid->abs.stats_id;
p_ramrod->rx_queue_id = OSAL_CPU_TO_LE16(p_cid->abs.queue_id);
@ -1153,8 +1155,8 @@ ecore_eth_txq_start_ramrod(struct ecore_hwfn *p_hwfn,
p_ramrod = &p_ent->ramrod.tx_queue_start;
p_ramrod->vport_id = p_cid->abs.vport_id;
p_ramrod->sb_id = OSAL_CPU_TO_LE16(p_cid->abs.sb);
p_ramrod->sb_index = p_cid->abs.sb_idx;
p_ramrod->sb_id = OSAL_CPU_TO_LE16(p_cid->sb_igu_id);
p_ramrod->sb_index = p_cid->sb_idx;
p_ramrod->stats_counter_id = p_cid->abs.stats_id;
p_ramrod->queue_zone_id = OSAL_CPU_TO_LE16(p_cid->abs.queue_id);

View File

@ -18,7 +18,16 @@
#define MAX_QUEUES_PER_QZONE (sizeof(unsigned long) * 8)
#define ECORE_QUEUE_CID_PF (0xff)
/* Additional parameters required for initialization of the queue_cid
/* Almost identical to the ecore_queue_start_common_params,
* but here we maintain the SB index in IGU CAM.
*/
struct ecore_queue_cid_params {
u8 vport_id;
u16 queue_id;
u8 stats_id;
};
/* Additional parameters required for initialization of the queue_cid
* and are relevant only for a PF initializing one for its VFs.
*/
struct ecore_queue_cid_vf_params {
@ -44,13 +53,14 @@ struct ecore_queue_cid_vf_params {
};
struct ecore_queue_cid {
/* 'Relative' is a relative term ;-). Usually the indices [not counting
* SBs] would be PF-relative, but there are some cases where that isn't
* the case - specifically for a PF configuring its VF indices it's
* possible some fields [E.g., stats-id] in 'rel' would already be abs.
*/
struct ecore_queue_start_common_params rel;
struct ecore_queue_start_common_params abs;
/* For stats-id, the `rel' is actually absolute as well */
struct ecore_queue_cid_params rel;
struct ecore_queue_cid_params abs;
/* These have no 'relative' meaning */
u16 sb_igu_id;
u8 sb_idx;
u32 cid;
u16 opaque_fid;

View File

@ -11,6 +11,7 @@
#include "ecore_status.h"
#include "ecore_sp_api.h"
#include "ecore_int_api.h"
#ifndef __EXTRACT__LINUX__
enum ecore_rss_caps {
@ -35,8 +36,7 @@ struct ecore_queue_start_common_params {
/* Relative, but relevant only for PFs */
u8 stats_id;
/* These are always absolute */
u16 sb;
struct ecore_sb_info *p_sb;
u8 sb_idx;
};

View File

@ -446,33 +446,6 @@ static enum _ecore_status_t ecore_iov_pci_cfg_info(struct ecore_dev *p_dev)
return ECORE_SUCCESS;
}
static void ecore_iov_clear_vf_igu_blocks(struct ecore_hwfn *p_hwfn,
struct ecore_ptt *p_ptt)
{
struct ecore_igu_block *p_sb;
u16 sb_id;
u32 val;
if (!p_hwfn->hw_info.p_igu_info) {
DP_ERR(p_hwfn,
"ecore_iov_clear_vf_igu_blocks IGU Info not inited\n");
return;
}
for (sb_id = 0;
sb_id < ECORE_MAPPING_MEMORY_SIZE(p_hwfn->p_dev); sb_id++) {
p_sb = &p_hwfn->hw_info.p_igu_info->igu_map.igu_blocks[sb_id];
if ((p_sb->status & ECORE_IGU_STATUS_FREE) &&
!(p_sb->status & ECORE_IGU_STATUS_PF)) {
val = ecore_rd(p_hwfn, p_ptt,
IGU_REG_MAPPING_MEMORY + sb_id * 4);
SET_FIELD(val, IGU_MAPPING_LINE_VALID, 0);
ecore_wr(p_hwfn, p_ptt,
IGU_REG_MAPPING_MEMORY + 4 * sb_id, val);
}
}
}
static void ecore_iov_setup_vfdb(struct ecore_hwfn *p_hwfn)
{
struct ecore_hw_sriov_info *p_iov = p_hwfn->p_dev->p_iov_info;
@ -634,7 +607,6 @@ void ecore_iov_setup(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
return;
ecore_iov_setup_vfdb(p_hwfn);
ecore_iov_clear_vf_igu_blocks(p_hwfn, p_ptt);
}
void ecore_iov_free(struct ecore_hwfn *p_hwfn)
@ -938,46 +910,38 @@ static u8 ecore_iov_alloc_vf_igu_sbs(struct ecore_hwfn *p_hwfn,
struct ecore_vf_info *vf,
u16 num_rx_queues)
{
struct ecore_igu_block *igu_blocks;
int qid = 0, igu_id = 0;
struct ecore_igu_block *p_block;
struct cau_sb_entry sb_entry;
int qid = 0;
u32 val = 0;
igu_blocks = p_hwfn->hw_info.p_igu_info->igu_map.igu_blocks;
if (num_rx_queues > p_hwfn->hw_info.p_igu_info->free_blks)
num_rx_queues = p_hwfn->hw_info.p_igu_info->free_blks;
p_hwfn->hw_info.p_igu_info->free_blks -= num_rx_queues;
if (num_rx_queues > p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov)
num_rx_queues =
(u16)p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov;
p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov -= num_rx_queues;
SET_FIELD(val, IGU_MAPPING_LINE_FUNCTION_NUMBER, vf->abs_vf_id);
SET_FIELD(val, IGU_MAPPING_LINE_VALID, 1);
SET_FIELD(val, IGU_MAPPING_LINE_PF_VALID, 0);
while ((qid < num_rx_queues) &&
(igu_id < ECORE_MAPPING_MEMORY_SIZE(p_hwfn->p_dev))) {
if (igu_blocks[igu_id].status & ECORE_IGU_STATUS_FREE) {
struct cau_sb_entry sb_entry;
for (qid = 0; qid < num_rx_queues; qid++) {
p_block = ecore_get_igu_free_sb(p_hwfn, false);
vf->igu_sbs[qid] = p_block->igu_sb_id;
p_block->status &= ~ECORE_IGU_STATUS_FREE;
SET_FIELD(val, IGU_MAPPING_LINE_VECTOR_NUMBER, qid);
vf->igu_sbs[qid] = (u16)igu_id;
igu_blocks[igu_id].status &= ~ECORE_IGU_STATUS_FREE;
ecore_wr(p_hwfn, p_ptt,
IGU_REG_MAPPING_MEMORY +
sizeof(u32) * p_block->igu_sb_id, val);
SET_FIELD(val, IGU_MAPPING_LINE_VECTOR_NUMBER, qid);
ecore_wr(p_hwfn, p_ptt,
IGU_REG_MAPPING_MEMORY + sizeof(u32) * igu_id,
val);
/* Configure igu sb in CAU which were marked valid */
ecore_init_cau_sb_entry(p_hwfn, &sb_entry,
p_hwfn->rel_pf_id,
vf->abs_vf_id, 1);
ecore_dmae_host2grc(p_hwfn, p_ptt,
(u64)(osal_uintptr_t)&sb_entry,
CAU_REG_SB_VAR_MEMORY +
igu_id * sizeof(u64), 2, 0);
qid++;
}
igu_id++;
/* Configure igu sb in CAU which were marked valid */
ecore_init_cau_sb_entry(p_hwfn, &sb_entry,
p_hwfn->rel_pf_id,
vf->abs_vf_id, 1);
ecore_dmae_host2grc(p_hwfn, p_ptt,
(u64)(osal_uintptr_t)&sb_entry,
CAU_REG_SB_VAR_MEMORY +
p_block->igu_sb_id * sizeof(u64), 2, 0);
}
vf->num_sbs = (u8)num_rx_queues;
@ -1013,10 +977,8 @@ static void ecore_iov_free_vf_igu_sbs(struct ecore_hwfn *p_hwfn,
SET_FIELD(val, IGU_MAPPING_LINE_VALID, 0);
ecore_wr(p_hwfn, p_ptt, addr, val);
p_info->igu_map.igu_blocks[igu_id].status |=
ECORE_IGU_STATUS_FREE;
p_hwfn->hw_info.p_igu_info->free_blks++;
p_info->entry[igu_id].status |= ECORE_IGU_STATUS_FREE;
p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov++;
}
vf->num_sbs = 0;
@ -1114,34 +1076,28 @@ ecore_iov_init_hw_for_vf(struct ecore_hwfn *p_hwfn,
vf->vport_id = p_params->vport_id;
vf->rss_eng_id = p_params->rss_eng_id;
/* Perform sanity checking on the requested queue_id */
/* Since it's possible to relocate SBs, it's a bit difficult to check
* things here. Simply check whether the index falls in the range
* belonging to the PF.
*/
for (i = 0; i < p_params->num_queues; i++) {
u16 min_vf_qzone = (u16)FEAT_NUM(p_hwfn, ECORE_PF_L2_QUE);
u16 max_vf_qzone = min_vf_qzone +
FEAT_NUM(p_hwfn, ECORE_VF_L2_QUE) - 1;
qid = p_params->req_rx_queue[i];
if (qid < min_vf_qzone || qid > max_vf_qzone) {
if (qid > (u16)RESC_NUM(p_hwfn, ECORE_L2_QUEUE)) {
DP_NOTICE(p_hwfn, true,
"Can't enable Rx qid [%04x] for VF[%d]: qids [0x%04x,...,0x%04x] available\n",
"Can't enable Rx qid [%04x] for VF[%d]: qids [0,,...,0x%04x] available\n",
qid, p_params->rel_vf_id,
min_vf_qzone, max_vf_qzone);
(u16)RESC_NUM(p_hwfn, ECORE_L2_QUEUE));
return ECORE_INVAL;
}
qid = p_params->req_tx_queue[i];
if (qid > max_vf_qzone) {
if (qid > (u16)RESC_NUM(p_hwfn, ECORE_L2_QUEUE)) {
DP_NOTICE(p_hwfn, true,
"Can't enable Tx qid [%04x] for VF[%d]: max qid 0x%04x\n",
qid, p_params->rel_vf_id, max_vf_qzone);
"Can't enable Tx qid [%04x] for VF[%d]: qids [0,,...,0x%04x] available\n",
qid, p_params->rel_vf_id,
(u16)RESC_NUM(p_hwfn, ECORE_L2_QUEUE));
return ECORE_INVAL;
}
/* If client *really* wants, Tx qid can be shared with PF */
if (qid < min_vf_qzone)
DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
"VF[%d] is using PF qid [0x%04x] for Txq[0x%02x]\n",
p_params->rel_vf_id, qid, i);
}
/* Limit number of queues according to number of CIDs */
@ -2233,6 +2189,7 @@ static void ecore_iov_vf_mbx_start_rxq(struct ecore_hwfn *p_hwfn,
struct ecore_vf_queue *p_queue;
struct vfpf_start_rxq_tlv *req;
struct ecore_queue_cid *p_cid;
struct ecore_sb_info sb_dummy;
enum _ecore_status_t rc;
req = &mbx->req_virt->start_rxq;
@ -2257,7 +2214,11 @@ static void ecore_iov_vf_mbx_start_rxq(struct ecore_hwfn *p_hwfn,
params.queue_id = (u8)p_queue->fw_rx_qid;
params.vport_id = vf->vport_id;
params.stats_id = vf->abs_vf_id + 0x10;
params.sb = req->hw_sb;
/* Since IGU index is passed via sb_info, construct a dummy one */
OSAL_MEM_ZERO(&sb_dummy, sizeof(sb_dummy));
sb_dummy.igu_sb_id = req->hw_sb;
params.p_sb = &sb_dummy;
params.sb_idx = req->sb_index;
OSAL_MEM_ZERO(&vf_params, sizeof(vf_params));
@ -2500,6 +2461,7 @@ static void ecore_iov_vf_mbx_start_txq(struct ecore_hwfn *p_hwfn,
struct ecore_vf_queue *p_queue;
struct vfpf_start_txq_tlv *req;
struct ecore_queue_cid *p_cid;
struct ecore_sb_info sb_dummy;
u8 qid_usage_idx, vf_legacy;
u32 cid = 0;
enum _ecore_status_t rc;
@ -2527,7 +2489,11 @@ static void ecore_iov_vf_mbx_start_txq(struct ecore_hwfn *p_hwfn,
params.queue_id = p_queue->fw_tx_qid;
params.vport_id = vf->vport_id;
params.stats_id = vf->abs_vf_id + 0x10;
params.sb = req->hw_sb;
/* Since IGU index is passed via sb_info, construct a dummy one */
OSAL_MEM_ZERO(&sb_dummy, sizeof(sb_dummy));
sb_dummy.igu_sb_id = req->hw_sb;
params.p_sb = &sb_dummy;
params.sb_idx = req->sb_index;
OSAL_MEM_ZERO(&vf_params, sizeof(vf_params));

View File

@ -652,8 +652,8 @@ ecore_vf_pf_rxq_start(struct ecore_hwfn *p_hwfn,
req->cqe_pbl_addr = cqe_pbl_addr;
req->cqe_pbl_size = cqe_pbl_size;
req->rxq_addr = bd_chain_phys_addr;
req->hw_sb = p_cid->rel.sb;
req->sb_index = p_cid->rel.sb_idx;
req->hw_sb = p_cid->sb_igu_id;
req->sb_index = p_cid->sb_idx;
req->bd_max_bytes = bd_max_bytes;
req->stat_id = -1; /* Keep initialized, for future compatibility */
@ -774,8 +774,8 @@ ecore_vf_pf_txq_start(struct ecore_hwfn *p_hwfn,
/* Tx */
req->pbl_addr = pbl_addr;
req->pbl_size = pbl_size;
req->hw_sb = p_cid->rel.sb;
req->sb_index = p_cid->rel.sb_idx;
req->hw_sb = p_cid->sb_igu_id;
req->sb_index = p_cid->sb_idx;
ecore_vf_pf_add_qid(p_hwfn, p_cid);
@ -930,9 +930,12 @@ ecore_vf_pf_vport_start(struct ecore_hwfn *p_hwfn, u8 vport_id,
req->only_untagged = only_untagged;
/* status blocks */
for (i = 0; i < p_hwfn->vf_iov_info->acquire_resp.resc.num_sbs; i++)
if (p_hwfn->sbs_info[i])
req->sb_addr[i] = p_hwfn->sbs_info[i]->sb_phys;
for (i = 0; i < p_hwfn->vf_iov_info->acquire_resp.resc.num_sbs; i++) {
struct ecore_sb_info *p_sb = p_hwfn->vf_iov_info->sbs_info[i];
if (p_sb)
req->sb_addr[i] = p_sb->sb_phys;
}
/* add list termination tlv */
ecore_add_tlv(p_hwfn, &p_iov->offset,
@ -1501,6 +1504,24 @@ u16 ecore_vf_get_igu_sb_id(struct ecore_hwfn *p_hwfn,
return p_iov->acquire_resp.resc.hw_sbs[sb_id].hw_sb_id;
}
void ecore_vf_set_sb_info(struct ecore_hwfn *p_hwfn,
u16 sb_id, struct ecore_sb_info *p_sb)
{
struct ecore_vf_iov *p_iov = p_hwfn->vf_iov_info;
if (!p_iov) {
DP_NOTICE(p_hwfn, true, "vf_sriov_info isn't initialized\n");
return;
}
if (sb_id >= PFVF_MAX_SBS_PER_VF) {
DP_NOTICE(p_hwfn, true, "Can't configure SB %04x\n", sb_id);
return;
}
p_iov->sbs_info[sb_id] = p_sb;
}
enum _ecore_status_t ecore_vf_read_bulletin(struct ecore_hwfn *p_hwfn,
u8 *p_change)
{

View File

@ -41,6 +41,14 @@ struct ecore_vf_iov {
* this has to be propagated as it affects the fastpath.
*/
bool b_pre_fp_hsi;
/* Current day VFs are passing the SBs physical address on vport
* start, and as they lack an IGU mapping they need to store the
* addresses of previously registered SBs.
* Even if we were to change configuration flow, due to backward
* compatibility [with older PFs] we'd still need to store these.
*/
struct ecore_sb_info *sbs_info[PFVF_MAX_SBS_PER_VF];
};
@ -205,6 +213,15 @@ enum _ecore_status_t ecore_vf_pf_release(struct ecore_hwfn *p_hwfn);
u16 ecore_vf_get_igu_sb_id(struct ecore_hwfn *p_hwfn,
u16 sb_id);
/**
* @brief Stores [or removes] a configured sb_info.
*
* @param p_hwfn
* @param sb_id - zero-based SB index [for fastpath]
* @param sb_info - may be OSAL_NULL [during removal].
*/
void ecore_vf_set_sb_info(struct ecore_hwfn *p_hwfn,
u16 sb_id, struct ecore_sb_info *p_sb);
/**
* @brief ecore_vf_pf_vport_start - perform vport start for VF.

View File

@ -555,7 +555,7 @@ qede_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
params.queue_id = rx_queue_id / edev->num_hwfns;
params.vport_id = 0;
params.stats_id = params.vport_id;
params.sb = fp->sb_info->igu_sb_id;
params.p_sb = fp->sb_info;
DP_INFO(edev, "rxq %u igu_sb_id 0x%x\n",
fp->rxq->queue_id, fp->sb_info->igu_sb_id);
params.sb_idx = RX_PI;
@ -614,7 +614,7 @@ qede_tx_queue_start(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id)
params.queue_id = tx_queue_id / edev->num_hwfns;
params.vport_id = 0;
params.stats_id = params.vport_id;
params.sb = fp->sb_info->igu_sb_id;
params.p_sb = fp->sb_info;
DP_INFO(edev, "txq %u igu_sb_id 0x%x\n",
fp->txq->queue_id, fp->sb_info->igu_sb_id);
params.sb_idx = TX_PI(0); /* tc = 0 */