Commit d749dd0d authored by Mintz, Yuval's avatar Mintz, Yuval Committed by David S. Miller

qed: IGU read revised

As a first step for relaxing various assumptions done by driver
about the IGU mapping, the driver is now going to read the entire
IGU into a shadow copy, and mark in its database each status block
that's relevant for it.
Signed-off-by: default avatarYuval Mintz <Yuval.Mintz@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 979cead3
...@@ -1167,7 +1167,7 @@ static void qed_init_cau_rt_data(struct qed_dev *cdev) ...@@ -1167,7 +1167,7 @@ static void qed_init_cau_rt_data(struct qed_dev *cdev)
for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(cdev); for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(cdev);
sb_id++) { sb_id++) {
p_block = &p_igu_info->igu_map.igu_blocks[sb_id]; p_block = &p_igu_info->entry[sb_id];
if (!p_block->is_pf) if (!p_block->is_pf)
continue; continue;
......
...@@ -1783,44 +1783,27 @@ void qed_int_igu_init_pure_rt(struct qed_hwfn *p_hwfn, ...@@ -1783,44 +1783,27 @@ void qed_int_igu_init_pure_rt(struct qed_hwfn *p_hwfn,
p_hwfn->hw_info.opaque_fid, b_set); p_hwfn->hw_info.opaque_fid, b_set);
} }
static u32 qed_int_igu_read_cam_block(struct qed_hwfn *p_hwfn, static void qed_int_igu_read_cam_block(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u16 sb_id) struct qed_ptt *p_ptt, u16 igu_sb_id)
{ {
u32 val = qed_rd(p_hwfn, p_ptt, u32 val = qed_rd(p_hwfn, p_ptt,
IGU_REG_MAPPING_MEMORY + sizeof(u32) * sb_id); IGU_REG_MAPPING_MEMORY + sizeof(u32) * igu_sb_id);
struct qed_igu_block *p_block; struct qed_igu_block *p_block;
p_block = &p_hwfn->hw_info.p_igu_info->igu_map.igu_blocks[sb_id]; p_block = &p_hwfn->hw_info.p_igu_info->entry[igu_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;
/* Fill the block information */ /* Fill the block information */
p_block->status = QED_IGU_STATUS_VALID; p_block->function_id = GET_FIELD(val, IGU_MAPPING_LINE_FUNCTION_NUMBER);
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->is_pf = GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID);
p_block->vector_number = GET_FIELD(val, p_block->vector_number = GET_FIELD(val, IGU_MAPPING_LINE_VECTOR_NUMBER);
IGU_MAPPING_LINE_VECTOR_NUMBER);
DP_VERBOSE(p_hwfn, NETIF_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;
} }
int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{ {
struct qed_igu_info *p_igu_info; struct qed_igu_info *p_igu_info;
u32 val, min_vf = 0, max_vf = 0; struct qed_igu_block *p_block;
u16 sb_id, last_iov_sb_id = 0; u32 min_vf = 0, max_vf = 0;
struct qed_igu_block *blk; u16 igu_sb_id;
u16 prev_sb_id = 0xFF;
p_hwfn->hw_info.p_igu_info = kzalloc(sizeof(*p_igu_info), GFP_KERNEL); p_hwfn->hw_info.p_igu_info = kzalloc(sizeof(*p_igu_info), GFP_KERNEL);
if (!p_hwfn->hw_info.p_igu_info) if (!p_hwfn->hw_info.p_igu_info)
...@@ -1831,9 +1814,12 @@ int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) ...@@ -1831,9 +1814,12 @@ int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
/* Initialize base sb / sb cnt for PFs and VFs */ /* Initialize base sb / sb cnt for PFs and VFs */
p_igu_info->igu_base_sb = 0xffff; p_igu_info->igu_base_sb = 0xffff;
p_igu_info->igu_sb_cnt = 0; p_igu_info->igu_sb_cnt = 0;
p_igu_info->igu_dsb_id = 0xffff;
p_igu_info->igu_base_sb_iov = 0xffff; p_igu_info->igu_base_sb_iov = 0xffff;
/* Distinguish between existent and non-existent default SB */
p_igu_info->igu_dsb_id = QED_SB_INVALID_IDX;
/* Find the range of VF ids whose SB belong to this PF */
if (p_hwfn->cdev->p_iov_info) { if (p_hwfn->cdev->p_iov_info) {
struct qed_hw_sriov_info *p_iov = p_hwfn->cdev->p_iov_info; struct qed_hw_sriov_info *p_iov = p_hwfn->cdev->p_iov_info;
...@@ -1841,113 +1827,72 @@ int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) ...@@ -1841,113 +1827,72 @@ int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
max_vf = p_iov->first_vf_in_pf + p_iov->total_vfs; max_vf = p_iov->first_vf_in_pf + p_iov->total_vfs;
} }
for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev); for (igu_sb_id = 0;
sb_id++) { igu_sb_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev); igu_sb_id++) {
blk = &p_igu_info->igu_map.igu_blocks[sb_id]; /* Read current entry; Notice it might not belong to this PF */
qed_int_igu_read_cam_block(p_hwfn, p_ptt, igu_sb_id);
p_block = &p_igu_info->entry[igu_sb_id];
val = qed_int_igu_read_cam_block(p_hwfn, p_ptt, sb_id); if ((p_block->is_pf) &&
(p_block->function_id == p_hwfn->rel_pf_id)) {
p_block->status = QED_IGU_STATUS_PF |
QED_IGU_STATUS_VALID |
QED_IGU_STATUS_FREE;
/* stop scanning when hit first invalid PF entry */ if (p_igu_info->igu_dsb_id != QED_SB_INVALID_IDX) {
if (!GET_FIELD(val, IGU_MAPPING_LINE_VALID) && if (p_igu_info->igu_base_sb == 0xffff)
GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID)) p_igu_info->igu_base_sb = igu_sb_id;
break; p_igu_info->igu_sb_cnt++;
if (blk->is_pf) {
if (blk->function_id == p_hwfn->rel_pf_id) {
blk->status |= QED_IGU_STATUS_PF;
if (blk->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->cdev,
"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 { } else if (!(p_block->is_pf) &&
if ((blk->function_id >= min_vf) && (p_block->function_id >= min_vf) &&
(blk->function_id < max_vf)) { (p_block->function_id < max_vf)) {
/* Available for VFs of this PF */ /* Available for VFs of this PF */
if (p_igu_info->igu_base_sb_iov == 0xffff) { p_block->status = QED_IGU_STATUS_VALID |
p_igu_info->igu_base_sb_iov = sb_id; QED_IGU_STATUS_FREE;
} else if (last_iov_sb_id != sb_id - 1) {
if (!val) { if (p_igu_info->igu_base_sb_iov == 0xffff)
DP_VERBOSE(p_hwfn->cdev, p_igu_info->igu_base_sb_iov = igu_sb_id;
NETIF_MSG_INTR, p_igu_info->free_blks++;
"First uninitialized IGU CAM entry at index 0x%04x\n",
sb_id);
} else {
DP_NOTICE(p_hwfn->cdev,
"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;
}
blk->status |= QED_IGU_STATUS_FREE;
p_hwfn->hw_info.p_igu_info->free_blks++;
last_iov_sb_id = sb_id;
}
} }
/* Mark the First entry belonging to the PF or its VFs
* as the default SB.
*/
if ((p_block->status & QED_IGU_STATUS_VALID) &&
(p_igu_info->igu_dsb_id == QED_SB_INVALID_IDX)) {
p_igu_info->igu_dsb_id = igu_sb_id;
p_block->status |= QED_IGU_STATUS_DSB;
} }
/* There's a possibility the igu_sb_cnt_iov doesn't properly reflect /* limit number of prints by having each PF print only its
* the number of VF SBs [especially for first VF on engine, as we can't * entries with the exception of PF0 which would print
* differentiate between empty entries and its entries]. * everything.
* 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)) { if ((p_block->status & QED_IGU_STATUS_VALID) ||
u16 total_vfs = p_hwfn->cdev->p_iov_info->total_vfs; (p_hwfn->abs_pf_id == 0)) {
DP_VERBOSE(p_hwfn, NETIF_MSG_INTR,
if (total_vfs < p_igu_info->free_blks) { "IGU_BLOCK: [SB 0x%04x] func_id = %d is_pf = %d vector_num = 0x%x\n",
DP_VERBOSE(p_hwfn, igu_sb_id, p_block->function_id,
(NETIF_MSG_INTR | QED_MSG_IOV), p_block->is_pf, p_block->vector_number);
"Limiting number of SBs for IOV - %04x --> %04x\n",
p_igu_info->free_blks,
p_hwfn->cdev->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,
"IGU has only %04x SBs for VFs while the device has %04x VFs\n",
p_igu_info->free_blks, total_vfs);
return -EINVAL;
} }
} }
p_igu_info->igu_sb_cnt_iov = p_igu_info->free_blks;
DP_VERBOSE(
p_hwfn,
NETIF_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 || if (p_igu_info->igu_dsb_id == QED_SB_INVALID_IDX) {
p_igu_info->igu_dsb_id == 0xffff ||
p_igu_info->igu_sb_cnt == 0) {
DP_NOTICE(p_hwfn, DP_NOTICE(p_hwfn,
"IGU CAM returned invalid values igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", "IGU CAM returned invalid values igu_dsb_id=0x%x\n",
p_igu_info->igu_base_sb,
p_igu_info->igu_sb_cnt,
p_igu_info->igu_dsb_id); p_igu_info->igu_dsb_id);
return -EINVAL; return -EINVAL;
} }
/* All non default SB are considered free at this point */
p_igu_info->igu_sb_cnt_iov = p_igu_info->free_blks;
DP_VERBOSE(p_hwfn, NETIF_MSG_INTR,
"igu_dsb_id=0x%x, num Free SBs - PF: %04x VF: %04x\n",
p_igu_info->igu_dsb_id,
p_igu_info->igu_sb_cnt, p_igu_info->igu_sb_cnt_iov);
return 0; return 0;
} }
......
...@@ -199,23 +199,22 @@ void qed_int_disable_post_isr_release(struct qed_dev *cdev); ...@@ -199,23 +199,22 @@ void qed_int_disable_post_isr_release(struct qed_dev *cdev);
#define SB_ALIGNED_SIZE(p_hwfn) \ #define SB_ALIGNED_SIZE(p_hwfn) \
ALIGNED_TYPE_SIZE(struct status_block, p_hwfn) ALIGNED_TYPE_SIZE(struct status_block, p_hwfn)
#define QED_SB_INVALID_IDX 0xffff
struct qed_igu_block { struct qed_igu_block {
u8 status; u8 status;
#define QED_IGU_STATUS_FREE 0x01 #define QED_IGU_STATUS_FREE 0x01
#define QED_IGU_STATUS_VALID 0x02 #define QED_IGU_STATUS_VALID 0x02
#define QED_IGU_STATUS_PF 0x04 #define QED_IGU_STATUS_PF 0x04
#define QED_IGU_STATUS_DSB 0x08
u8 vector_number; u8 vector_number;
u8 function_id; u8 function_id;
u8 is_pf; u8 is_pf;
}; };
struct qed_igu_map {
struct qed_igu_block igu_blocks[MAX_TOT_SB_PER_PATH];
};
struct qed_igu_info { struct qed_igu_info {
struct qed_igu_map igu_map; struct qed_igu_block entry[MAX_TOT_SB_PER_PATH];
u16 igu_dsb_id; u16 igu_dsb_id;
u16 igu_base_sb; u16 igu_base_sb;
u16 igu_base_sb_iov; u16 igu_base_sb_iov;
......
...@@ -393,7 +393,7 @@ static void qed_iov_clear_vf_igu_blocks(struct qed_hwfn *p_hwfn, ...@@ -393,7 +393,7 @@ static void qed_iov_clear_vf_igu_blocks(struct qed_hwfn *p_hwfn,
for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev); for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev);
sb_id++) { sb_id++) {
p_sb = &p_hwfn->hw_info.p_igu_info->igu_map.igu_blocks[sb_id]; p_sb = &p_hwfn->hw_info.p_igu_info->entry[sb_id];
if ((p_sb->status & QED_IGU_STATUS_FREE) && if ((p_sb->status & QED_IGU_STATUS_FREE) &&
!(p_sb->status & QED_IGU_STATUS_PF)) { !(p_sb->status & QED_IGU_STATUS_PF)) {
val = qed_rd(p_hwfn, p_ptt, val = qed_rd(p_hwfn, p_ptt,
...@@ -872,7 +872,7 @@ static u8 qed_iov_alloc_vf_igu_sbs(struct qed_hwfn *p_hwfn, ...@@ -872,7 +872,7 @@ static u8 qed_iov_alloc_vf_igu_sbs(struct qed_hwfn *p_hwfn,
int qid = 0, igu_id = 0; int qid = 0, igu_id = 0;
u32 val = 0; u32 val = 0;
igu_blocks = p_hwfn->hw_info.p_igu_info->igu_map.igu_blocks; igu_blocks = p_hwfn->hw_info.p_igu_info->entry;
if (num_rx_queues > p_hwfn->hw_info.p_igu_info->free_blks) 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; num_rx_queues = p_hwfn->hw_info.p_igu_info->free_blks;
...@@ -931,8 +931,7 @@ static void qed_iov_free_vf_igu_sbs(struct qed_hwfn *p_hwfn, ...@@ -931,8 +931,7 @@ static void qed_iov_free_vf_igu_sbs(struct qed_hwfn *p_hwfn,
SET_FIELD(val, IGU_MAPPING_LINE_VALID, 0); SET_FIELD(val, IGU_MAPPING_LINE_VALID, 0);
qed_wr(p_hwfn, p_ptt, addr, val); qed_wr(p_hwfn, p_ptt, addr, val);
p_info->igu_map.igu_blocks[igu_id].status |= p_info->entry[igu_id].status |= QED_IGU_STATUS_FREE;
QED_IGU_STATUS_FREE;
p_hwfn->hw_info.p_igu_info->free_blks++; p_hwfn->hw_info.p_igu_info->free_blks++;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment