net/bnx2x: fix reading VF id

The logic to read vf_id used by ACQUIRE/TEARDOWN_Q/RELEASE TLVs,
multiplexed return value to convey vf_id value and status of read vf_id
API. This lets to segfault at dev_start() as resources are not properly
cleaned and re-allocated.

Fix read vf_id API to differentiate between vf_id value and return
status. Adjust the status checking accordingly.
Added bnx2x_vf_teardown_queue() API and moved relevant code from
bnx2x_vf_unload() to new API.

Fixes: 540a211084 ("bnx2x: driver core")
Cc: stable@dpdk.org

Signed-off-by: Rasesh Mody <rmody@marvell.com>
This commit is contained in:
Rasesh Mody 2019-07-03 16:43:11 -07:00 committed by Ferruh Yigit
parent 6bee9d5f45
commit e0c103a79c
3 changed files with 91 additions and 60 deletions

View File

@ -2015,6 +2015,8 @@ bnx2x_nic_unload(struct bnx2x_softc *sc, uint32_t unload_mode, uint8_t keep_link
uint8_t global = FALSE;
uint32_t val;
PMD_INIT_FUNC_TRACE(sc);
PMD_DRV_LOG(DEBUG, sc, "Starting NIC unload...");
/* mark driver as unloaded in shmem2 */

View File

@ -162,20 +162,26 @@ static inline uint16_t bnx2x_check_me_flags(uint32_t val)
#define BNX2X_ME_ANSWER_DELAY 100
#define BNX2X_ME_ANSWER_TRIES 10
static inline int bnx2x_read_vf_id(struct bnx2x_softc *sc)
static inline int bnx2x_read_vf_id(struct bnx2x_softc *sc, uint32_t *vf_id)
{
uint32_t val;
uint8_t i = 0;
while (i <= BNX2X_ME_ANSWER_TRIES) {
val = BNX2X_DB_READ(DOORBELL_ADDR(sc, 0));
if (bnx2x_check_me_flags(val))
return VF_ID(val);
if (bnx2x_check_me_flags(val)) {
PMD_DRV_LOG(DEBUG, sc,
"valid register value: 0x%08x", val);
*vf_id = VF_ID(val);
return 0;
}
DELAY_MS(BNX2X_ME_ANSWER_DELAY);
i++;
}
PMD_DRV_LOG(ERR, sc, "Invalid register value: 0x%08x", val);
return -EINVAL;
}
@ -240,14 +246,13 @@ int bnx2x_loop_obtain_resources(struct bnx2x_softc *sc)
int bnx2x_vf_get_resources(struct bnx2x_softc *sc, uint8_t tx_count, uint8_t rx_count)
{
struct vf_acquire_tlv *acq = &sc->vf2pf_mbox->query[0].acquire;
int vf_id;
uint32_t vf_id;
int rc;
bnx2x_vf_close(sc);
bnx2x_vf_prep(sc, &acq->first_tlv, BNX2X_VF_TLV_ACQUIRE, sizeof(*acq));
vf_id = bnx2x_read_vf_id(sc);
if (vf_id < 0) {
if (bnx2x_read_vf_id(sc, &vf_id)) {
rc = -EAGAIN;
goto out;
}
@ -318,25 +323,30 @@ bnx2x_vf_close(struct bnx2x_softc *sc)
{
struct vf_release_tlv *query;
struct vf_common_reply_tlv *reply = &sc->vf2pf_mbox->resp.common_reply;
int vf_id = bnx2x_read_vf_id(sc);
uint32_t vf_id;
int rc;
if (vf_id >= 0) {
query = &sc->vf2pf_mbox->query[0].release;
bnx2x_vf_prep(sc, &query->first_tlv, BNX2X_VF_TLV_RELEASE,
sizeof(*query));
query = &sc->vf2pf_mbox->query[0].release;
bnx2x_vf_prep(sc, &query->first_tlv, BNX2X_VF_TLV_RELEASE,
sizeof(*query));
query->vf_id = vf_id;
bnx2x_add_tlv(sc, query, query->first_tlv.tl.length,
BNX2X_VF_TLV_LIST_END,
sizeof(struct channel_list_end_tlv));
rc = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr);
if (rc || reply->status != BNX2X_VF_STATUS_SUCCESS)
PMD_DRV_LOG(ERR, sc, "Failed to release VF");
bnx2x_vf_finalize(sc, &query->first_tlv);
if (bnx2x_read_vf_id(sc, &vf_id)) {
rc = -EAGAIN;
goto out;
}
query->vf_id = vf_id;
bnx2x_add_tlv(sc, query, query->first_tlv.tl.length,
BNX2X_VF_TLV_LIST_END,
sizeof(struct channel_list_end_tlv));
rc = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr);
if (rc || reply->status != BNX2X_VF_STATUS_SUCCESS)
PMD_DRV_LOG(ERR, sc, "Failed to release VF");
out:
bnx2x_vf_finalize(sc, &query->first_tlv);
}
/* Let PF know the VF status blocks phys_addrs */
@ -347,6 +357,8 @@ bnx2x_vf_init(struct bnx2x_softc *sc)
struct vf_common_reply_tlv *reply = &sc->vf2pf_mbox->resp.common_reply;
int i, rc;
PMD_INIT_FUNC_TRACE(sc);
query = &sc->vf2pf_mbox->query[0].init;
bnx2x_vf_prep(sc, &query->first_tlv, BNX2X_VF_TLV_INIT,
sizeof(*query));
@ -383,51 +395,38 @@ bnx2x_vf_unload(struct bnx2x_softc *sc)
{
struct vf_close_tlv *query;
struct vf_common_reply_tlv *reply = &sc->vf2pf_mbox->resp.common_reply;
struct vf_q_op_tlv *query_op;
int i, vf_id, rc;
uint32_t vf_id;
int i, rc;
vf_id = bnx2x_read_vf_id(sc);
if (vf_id > 0) {
FOR_EACH_QUEUE(sc, i) {
query_op = &sc->vf2pf_mbox->query[0].q_op;
bnx2x_vf_prep(sc, &query_op->first_tlv,
BNX2X_VF_TLV_TEARDOWN_Q,
sizeof(*query_op));
PMD_INIT_FUNC_TRACE(sc);
query_op->vf_qid = i;
FOR_EACH_QUEUE(sc, i)
bnx2x_vf_teardown_queue(sc, i);
bnx2x_add_tlv(sc, query_op,
query_op->first_tlv.tl.length,
BNX2X_VF_TLV_LIST_END,
sizeof(struct channel_list_end_tlv));
bnx2x_vf_set_mac(sc, false);
rc = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr);
if (rc || reply->status != BNX2X_VF_STATUS_SUCCESS)
PMD_DRV_LOG(ERR, sc,
"Bad reply for vf_q %d teardown", i);
query = &sc->vf2pf_mbox->query[0].close;
bnx2x_vf_prep(sc, &query->first_tlv, BNX2X_VF_TLV_CLOSE,
sizeof(*query));
bnx2x_vf_finalize(sc, &query_op->first_tlv);
}
bnx2x_vf_set_mac(sc, false);
query = &sc->vf2pf_mbox->query[0].close;
bnx2x_vf_prep(sc, &query->first_tlv, BNX2X_VF_TLV_CLOSE,
sizeof(*query));
query->vf_id = vf_id;
bnx2x_add_tlv(sc, query, query->first_tlv.tl.length,
BNX2X_VF_TLV_LIST_END,
sizeof(struct channel_list_end_tlv));
rc = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr);
if (rc || reply->status != BNX2X_VF_STATUS_SUCCESS)
PMD_DRV_LOG(ERR, sc,
"Bad reply from PF for close message");
bnx2x_vf_finalize(sc, &query->first_tlv);
if (bnx2x_read_vf_id(sc, &vf_id)) {
rc = -EAGAIN;
goto out;
}
query->vf_id = vf_id;
bnx2x_add_tlv(sc, query, query->first_tlv.tl.length,
BNX2X_VF_TLV_LIST_END,
sizeof(struct channel_list_end_tlv));
rc = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr);
if (rc || reply->status != BNX2X_VF_STATUS_SUCCESS)
PMD_DRV_LOG(ERR, sc,
"Bad reply from PF for close message");
out:
bnx2x_vf_finalize(sc, &query->first_tlv);
}
static inline uint16_t
@ -521,6 +520,35 @@ bnx2x_vf_setup_queue(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, int lead
return rc;
}
int
bnx2x_vf_teardown_queue(struct bnx2x_softc *sc, int qid)
{
struct vf_q_op_tlv *query_op;
struct vf_common_reply_tlv *reply = &sc->vf2pf_mbox->resp.common_reply;
int rc;
query_op = &sc->vf2pf_mbox->query[0].q_op;
bnx2x_vf_prep(sc, &query_op->first_tlv,
BNX2X_VF_TLV_TEARDOWN_Q,
sizeof(*query_op));
query_op->vf_qid = qid;
bnx2x_add_tlv(sc, query_op,
query_op->first_tlv.tl.length,
BNX2X_VF_TLV_LIST_END,
sizeof(struct channel_list_end_tlv));
rc = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr);
if (rc || reply->status != BNX2X_VF_STATUS_SUCCESS)
PMD_DRV_LOG(ERR, sc,
"Bad reply for vf_q %d teardown", qid);
bnx2x_vf_finalize(sc, &query_op->first_tlv);
return rc;
}
int
bnx2x_vf_set_mac(struct bnx2x_softc *sc, int set)
{

View File

@ -328,6 +328,7 @@ struct bnx2x_vf_mbx_msg {
union resp_tlvs resp;
};
int bnx2x_vf_teardown_queue(struct bnx2x_softc *sc, int qid);
int bnx2x_vf_set_mac(struct bnx2x_softc *sc, int set);
int bnx2x_vf_config_rss(struct bnx2x_softc *sc, struct ecore_config_rss_params *params);