Fix VF representor port add when it's endpoint interface is down.
While adding vf representor port to a bridge, vnic & svif information of
vf representors endpoint(VF) would be needed to program default flow
rules.
However, if the endpoint interface is down when vf representor port is
added, firmware will return invalid vnic & svif information.
This patch fixes the problem by registering to DEFAULT_VNIC_CHANGE
async event and once the async event is received, use the endpoint
information(VF's fid) to fetch it's vnic & svif information and
program the default flow rules.
Fixes: 322bd6e70272 ("net/bnxt: add port representor infrastructure")
Cc: stable@dpdk.org
Signed-off-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>
Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
#define BNXT_CMPL_AGGR_DMA_TMR_DURING_INT 50
#define BNXT_NUM_CMPL_DMA_AGGR_DURING_INT 12
+#define BNXT_DEFAULT_VNIC_STATE_MASK \
+ HWRM_ASYNC_EVENT_CMPL_DEFAULT_VNIC_CHANGE_EVENT_DATA1_DEF_VNIC_STATE_MASK
+#define BNXT_DEFAULT_VNIC_STATE_SFT \
+ HWRM_ASYNC_EVENT_CMPL_DEFAULT_VNIC_CHANGE_EVENT_DATA1_DEF_VNIC_STATE_SFT
+#define BNXT_DEFAULT_VNIC_ALLOC \
+ HWRM_ASYNC_EVENT_CMPL_DEFAULT_VNIC_CHANGE_EVENT_DATA1_DEF_VNIC_STATE_DEF_VNIC_ALLOC
+#define BNXT_DEFAULT_VNIC_FREE \
+ HWRM_ASYNC_EVENT_CMPL_DEFAULT_VNIC_CHANGE_EVENT_DATA1_DEF_VNIC_STATE_DEF_VNIC_FREE
+#define BNXT_DEFAULT_VNIC_CHANGE_PF_ID_MASK \
+ HWRM_ASYNC_EVENT_CMPL_DEFAULT_VNIC_CHANGE_EVENT_DATA1_PF_ID_MASK
+#define BNXT_DEFAULT_VNIC_CHANGE_PF_ID_SFT \
+ HWRM_ASYNC_EVENT_CMPL_DEFAULT_VNIC_CHANGE_EVENT_DATA1_PF_ID_SFT
+#define BNXT_DEFAULT_VNIC_CHANGE_VF_ID_MASK \
+ HWRM_ASYNC_EVENT_CMPL_DEFAULT_VNIC_CHANGE_EVENT_DATA1_VF_ID_MASK
+#define BNXT_DEFAULT_VNIC_CHANGE_VF_ID_SFT \
+ HWRM_ASYNC_EVENT_CMPL_DEFAULT_VNIC_CHANGE_EVENT_DATA1_VF_ID_SFT
+
struct bnxt_led_info {
uint8_t num_leds;
uint8_t led_id;
struct bnxt_rep_info {
struct rte_eth_dev *vfr_eth_dev;
pthread_mutex_t vfr_lock;
+ pthread_mutex_t vfr_start_lock;
+ bool conduit_valid;
};
/* address space location of register */
uint16_t switch_domain_id;
uint16_t vf_id;
uint16_t fw_fid;
+#define BNXT_DFLT_VNIC_ID_INVALID 0xFFFF
uint16_t dflt_vnic_id;
uint16_t svif;
uint16_t vfr_tx_cfa_action;
uint16_t bnxt_get_vport(uint16_t port);
enum bnxt_ulp_intf_type
bnxt_get_interface_type(uint16_t port);
+int bnxt_vf_rep_dev_start_op(struct rte_eth_dev *eth_dev);
void bnxt_cancel_fc_thread(struct bnxt *bp);
void bnxt_flow_cnt_alarm_cb(void *arg);
} while (timeout);
}
+static void
+bnxt_process_default_vnic_change(struct bnxt *bp,
+ struct hwrm_async_event_cmpl *async_cmp)
+{
+ uint16_t fid, vnic_state, parent_id, vf_fid, vf_id;
+ struct bnxt_vf_representor *vf_rep_bp;
+ struct rte_eth_dev *eth_dev;
+ bool vfr_found = false;
+ uint32_t event_data;
+
+ if (!BNXT_TRUFLOW_EN(bp))
+ return;
+
+ PMD_DRV_LOG(INFO, "Default vnic change async event received\n");
+ event_data = rte_le_to_cpu_32(async_cmp->event_data1);
+
+ vnic_state = (event_data & BNXT_DEFAULT_VNIC_STATE_MASK) >>
+ BNXT_DEFAULT_VNIC_STATE_SFT;
+ if (vnic_state != BNXT_DEFAULT_VNIC_ALLOC)
+ return;
+
+ parent_id = (event_data & BNXT_DEFAULT_VNIC_CHANGE_PF_ID_MASK) >>
+ BNXT_DEFAULT_VNIC_CHANGE_PF_ID_SFT;
+ fid = BNXT_PF(bp) ? bp->fw_fid : bp->parent->fid;
+ if (parent_id != fid || !bp->rep_info)
+ return;
+
+ vf_fid = (event_data & BNXT_DEFAULT_VNIC_CHANGE_VF_ID_MASK) >>
+ BNXT_DEFAULT_VNIC_CHANGE_VF_ID_SFT;
+ PMD_DRV_LOG(INFO, "async event received vf_id 0x%x\n", vf_fid);
+
+ for (vf_id = 0; vf_id < BNXT_MAX_VF_REPS; vf_id++) {
+ eth_dev = bp->rep_info[vf_id].vfr_eth_dev;
+ if (!eth_dev)
+ continue;
+ vf_rep_bp = eth_dev->data->dev_private;
+ if (vf_rep_bp &&
+ vf_rep_bp->fw_fid == vf_fid) {
+ vfr_found = true;
+ break;
+ }
+ }
+ if (!vfr_found)
+ return;
+
+ bnxt_vf_rep_dev_start_op(eth_dev);
+}
+
/*
* Async event handling
*/
rte_le_to_cpu_32(async_cmp->event_data1),
rte_le_to_cpu_32(async_cmp->event_data2));
break;
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DEFAULT_VNIC_CHANGE:
+ bnxt_process_default_vnic_change(bp, async_cmp);
+ break;
default:
PMD_DRV_LOG(DEBUG, "handle_async_event id = 0x%x\n", event_id);
break;
{
pthread_mutex_destroy(&bp->flow_lock);
pthread_mutex_destroy(&bp->def_cp_lock);
- if (bp->rep_info)
+ if (bp->rep_info) {
pthread_mutex_destroy(&bp->rep_info->vfr_lock);
+ pthread_mutex_destroy(&bp->rep_info->vfr_start_lock);
+ }
}
static int
bnxt_free_rep_info(bp);
return rc;
}
+
+ rc = pthread_mutex_init(&bp->rep_info->vfr_start_lock, NULL);
+ if (rc) {
+ PMD_DRV_LOG(ERR, "Unable to initialize vfr_start_lock\n");
+ bnxt_free_rep_info(bp);
+ return rc;
+ }
+
return rc;
}
req.async_event_fwd[1] |=
rte_cpu_to_le_32(ASYNC_CMPL_EVENT_ID_DBG_NOTIFICATION);
+ if (BNXT_VF_IS_TRUSTED(bp))
+ req.async_event_fwd[1] |=
+ rte_cpu_to_le_32(ASYNC_CMPL_EVENT_ID_DEFAULT_VNIC_CHANGE);
+
rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
HWRM_CHECK_RESULT();
(1 << (HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE - 32))
#define ASYNC_CMPL_EVENT_ID_DBG_NOTIFICATION \
(1 << (HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DEBUG_NOTIFICATION - 32))
+#define ASYNC_CMPL_EVENT_ID_DEFAULT_VNIC_CHANGE \
+ (1 << (HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DEFAULT_VNIC_CHANGE - 32))
#define HWRM_QUEUE_SERVICE_PROFILE_LOSSY \
HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSY
return rc;
}
+static int
+bnxt_get_dflt_vnic_svif(struct bnxt *bp, struct bnxt_vf_representor *vf_rep_bp)
+{
+ struct bnxt_rep_info *rep_info;
+ int rc;
+
+ rc = bnxt_hwrm_get_dflt_vnic_svif(bp, vf_rep_bp->fw_fid,
+ &vf_rep_bp->dflt_vnic_id,
+ &vf_rep_bp->svif);
+ if (rc) {
+ PMD_DRV_LOG(ERR, "Failed to get default vnic id of VF\n");
+ vf_rep_bp->dflt_vnic_id = BNXT_DFLT_VNIC_ID_INVALID;
+ vf_rep_bp->svif = BNXT_SVIF_INVALID;
+ } else {
+ PMD_DRV_LOG(INFO, "vf_rep->dflt_vnic_id = %d\n",
+ vf_rep_bp->dflt_vnic_id);
+ }
+ if (vf_rep_bp->dflt_vnic_id != BNXT_DFLT_VNIC_ID_INVALID &&
+ vf_rep_bp->svif != BNXT_SVIF_INVALID) {
+ rep_info = &bp->rep_info[vf_rep_bp->vf_id];
+ rep_info->conduit_valid = true;
+ }
+
+ return rc;
+}
+
int bnxt_vf_representor_init(struct rte_eth_dev *eth_dev, void *params)
{
struct bnxt_vf_representor *vf_rep_bp = eth_dev->data->dev_private;
(struct bnxt_vf_representor *)params;
struct rte_eth_link *link;
struct bnxt *parent_bp;
- int rc = 0;
vf_rep_bp->vf_id = rep_params->vf_id;
vf_rep_bp->switch_domain_id = rep_params->switch_domain_id;
eth_dev->data->dev_link.link_status = link->link_status;
eth_dev->data->dev_link.link_autoneg = link->link_autoneg;
- vf_rep_bp->fw_fid = rep_params->vf_id + parent_bp->first_vf_id;
- PMD_DRV_LOG(INFO, "vf_rep->fw_fid = %d\n", vf_rep_bp->fw_fid);
- rc = bnxt_hwrm_get_dflt_vnic_svif(parent_bp, vf_rep_bp->fw_fid,
- &vf_rep_bp->dflt_vnic_id,
- &vf_rep_bp->svif);
- if (rc)
- PMD_DRV_LOG(ERR, "Failed to get default vnic id of VF\n");
- else
- PMD_DRV_LOG(INFO, "vf_rep->dflt_vnic_id = %d\n",
- vf_rep_bp->dflt_vnic_id);
-
PMD_DRV_LOG(INFO, "calling bnxt_print_link_info\n");
bnxt_print_link_info(eth_dev);
"Switch domain id %d: Representor Device %d init done\n",
vf_rep_bp->switch_domain_id, vf_rep_bp->vf_id);
+ vf_rep_bp->fw_fid = rep_params->vf_id + parent_bp->first_vf_id;
+ PMD_DRV_LOG(INFO, "vf_rep->fw_fid = %d\n", vf_rep_bp->fw_fid);
+
return 0;
}
int bnxt_vf_rep_dev_start_op(struct rte_eth_dev *eth_dev)
{
struct bnxt_vf_representor *rep_bp = eth_dev->data->dev_private;
+ struct bnxt_rep_info *rep_info;
+ struct bnxt *parent_bp;
int rc;
- rc = bnxt_vfr_alloc(eth_dev);
+ parent_bp = rep_bp->parent_dev->data->dev_private;
+ rep_info = &parent_bp->rep_info[rep_bp->vf_id];
- if (!rc) {
- eth_dev->rx_pkt_burst = &bnxt_vf_rep_rx_burst;
- eth_dev->tx_pkt_burst = &bnxt_vf_rep_tx_burst;
+ pthread_mutex_lock(&rep_info->vfr_start_lock);
+ if (rep_info->conduit_valid) {
+ pthread_mutex_unlock(&rep_info->vfr_start_lock);
+ return 0;
+ }
+ rc = bnxt_get_dflt_vnic_svif(parent_bp, rep_bp);
+ if (rc || !rep_info->conduit_valid) {
+ pthread_mutex_unlock(&rep_info->vfr_start_lock);
+ return rc;
+ }
+ pthread_mutex_unlock(&rep_info->vfr_start_lock);
- bnxt_vf_rep_link_update_op(eth_dev, 1);
- } else {
+ rc = bnxt_vfr_alloc(eth_dev);
+ if (rc) {
eth_dev->data->dev_link.link_status = 0;
bnxt_vf_rep_free_rx_mbufs(rep_bp);
+ return rc;
}
+ eth_dev->rx_pkt_burst = &bnxt_vf_rep_rx_burst;
+ eth_dev->tx_pkt_burst = &bnxt_vf_rep_tx_burst;
+ bnxt_vf_rep_link_update_op(eth_dev, 1);
- return rc;
+ return 0;
}
static int bnxt_tf_vfr_free(struct bnxt_vf_representor *vfr)