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

qed: Add bitmaps for VF CIDs

Each PF has a bitmap for its own ranges of CIDs, to allow easy grabbing
of an available CID when such is needed. But VFs are not using the same
mechanism, instead relying on hard-coded CIDs [ queue-index == cid ].

As an infrastructure step toward increasing number of CIDs of VFs,
the PF is going to maintain bitmaps for the VF CIDs as well -
the bitmaps would be per-VF and the ranges would be the same [in HW all
VFs of a given PF have the same mapping of CIDs, and the HW is capable
of distinguishing between those according to the VF index]
Signed-off-by: default avatarYuval Mintz <Yuval.Mintz@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a619cc8b
...@@ -135,7 +135,6 @@ struct qed_tid_seg { ...@@ -135,7 +135,6 @@ struct qed_tid_seg {
struct qed_conn_type_cfg { struct qed_conn_type_cfg {
u32 cid_count; u32 cid_count;
u32 cid_start;
u32 cids_per_vf; u32 cids_per_vf;
struct qed_tid_seg tid_seg[TASK_SEGMENTS]; struct qed_tid_seg tid_seg[TASK_SEGMENTS];
}; };
...@@ -222,6 +221,9 @@ struct qed_cxt_mngr { ...@@ -222,6 +221,9 @@ struct qed_cxt_mngr {
/* Acquired CIDs */ /* Acquired CIDs */
struct qed_cid_acquired_map acquired[MAX_CONN_TYPES]; struct qed_cid_acquired_map acquired[MAX_CONN_TYPES];
struct qed_cid_acquired_map
acquired_vf[MAX_CONN_TYPES][MAX_NUM_VFS];
/* ILT shadow table */ /* ILT shadow table */
struct qed_dma_mem *ilt_shadow; struct qed_dma_mem *ilt_shadow;
u32 pf_start_line; u32 pf_start_line;
...@@ -1121,45 +1123,76 @@ static int qed_ilt_shadow_alloc(struct qed_hwfn *p_hwfn) ...@@ -1121,45 +1123,76 @@ static int qed_ilt_shadow_alloc(struct qed_hwfn *p_hwfn)
static void qed_cid_map_free(struct qed_hwfn *p_hwfn) static void qed_cid_map_free(struct qed_hwfn *p_hwfn)
{ {
struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
u32 type; u32 type, vf;
for (type = 0; type < MAX_CONN_TYPES; type++) { for (type = 0; type < MAX_CONN_TYPES; type++) {
kfree(p_mngr->acquired[type].cid_map); kfree(p_mngr->acquired[type].cid_map);
p_mngr->acquired[type].max_count = 0; p_mngr->acquired[type].max_count = 0;
p_mngr->acquired[type].start_cid = 0; p_mngr->acquired[type].start_cid = 0;
for (vf = 0; vf < MAX_NUM_VFS; vf++) {
kfree(p_mngr->acquired_vf[type][vf].cid_map);
p_mngr->acquired_vf[type][vf].max_count = 0;
p_mngr->acquired_vf[type][vf].start_cid = 0;
}
} }
} }
static int
qed_cid_map_alloc_single(struct qed_hwfn *p_hwfn,
u32 type,
u32 cid_start,
u32 cid_count, struct qed_cid_acquired_map *p_map)
{
u32 size;
if (!cid_count)
return 0;
size = DIV_ROUND_UP(cid_count,
sizeof(unsigned long) * BITS_PER_BYTE) *
sizeof(unsigned long);
p_map->cid_map = kzalloc(size, GFP_KERNEL);
if (!p_map->cid_map)
return -ENOMEM;
p_map->max_count = cid_count;
p_map->start_cid = cid_start;
DP_VERBOSE(p_hwfn, QED_MSG_CXT,
"Type %08x start: %08x count %08x\n",
type, p_map->start_cid, p_map->max_count);
return 0;
}
static int qed_cid_map_alloc(struct qed_hwfn *p_hwfn) static int qed_cid_map_alloc(struct qed_hwfn *p_hwfn)
{ {
struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
u32 start_cid = 0; u32 start_cid = 0, vf_start_cid = 0;
u32 type; u32 type, vf;
for (type = 0; type < MAX_CONN_TYPES; type++) { for (type = 0; type < MAX_CONN_TYPES; type++) {
u32 cid_cnt = p_hwfn->p_cxt_mngr->conn_cfg[type].cid_count; struct qed_conn_type_cfg *p_cfg = &p_mngr->conn_cfg[type];
u32 size; struct qed_cid_acquired_map *p_map;
if (cid_cnt == 0) /* Handle PF maps */
continue; p_map = &p_mngr->acquired[type];
if (qed_cid_map_alloc_single(p_hwfn, type, start_cid,
size = DIV_ROUND_UP(cid_cnt, p_cfg->cid_count, p_map))
sizeof(unsigned long) * BITS_PER_BYTE) *
sizeof(unsigned long);
p_mngr->acquired[type].cid_map = kzalloc(size, GFP_KERNEL);
if (!p_mngr->acquired[type].cid_map)
goto cid_map_fail; goto cid_map_fail;
p_mngr->acquired[type].max_count = cid_cnt; /* Handle VF maps */
p_mngr->acquired[type].start_cid = start_cid; for (vf = 0; vf < MAX_NUM_VFS; vf++) {
p_map = &p_mngr->acquired_vf[type][vf];
p_hwfn->p_cxt_mngr->conn_cfg[type].cid_start = start_cid; if (qed_cid_map_alloc_single(p_hwfn, type,
vf_start_cid,
p_cfg->cids_per_vf, p_map))
goto cid_map_fail;
}
DP_VERBOSE(p_hwfn, QED_MSG_CXT, start_cid += p_cfg->cid_count;
"Type %08x start: %08x count %08x\n", vf_start_cid += p_cfg->cids_per_vf;
type, p_mngr->acquired[type].start_cid,
p_mngr->acquired[type].max_count);
start_cid += cid_cnt;
} }
return 0; return 0;
...@@ -1265,19 +1298,36 @@ void qed_cxt_mngr_free(struct qed_hwfn *p_hwfn) ...@@ -1265,19 +1298,36 @@ void qed_cxt_mngr_free(struct qed_hwfn *p_hwfn)
void qed_cxt_mngr_setup(struct qed_hwfn *p_hwfn) void qed_cxt_mngr_setup(struct qed_hwfn *p_hwfn)
{ {
struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
struct qed_cid_acquired_map *p_map;
struct qed_conn_type_cfg *p_cfg;
int type; int type;
u32 len;
/* Reset acquired cids */ /* Reset acquired cids */
for (type = 0; type < MAX_CONN_TYPES; type++) { for (type = 0; type < MAX_CONN_TYPES; type++) {
u32 cid_cnt = p_hwfn->p_cxt_mngr->conn_cfg[type].cid_count; u32 vf;
p_cfg = &p_mngr->conn_cfg[type];
if (p_cfg->cid_count) {
p_map = &p_mngr->acquired[type];
len = DIV_ROUND_UP(p_map->max_count,
sizeof(unsigned long) *
BITS_PER_BYTE) *
sizeof(unsigned long);
memset(p_map->cid_map, 0, len);
}
if (cid_cnt == 0) if (!p_cfg->cids_per_vf)
continue; continue;
memset(p_mngr->acquired[type].cid_map, 0, for (vf = 0; vf < MAX_NUM_VFS; vf++) {
DIV_ROUND_UP(cid_cnt, p_map = &p_mngr->acquired_vf[type][vf];
sizeof(unsigned long) * BITS_PER_BYTE) * len = DIV_ROUND_UP(p_map->max_count,
sizeof(unsigned long)); sizeof(unsigned long) *
BITS_PER_BYTE) *
sizeof(unsigned long);
memset(p_map->cid_map, 0, len);
}
} }
} }
...@@ -1841,91 +1891,145 @@ void qed_cxt_hw_init_pf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) ...@@ -1841,91 +1891,145 @@ void qed_cxt_hw_init_pf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
qed_prs_init_pf(p_hwfn); qed_prs_init_pf(p_hwfn);
} }
int qed_cxt_acquire_cid(struct qed_hwfn *p_hwfn, int _qed_cxt_acquire_cid(struct qed_hwfn *p_hwfn,
enum protocol_type type, u32 *p_cid) enum protocol_type type, u32 *p_cid, u8 vfid)
{ {
struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
struct qed_cid_acquired_map *p_map;
u32 rel_cid; u32 rel_cid;
if (type >= MAX_CONN_TYPES || !p_mngr->acquired[type].cid_map) { if (type >= MAX_CONN_TYPES) {
DP_NOTICE(p_hwfn, "Invalid protocol type %d", type);
return -EINVAL;
}
if (vfid >= MAX_NUM_VFS && vfid != QED_CXT_PF_CID) {
DP_NOTICE(p_hwfn, "VF [%02x] is out of range\n", vfid);
return -EINVAL;
}
/* Determine the right map to take this CID from */
if (vfid == QED_CXT_PF_CID)
p_map = &p_mngr->acquired[type];
else
p_map = &p_mngr->acquired_vf[type][vfid];
if (!p_map->cid_map) {
DP_NOTICE(p_hwfn, "Invalid protocol type %d", type); DP_NOTICE(p_hwfn, "Invalid protocol type %d", type);
return -EINVAL; return -EINVAL;
} }
rel_cid = find_first_zero_bit(p_mngr->acquired[type].cid_map, rel_cid = find_first_zero_bit(p_map->cid_map, p_map->max_count);
p_mngr->acquired[type].max_count);
if (rel_cid >= p_mngr->acquired[type].max_count) { if (rel_cid >= p_map->max_count) {
DP_NOTICE(p_hwfn, "no CID available for protocol %d\n", type); DP_NOTICE(p_hwfn, "no CID available for protocol %d\n", type);
return -EINVAL; return -EINVAL;
} }
__set_bit(rel_cid, p_mngr->acquired[type].cid_map); __set_bit(rel_cid, p_map->cid_map);
*p_cid = rel_cid + p_map->start_cid;
*p_cid = rel_cid + p_mngr->acquired[type].start_cid; DP_VERBOSE(p_hwfn, QED_MSG_CXT,
"Acquired cid 0x%08x [rel. %08x] vfid %02x type %d\n",
*p_cid, rel_cid, vfid, type);
return 0; return 0;
} }
int qed_cxt_acquire_cid(struct qed_hwfn *p_hwfn,
enum protocol_type type, u32 *p_cid)
{
return _qed_cxt_acquire_cid(p_hwfn, type, p_cid, QED_CXT_PF_CID);
}
static bool qed_cxt_test_cid_acquired(struct qed_hwfn *p_hwfn, static bool qed_cxt_test_cid_acquired(struct qed_hwfn *p_hwfn,
u32 cid, enum protocol_type *p_type) u32 cid,
u8 vfid,
enum protocol_type *p_type,
struct qed_cid_acquired_map **pp_map)
{ {
struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
struct qed_cid_acquired_map *p_map;
enum protocol_type p;
u32 rel_cid; u32 rel_cid;
/* Iterate over protocols and find matching cid range */ /* Iterate over protocols and find matching cid range */
for (p = 0; p < MAX_CONN_TYPES; p++) { for (*p_type = 0; *p_type < MAX_CONN_TYPES; (*p_type)++) {
p_map = &p_mngr->acquired[p]; if (vfid == QED_CXT_PF_CID)
*pp_map = &p_mngr->acquired[*p_type];
else
*pp_map = &p_mngr->acquired_vf[*p_type][vfid];
if (!p_map->cid_map) if (!((*pp_map)->cid_map))
continue; continue;
if (cid >= p_map->start_cid && if (cid >= (*pp_map)->start_cid &&
cid < p_map->start_cid + p_map->max_count) cid < (*pp_map)->start_cid + (*pp_map)->max_count)
break; break;
} }
*p_type = p;
if (p == MAX_CONN_TYPES) { if (*p_type == MAX_CONN_TYPES) {
DP_NOTICE(p_hwfn, "Invalid CID %d", cid); DP_NOTICE(p_hwfn, "Invalid CID %d vfid %02x", cid, vfid);
return false; goto fail;
} }
rel_cid = cid - p_map->start_cid; rel_cid = cid - (*pp_map)->start_cid;
if (!test_bit(rel_cid, p_map->cid_map)) { if (!test_bit(rel_cid, (*pp_map)->cid_map)) {
DP_NOTICE(p_hwfn, "CID %d not acquired", cid); DP_NOTICE(p_hwfn, "CID %d [vifd %02x] not acquired",
return false; cid, vfid);
goto fail;
} }
return true; return true;
fail:
*p_type = MAX_CONN_TYPES;
*pp_map = NULL;
return false;
} }
void qed_cxt_release_cid(struct qed_hwfn *p_hwfn, u32 cid) void _qed_cxt_release_cid(struct qed_hwfn *p_hwfn, u32 cid, u8 vfid)
{ {
struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; struct qed_cid_acquired_map *p_map = NULL;
enum protocol_type type; enum protocol_type type;
bool b_acquired; bool b_acquired;
u32 rel_cid; u32 rel_cid;
if (vfid != QED_CXT_PF_CID && vfid > MAX_NUM_VFS) {
DP_NOTICE(p_hwfn,
"Trying to return incorrect CID belonging to VF %02x\n",
vfid);
return;
}
/* Test acquired and find matching per-protocol map */ /* Test acquired and find matching per-protocol map */
b_acquired = qed_cxt_test_cid_acquired(p_hwfn, cid, &type); b_acquired = qed_cxt_test_cid_acquired(p_hwfn, cid, vfid,
&type, &p_map);
if (!b_acquired) if (!b_acquired)
return; return;
rel_cid = cid - p_mngr->acquired[type].start_cid; rel_cid = cid - p_map->start_cid;
__clear_bit(rel_cid, p_mngr->acquired[type].cid_map); clear_bit(rel_cid, p_map->cid_map);
DP_VERBOSE(p_hwfn, QED_MSG_CXT,
"Released CID 0x%08x [rel. %08x] vfid %02x type %d\n",
cid, rel_cid, vfid, type);
}
void qed_cxt_release_cid(struct qed_hwfn *p_hwfn, u32 cid)
{
_qed_cxt_release_cid(p_hwfn, cid, QED_CXT_PF_CID);
} }
int qed_cxt_get_cid_info(struct qed_hwfn *p_hwfn, struct qed_cxt_info *p_info) int qed_cxt_get_cid_info(struct qed_hwfn *p_hwfn, struct qed_cxt_info *p_info)
{ {
struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
struct qed_cid_acquired_map *p_map = NULL;
u32 conn_cxt_size, hw_p_size, cxts_per_p, line; u32 conn_cxt_size, hw_p_size, cxts_per_p, line;
enum protocol_type type; enum protocol_type type;
bool b_acquired; bool b_acquired;
/* Test acquired and find matching per-protocol map */ /* Test acquired and find matching per-protocol map */
b_acquired = qed_cxt_test_cid_acquired(p_hwfn, p_info->iid, &type); b_acquired = qed_cxt_test_cid_acquired(p_hwfn, p_info->iid,
QED_CXT_PF_CID, &type, &p_map);
if (!b_acquired) if (!b_acquired)
return -EINVAL; return -EINVAL;
......
...@@ -53,19 +53,6 @@ struct qed_tid_mem { ...@@ -53,19 +53,6 @@ struct qed_tid_mem {
u8 *blocks[MAX_TID_BLOCKS]; /* 4K */ u8 *blocks[MAX_TID_BLOCKS]; /* 4K */
}; };
/**
* @brief qed_cxt_acquire - Acquire a new cid of a specific protocol type
*
* @param p_hwfn
* @param type
* @param p_cid
*
* @return int
*/
int qed_cxt_acquire_cid(struct qed_hwfn *p_hwfn,
enum protocol_type type,
u32 *p_cid);
/** /**
* @brief qedo_cid_get_cxt_info - Returns the context info for a specific cid * @brief qedo_cid_get_cxt_info - Returns the context info for a specific cid
* *
...@@ -195,14 +182,51 @@ void qed_qm_init_pf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); ...@@ -195,14 +182,51 @@ void qed_qm_init_pf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
*/ */
int qed_qm_reconf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); int qed_qm_reconf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
#define QED_CXT_PF_CID (0xff)
/** /**
* @brief qed_cxt_release - Release a cid * @brief qed_cxt_release - Release a cid
* *
* @param p_hwfn * @param p_hwfn
* @param cid * @param cid
*/ */
void qed_cxt_release_cid(struct qed_hwfn *p_hwfn, void qed_cxt_release_cid(struct qed_hwfn *p_hwfn, u32 cid);
u32 cid);
/**
* @brief qed_cxt_release - Release a cid belonging to a vf-queue
*
* @param p_hwfn
* @param cid
* @param vfid - engine relative index. QED_CXT_PF_CID if belongs to PF
*/
void _qed_cxt_release_cid(struct qed_hwfn *p_hwfn, u32 cid, u8 vfid);
/**
* @brief qed_cxt_acquire - Acquire a new cid of a specific protocol type
*
* @param p_hwfn
* @param type
* @param p_cid
*
* @return int
*/
int qed_cxt_acquire_cid(struct qed_hwfn *p_hwfn,
enum protocol_type type, u32 *p_cid);
/**
* @brief _qed_cxt_acquire - Acquire a new cid of a specific protocol type
* for a vf-queue
*
* @param p_hwfn
* @param type
* @param p_cid
* @param vfid - engine relative index. QED_CXT_PF_CID if belongs to PF
*
* @return int
*/
int _qed_cxt_acquire_cid(struct qed_hwfn *p_hwfn,
enum protocol_type type, u32 *p_cid, u8 vfid);
int qed_cxt_dynamic_ilt_alloc(struct qed_hwfn *p_hwfn, int qed_cxt_dynamic_ilt_alloc(struct qed_hwfn *p_hwfn,
enum qed_cxt_elem_type elem_type, u32 iid); enum qed_cxt_elem_type elem_type, u32 iid);
u32 qed_cxt_get_proto_tid_count(struct qed_hwfn *p_hwfn, u32 qed_cxt_get_proto_tid_count(struct qed_hwfn *p_hwfn,
......
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