From e0c103a79c0e9d72cf78e3643a85b6869599f79d Mon Sep 17 00:00:00 2001 From: Rasesh Mody Date: Wed, 3 Jul 2019 16:43:11 -0700 Subject: [PATCH] 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: 540a211084a7 ("bnx2x: driver core") Cc: stable@dpdk.org Signed-off-by: Rasesh Mody --- drivers/net/bnx2x/bnx2x.c | 2 + drivers/net/bnx2x/bnx2x_vfpf.c | 140 ++++++++++++++++++++------------- drivers/net/bnx2x/bnx2x_vfpf.h | 1 + 3 files changed, 87 insertions(+), 56 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x.c b/drivers/net/bnx2x/bnx2x.c index d523f4f2ce..877f5b73df 100644 --- a/drivers/net/bnx2x/bnx2x.c +++ b/drivers/net/bnx2x/bnx2x.c @@ -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 */ diff --git a/drivers/net/bnx2x/bnx2x_vfpf.c b/drivers/net/bnx2x/bnx2x_vfpf.c index 7cf738a829..8f7559c675 100644 --- a/drivers/net/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/bnx2x/bnx2x_vfpf.c @@ -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)); + if (bnx2x_read_vf_id(sc, &vf_id)) { + rc = -EAGAIN; + goto out; + } - 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"); + query->vf_id = vf_id; - bnx2x_vf_finalize(sc, &query->first_tlv); - } + 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; - - 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)); - - query_op->vf_qid = i; + uint32_t vf_id; + int i, rc; - bnx2x_add_tlv(sc, query_op, - query_op->first_tlv.tl.length, - BNX2X_VF_TLV_LIST_END, - sizeof(struct channel_list_end_tlv)); + PMD_INIT_FUNC_TRACE(sc); - 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); + FOR_EACH_QUEUE(sc, i) + bnx2x_vf_teardown_queue(sc, i); - bnx2x_vf_finalize(sc, &query_op->first_tlv); - } + bnx2x_vf_set_mac(sc, false); - 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 = &sc->vf2pf_mbox->query[0].close; - bnx2x_vf_prep(sc, &query->first_tlv, BNX2X_VF_TLV_CLOSE, - sizeof(*query)); + if (bnx2x_read_vf_id(sc, &vf_id)) { + rc = -EAGAIN; + goto out; + } - query->vf_id = vf_id; + 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)); + 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"); + 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); - } +out: + bnx2x_vf_finalize(sc, &query->first_tlv); } static inline uint16_t @@ -521,6 +520,35 @@ out: 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) { diff --git a/drivers/net/bnx2x/bnx2x_vfpf.h b/drivers/net/bnx2x/bnx2x_vfpf.h index 6964c9d989..ce0259adf1 100644 --- a/drivers/net/bnx2x/bnx2x_vfpf.h +++ b/drivers/net/bnx2x/bnx2x_vfpf.h @@ -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); -- 2.20.1