net: use named constants for deprecated QinQ TPIDs
[dpdk.git] / drivers / net / bnxt / bnxt_ethdev.c
index 3154b94..66ac04b 100644 (file)
@@ -28,6 +28,8 @@
 #include "bnxt_vnic.h"
 #include "hsi_struct_def_dpdk.h"
 #include "bnxt_nvm_defs.h"
+#include "bnxt_tf_common.h"
+#include "ulp_flow_db.h"
 
 #define DRV_MODULE_NAME                "bnxt"
 static const char bnxt_version[] =
@@ -96,7 +98,10 @@ static const struct rte_pci_id bnxt_pci_id_map[] = {
 #define BNXT_DEVARG_TRUFLOW    "host-based-truflow"
 #define BNXT_DEVARG_FLOW_XSTAT "flow-xstat"
 #define BNXT_DEVARG_MAX_NUM_KFLOWS  "max-num-kflows"
+#define BNXT_DEVARG_REPRESENTOR        "representor"
+
 static const char *const bnxt_dev_args[] = {
+       BNXT_DEVARG_REPRESENTOR,
        BNXT_DEVARG_TRUFLOW,
        BNXT_DEVARG_FLOW_XSTAT,
        BNXT_DEVARG_MAX_NUM_KFLOWS,
@@ -136,6 +141,7 @@ static void bnxt_cancel_fw_health_check(struct bnxt *bp);
 static int bnxt_restore_vlan_filters(struct bnxt *bp);
 static void bnxt_dev_recover(void *arg);
 static void bnxt_free_error_recovery_info(struct bnxt *bp);
+static void bnxt_free_rep_info(struct bnxt *bp);
 
 int is_bnxt_in_error(struct bnxt *bp)
 {
@@ -171,6 +177,11 @@ uint16_t bnxt_rss_hash_tbl_size(const struct bnxt *bp)
        return bnxt_rss_ctxts(bp) * BNXT_RSS_ENTRIES_PER_CTX_THOR;
 }
 
+static void bnxt_free_parent_info(struct bnxt *bp)
+{
+       rte_free(bp->parent);
+}
+
 static void bnxt_free_pf_info(struct bnxt *bp)
 {
        rte_free(bp->pf);
@@ -221,6 +232,16 @@ static void bnxt_free_mem(struct bnxt *bp, bool reconfig)
        bp->grp_info = NULL;
 }
 
+static int bnxt_alloc_parent_info(struct bnxt *bp)
+{
+       bp->parent = rte_zmalloc("bnxt_parent_info",
+                                sizeof(struct bnxt_parent_info), 0);
+       if (bp->parent == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+
 static int bnxt_alloc_pf_info(struct bnxt *bp)
 {
        bp->pf = rte_zmalloc("bnxt_pf_info", sizeof(struct bnxt_pf_info), 0);
@@ -1055,7 +1076,7 @@ bnxt_receive_function(struct rte_eth_dev *eth_dev)
 {
        struct bnxt *bp = eth_dev->data->dev_private;
 
-#ifdef RTE_ARCH_X86
+#if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM64)
 #ifndef RTE_LIBRTE_IEEE1588
        /*
         * Vector mode receive can be enabled only if scatter rx is not
@@ -1095,14 +1116,17 @@ bnxt_receive_function(struct rte_eth_dev *eth_dev)
 static eth_tx_burst_t
 bnxt_transmit_function(__rte_unused struct rte_eth_dev *eth_dev)
 {
-#ifdef RTE_ARCH_X86
+#if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM64)
 #ifndef RTE_LIBRTE_IEEE1588
+       struct bnxt *bp = eth_dev->data->dev_private;
+
        /*
         * Vector mode transmit can be enabled only if not using scatter rx
         * or tx offloads.
         */
        if (!eth_dev->data->scattered_rx &&
-           !eth_dev->data->dev_conf.txmode.offloads) {
+           !eth_dev->data->dev_conf.txmode.offloads &&
+           !BNXT_TRUFLOW_EN(bp)) {
                PMD_DRV_LOG(INFO, "Using vector mode transmit for port %d\n",
                            eth_dev->data->port_id);
                return bnxt_xmit_pkts_vec;
@@ -1138,6 +1162,73 @@ static int bnxt_handle_if_change_status(struct bnxt *bp)
        return rc;
 }
 
+static int32_t
+bnxt_create_port_app_df_rule(struct bnxt *bp, uint8_t flow_type,
+                            uint32_t *flow_id)
+{
+       uint16_t port_id = bp->eth_dev->data->port_id;
+       struct ulp_tlv_param param_list[] = {
+               {
+                       .type = BNXT_ULP_DF_PARAM_TYPE_DEV_PORT_ID,
+                       .length = 2,
+                       .value = {(port_id >> 8) & 0xff, port_id & 0xff}
+               },
+               {
+                       .type = BNXT_ULP_DF_PARAM_TYPE_LAST,
+                       .length = 0,
+                       .value = {0}
+               }
+       };
+
+       return ulp_default_flow_create(bp->eth_dev, param_list, flow_type,
+                                      flow_id);
+}
+
+static int32_t
+bnxt_create_df_rules(struct bnxt *bp)
+{
+       struct bnxt_ulp_data *cfg_data;
+       int rc;
+
+       cfg_data = bp->ulp_ctx->cfg_data;
+       rc = bnxt_create_port_app_df_rule(bp, BNXT_ULP_DF_TPL_PORT_TO_VS,
+                                         &cfg_data->port_to_app_flow_id);
+       if (rc) {
+               PMD_DRV_LOG(ERR,
+                           "Failed to create port to app default rule\n");
+               return rc;
+       }
+
+       BNXT_TF_DBG(DEBUG, "***** created port to app default rule ******\n");
+       rc = bnxt_create_port_app_df_rule(bp, BNXT_ULP_DF_TPL_VS_TO_PORT,
+                                         &cfg_data->app_to_port_flow_id);
+       if (!rc) {
+               rc = ulp_default_flow_db_cfa_action_get(bp->ulp_ctx,
+                                                       cfg_data->app_to_port_flow_id,
+                                                       &cfg_data->tx_cfa_action);
+               if (rc)
+                       goto err;
+
+               BNXT_TF_DBG(DEBUG,
+                           "***** created app to port default rule *****\n");
+               return 0;
+       }
+
+err:
+       BNXT_TF_DBG(DEBUG, "Failed to create app to port default rule\n");
+       return rc;
+}
+
+static void
+bnxt_destroy_df_rules(struct bnxt *bp)
+{
+       struct bnxt_ulp_data *cfg_data;
+
+       cfg_data = bp->ulp_ctx->cfg_data;
+       ulp_default_flow_destroy(bp->eth_dev, cfg_data->port_to_app_flow_id);
+       ulp_default_flow_destroy(bp->eth_dev, cfg_data->app_to_port_flow_id);
+}
+
 static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 {
        struct bnxt *bp = eth_dev->data->dev_private;
@@ -1251,9 +1342,6 @@ static void bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 
-       if (BNXT_TRUFLOW_EN(bp))
-               bnxt_ulp_deinit(bp);
-
        eth_dev->data->dev_started = 0;
        /* Prevent crashes when queues are still in use */
        eth_dev->rx_pkt_burst = &bnxt_dummy_recv_pkts;
@@ -1309,6 +1397,12 @@ static void bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
        rte_eal_alarm_cancel(bnxt_dev_recover, (void *)bp);
        bnxt_cancel_fc_thread(bp);
 
+       if (BNXT_TRUFLOW_EN(bp)) {
+               if (bp->rep_info != NULL)
+                       bnxt_destroy_df_rules(bp);
+               bnxt_ulp_deinit(bp);
+       }
+
        if (eth_dev->data->dev_started)
                bnxt_dev_stop_op(eth_dev);
 
@@ -1320,6 +1414,7 @@ static void bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
        bnxt_free_cos_queues(bp);
        bnxt_free_link_info(bp);
        bnxt_free_pf_info(bp);
+       bnxt_free_parent_info(bp);
 
        eth_dev->dev_ops = NULL;
        eth_dev->rx_pkt_burst = NULL;
@@ -1556,6 +1651,9 @@ static int bnxt_promiscuous_disable_op(struct rte_eth_dev *eth_dev)
        if (rc != 0)
                vnic->flags = old_flags;
 
+       if (BNXT_TRUFLOW_EN(bp) && bp->rep_info != NULL)
+               bnxt_create_df_rules(bp);
+
        return rc;
 }
 
@@ -2397,15 +2495,15 @@ bnxt_vlan_tpid_set_op(struct rte_eth_dev *dev, enum rte_vlan_type vlan_type,
                        bp->outer_tpid_bd =
                                TX_BD_LONG_CFA_META_VLAN_TPID_TPID8100;
                                break;
-               case 0x9100:
+               case RTE_ETHER_TYPE_QINQ1:
                        bp->outer_tpid_bd =
                                TX_BD_LONG_CFA_META_VLAN_TPID_TPID9100;
                                break;
-               case 0x9200:
+               case RTE_ETHER_TYPE_QINQ2:
                        bp->outer_tpid_bd =
                                TX_BD_LONG_CFA_META_VLAN_TPID_TPID9200;
                                break;
-               case 0x9300:
+               case RTE_ETHER_TYPE_QINQ3:
                        bp->outer_tpid_bd =
                                 TX_BD_LONG_CFA_META_VLAN_TPID_TPID9300;
                                break;
@@ -2570,6 +2668,50 @@ bnxt_txq_info_get_op(struct rte_eth_dev *dev, uint16_t queue_id,
        qinfo->conf.tx_deferred_start = txq->tx_deferred_start;
 }
 
+static int
+bnxt_rx_burst_mode_get(struct rte_eth_dev *dev, __rte_unused uint16_t queue_id,
+                      struct rte_eth_burst_mode *mode)
+{
+       eth_rx_burst_t pkt_burst = dev->rx_pkt_burst;
+
+       if (pkt_burst == bnxt_recv_pkts) {
+               snprintf(mode->info, sizeof(mode->info), "%s",
+                        "Scalar");
+               return 0;
+       }
+#if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM64)
+       if (pkt_burst == bnxt_recv_pkts_vec) {
+               snprintf(mode->info, sizeof(mode->info), "%s",
+                        "Vector SSE");
+               return 0;
+       }
+#endif
+
+       return -EINVAL;
+}
+
+static int
+bnxt_tx_burst_mode_get(struct rte_eth_dev *dev, __rte_unused uint16_t queue_id,
+                      struct rte_eth_burst_mode *mode)
+{
+       eth_tx_burst_t pkt_burst = dev->tx_pkt_burst;
+
+       if (pkt_burst == bnxt_xmit_pkts) {
+               snprintf(mode->info, sizeof(mode->info), "%s",
+                        "Scalar");
+               return 0;
+       }
+#if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM64)
+       if (pkt_burst == bnxt_xmit_pkts_vec) {
+               snprintf(mode->info, sizeof(mode->info), "%s",
+                        "Vector SSE");
+               return 0;
+       }
+#endif
+
+       return -EINVAL;
+}
+
 int bnxt_mtu_set_op(struct rte_eth_dev *eth_dev, uint16_t new_mtu)
 {
        struct bnxt *bp = eth_dev->data->dev_private;
@@ -2588,7 +2730,7 @@ int bnxt_mtu_set_op(struct rte_eth_dev *eth_dev, uint16_t new_mtu)
        new_pkt_size = new_mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN +
                       VLAN_TAG_SIZE * BNXT_NUM_VLANS;
 
-#ifdef RTE_ARCH_X86
+#if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM64)
        /*
         * If vector-mode tx/rx is active, disallow any MTU change that would
         * require scattered receive support.
@@ -3604,7 +3746,7 @@ free_filter:
        return ret;
 }
 
-static int
+int
 bnxt_filter_ctrl_op(struct rte_eth_dev *dev,
                    enum rte_filter_type filter_type,
                    enum rte_filter_op filter_op, void *arg)
@@ -3612,7 +3754,12 @@ bnxt_filter_ctrl_op(struct rte_eth_dev *dev,
        struct bnxt *bp = dev->data->dev_private;
        int ret = 0;
 
-       ret = is_bnxt_in_error(dev->data->dev_private);
+       if (BNXT_ETH_DEV_IS_REPRESENTOR(dev)) {
+               struct bnxt_vf_representor *vfr = dev->data->dev_private;
+               bp = vfr->parent_dev->data->dev_private;
+       }
+
+       ret = is_bnxt_in_error(bp);
        if (ret)
                return ret;
 
@@ -4146,6 +4293,8 @@ static const struct eth_dev_ops bnxt_dev_ops = {
        .set_mc_addr_list = bnxt_dev_set_mc_addr_list_op,
        .rxq_info_get = bnxt_rxq_info_get_op,
        .txq_info_get = bnxt_txq_info_get_op,
+       .rx_burst_mode_get = bnxt_rx_burst_mode_get,
+       .tx_burst_mode_get = bnxt_tx_burst_mode_get,
        .dev_led_on = bnxt_dev_led_on_op,
        .dev_led_off = bnxt_dev_led_off_op,
        .xstats_get_by_id = bnxt_dev_xstats_get_by_id_op,
@@ -5044,25 +5193,48 @@ static void bnxt_config_vf_req_fwd(struct bnxt *bp)
 }
 
 uint16_t
-bnxt_get_svif(uint16_t port_id, bool func_svif)
+bnxt_get_svif(uint16_t port_id, bool func_svif,
+             enum bnxt_ulp_intf_type type)
 {
        struct rte_eth_dev *eth_dev;
        struct bnxt *bp;
 
        eth_dev = &rte_eth_devices[port_id];
+       if (BNXT_ETH_DEV_IS_REPRESENTOR(eth_dev)) {
+               struct bnxt_vf_representor *vfr = eth_dev->data->dev_private;
+               if (!vfr)
+                       return 0;
+
+               if (type == BNXT_ULP_INTF_TYPE_VF_REP)
+                       return vfr->svif;
+
+               eth_dev = vfr->parent_dev;
+       }
+
        bp = eth_dev->data->dev_private;
 
        return func_svif ? bp->func_svif : bp->port_svif;
 }
 
 uint16_t
-bnxt_get_vnic_id(uint16_t port)
+bnxt_get_vnic_id(uint16_t port, enum bnxt_ulp_intf_type type)
 {
        struct rte_eth_dev *eth_dev;
        struct bnxt_vnic_info *vnic;
        struct bnxt *bp;
 
        eth_dev = &rte_eth_devices[port];
+       if (BNXT_ETH_DEV_IS_REPRESENTOR(eth_dev)) {
+               struct bnxt_vf_representor *vfr = eth_dev->data->dev_private;
+               if (!vfr)
+                       return 0;
+
+               if (type == BNXT_ULP_INTF_TYPE_VF_REP)
+                       return vfr->dflt_vnic_id;
+
+               eth_dev = vfr->parent_dev;
+       }
+
        bp = eth_dev->data->dev_private;
 
        vnic = BNXT_GET_DEFAULT_VNIC(bp);
@@ -5071,17 +5243,99 @@ bnxt_get_vnic_id(uint16_t port)
 }
 
 uint16_t
-bnxt_get_fw_func_id(uint16_t port)
+bnxt_get_fw_func_id(uint16_t port, enum bnxt_ulp_intf_type type)
 {
        struct rte_eth_dev *eth_dev;
        struct bnxt *bp;
 
        eth_dev = &rte_eth_devices[port];
+       if (BNXT_ETH_DEV_IS_REPRESENTOR(eth_dev)) {
+               struct bnxt_vf_representor *vfr = eth_dev->data->dev_private;
+               if (!vfr)
+                       return 0;
+
+               if (type == BNXT_ULP_INTF_TYPE_VF_REP)
+                       return vfr->fw_fid;
+
+               eth_dev = vfr->parent_dev;
+       }
+
        bp = eth_dev->data->dev_private;
 
        return bp->fw_fid;
 }
 
+enum bnxt_ulp_intf_type
+bnxt_get_interface_type(uint16_t port)
+{
+       struct rte_eth_dev *eth_dev;
+       struct bnxt *bp;
+
+       eth_dev = &rte_eth_devices[port];
+       if (BNXT_ETH_DEV_IS_REPRESENTOR(eth_dev))
+               return BNXT_ULP_INTF_TYPE_VF_REP;
+
+       bp = eth_dev->data->dev_private;
+       if (BNXT_PF(bp))
+               return BNXT_ULP_INTF_TYPE_PF;
+       else if (BNXT_VF_IS_TRUSTED(bp))
+               return BNXT_ULP_INTF_TYPE_TRUSTED_VF;
+       else if (BNXT_VF(bp))
+               return BNXT_ULP_INTF_TYPE_VF;
+
+       return BNXT_ULP_INTF_TYPE_INVALID;
+}
+
+uint16_t
+bnxt_get_phy_port_id(uint16_t port_id)
+{
+       struct bnxt_vf_representor *vfr;
+       struct rte_eth_dev *eth_dev;
+       struct bnxt *bp;
+
+       eth_dev = &rte_eth_devices[port_id];
+       if (BNXT_ETH_DEV_IS_REPRESENTOR(eth_dev)) {
+               vfr = eth_dev->data->dev_private;
+               if (!vfr)
+                       return 0;
+
+               eth_dev = vfr->parent_dev;
+       }
+
+       bp = eth_dev->data->dev_private;
+
+       return BNXT_PF(bp) ? bp->pf->port_id : bp->parent->port_id;
+}
+
+uint16_t
+bnxt_get_parif(uint16_t port_id, enum bnxt_ulp_intf_type type)
+{
+       struct rte_eth_dev *eth_dev;
+       struct bnxt *bp;
+
+       eth_dev = &rte_eth_devices[port_id];
+       if (BNXT_ETH_DEV_IS_REPRESENTOR(eth_dev)) {
+               struct bnxt_vf_representor *vfr = eth_dev->data->dev_private;
+               if (!vfr)
+                       return 0;
+
+               if (type == BNXT_ULP_INTF_TYPE_VF_REP)
+                       return vfr->fw_fid - 1;
+
+               eth_dev = vfr->parent_dev;
+       }
+
+       bp = eth_dev->data->dev_private;
+
+       return BNXT_PF(bp) ? bp->fw_fid - 1 : bp->parent->fid - 1;
+}
+
+uint16_t
+bnxt_get_vport(uint16_t port_id)
+{
+       return (1 << bnxt_get_phy_port_id(port_id));
+}
+
 static void bnxt_alloc_error_recovery_info(struct bnxt *bp)
 {
        struct bnxt_error_recovery_info *info = bp->recovery_info;
@@ -5208,6 +5462,10 @@ static int bnxt_init_fw(struct bnxt *bp)
 
        bnxt_hwrm_port_mac_qcfg(bp);
 
+       bnxt_hwrm_parent_pf_qcfg(bp);
+
+       bnxt_hwrm_port_phy_qcaps(bp);
+
        rc = bnxt_hwrm_cfa_adv_flow_mgmt_qcaps(bp);
        if (rc)
                return rc;
@@ -5242,7 +5500,7 @@ bnxt_init_locks(struct bnxt *bp)
 
 static int bnxt_init_resources(struct bnxt *bp, bool reconfig_dev)
 {
-       int rc;
+       int rc = 0;
 
        rc = bnxt_init_fw(bp);
        if (rc)
@@ -5526,6 +5784,10 @@ bnxt_dev_init(struct rte_eth_dev *eth_dev, void *params __rte_unused)
        if (rc)
                goto error_free;
 
+       rc = bnxt_alloc_parent_info(bp);
+       if (rc)
+               goto error_free;
+
        rc = bnxt_alloc_hwrm_resources(bp);
        if (rc) {
                PMD_DRV_LOG(ERR,
@@ -5641,6 +5903,8 @@ bnxt_uninit_locks(struct bnxt *bp)
 {
        pthread_mutex_destroy(&bp->flow_lock);
        pthread_mutex_destroy(&bp->def_cp_lock);
+       if (bp->rep_info)
+               pthread_mutex_destroy(&bp->rep_info->vfr_lock);
 }
 
 static int
@@ -5663,6 +5927,7 @@ bnxt_uninit_resources(struct bnxt *bp, bool reconfig_dev)
 
        bnxt_uninit_locks(bp);
        bnxt_free_flow_stats_info(bp);
+       bnxt_free_rep_info(bp);
        rte_free(bp->ptp_cfg);
        bp->ptp_cfg = NULL;
        return rc;
@@ -5702,56 +5967,73 @@ static int bnxt_pci_remove_dev_with_reps(struct rte_eth_dev *eth_dev)
        return ret;
 }
 
-static int bnxt_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
-       struct rte_pci_device *pci_dev)
+static void bnxt_free_rep_info(struct bnxt *bp)
 {
-       char name[RTE_ETH_NAME_MAX_LEN];
-       struct rte_eth_devargs eth_da = { .nb_representor_ports = 0 };
-       struct rte_eth_dev *backing_eth_dev, *vf_rep_eth_dev;
-       uint16_t num_rep;
-       int i, ret = 0;
-       struct bnxt *backing_bp;
+       rte_free(bp->rep_info);
+       bp->rep_info = NULL;
+       rte_free(bp->cfa_code_map);
+       bp->cfa_code_map = NULL;
+}
 
-       if (pci_dev->device.devargs) {
-               ret = rte_eth_devargs_parse(pci_dev->device.devargs->args,
-                                           &eth_da);
-               if (ret)
-                       return ret;
-       }
+static int bnxt_init_rep_info(struct bnxt *bp)
+{
+       int i = 0, rc;
 
-       num_rep = eth_da.nb_representor_ports;
-       PMD_DRV_LOG(DEBUG, "nb_representor_ports = %d\n",
-                   num_rep);
+       if (bp->rep_info)
+               return 0;
 
-       /* We could come here after first level of probe is already invoked
-        * as part of an application bringup(OVS-DPDK vswitchd), so first check
-        * for already allocated eth_dev for the backing device (PF/Trusted VF)
-        */
-       backing_eth_dev = rte_eth_dev_allocated(pci_dev->device.name);
-       if (backing_eth_dev == NULL) {
-               ret = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
-                                        sizeof(struct bnxt),
-                                        eth_dev_pci_specific_init, pci_dev,
-                                        bnxt_dev_init, NULL);
+       bp->rep_info = rte_zmalloc("bnxt_rep_info",
+                                  sizeof(bp->rep_info[0]) * BNXT_MAX_VF_REPS,
+                                  0);
+       if (!bp->rep_info) {
+               PMD_DRV_LOG(ERR, "Failed to alloc memory for rep info\n");
+               return -ENOMEM;
+       }
+       bp->cfa_code_map = rte_zmalloc("bnxt_cfa_code_map",
+                                      sizeof(*bp->cfa_code_map) *
+                                      BNXT_MAX_CFA_CODE, 0);
+       if (!bp->cfa_code_map) {
+               PMD_DRV_LOG(ERR, "Failed to alloc memory for cfa_code_map\n");
+               bnxt_free_rep_info(bp);
+               return -ENOMEM;
+       }
 
-               if (ret || !num_rep)
-                       return ret;
+       for (i = 0; i < BNXT_MAX_CFA_CODE; i++)
+               bp->cfa_code_map[i] = BNXT_VF_IDX_INVALID;
+
+       rc = pthread_mutex_init(&bp->rep_info->vfr_lock, NULL);
+       if (rc) {
+               PMD_DRV_LOG(ERR, "Unable to initialize vfr_lock\n");
+               bnxt_free_rep_info(bp);
+               return rc;
        }
+       return rc;
+}
+
+static int bnxt_rep_port_probe(struct rte_pci_device *pci_dev,
+                              struct rte_eth_devargs eth_da,
+                              struct rte_eth_dev *backing_eth_dev)
+{
+       struct rte_eth_dev *vf_rep_eth_dev;
+       char name[RTE_ETH_NAME_MAX_LEN];
+       struct bnxt *backing_bp;
+       uint16_t num_rep;
+       int i, ret = 0;
 
+       num_rep = eth_da.nb_representor_ports;
        if (num_rep > BNXT_MAX_VF_REPS) {
                PMD_DRV_LOG(ERR, "nb_representor_ports = %d > %d MAX VF REPS\n",
-                           eth_da.nb_representor_ports, BNXT_MAX_VF_REPS);
-               ret = -EINVAL;
-               return ret;
+                           num_rep, BNXT_MAX_VF_REPS);
+               return -EINVAL;
        }
 
-       /* probe representor ports now */
-       if (!backing_eth_dev)
-               backing_eth_dev = rte_eth_dev_allocated(pci_dev->device.name);
-       if (backing_eth_dev == NULL) {
-               ret = -ENODEV;
-               return ret;
+       if (num_rep > RTE_MAX_ETHPORTS) {
+               PMD_DRV_LOG(ERR,
+                           "nb_representor_ports = %d > %d MAX ETHPORTS\n",
+                           num_rep, RTE_MAX_ETHPORTS);
+               return -EINVAL;
        }
+
        backing_bp = backing_eth_dev->data->dev_private;
 
        if (!(BNXT_PF(backing_bp) || BNXT_VF_IS_TRUSTED(backing_bp))) {
@@ -5760,14 +6042,17 @@ static int bnxt_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
                /* Returning an error is not an option.
                 * Applications are not handling this correctly
                 */
-               return ret;
+               return 0;
        }
 
-       for (i = 0; i < eth_da.nb_representor_ports; i++) {
+       if (bnxt_init_rep_info(backing_bp))
+               return 0;
+
+       for (i = 0; i < num_rep; i++) {
                struct bnxt_vf_representor representor = {
                        .vf_id = eth_da.representor_ports[i],
                        .switch_domain_id = backing_bp->switch_domain_id,
-                       .parent_priv = backing_bp
+                       .parent_dev = backing_eth_dev
                };
 
                if (representor.vf_id >= BNXT_MAX_VF_REPS) {
@@ -5808,6 +6093,48 @@ static int bnxt_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
        return ret;
 }
 
+static int bnxt_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+                         struct rte_pci_device *pci_dev)
+{
+       struct rte_eth_devargs eth_da = { .nb_representor_ports = 0 };
+       struct rte_eth_dev *backing_eth_dev;
+       uint16_t num_rep;
+       int ret = 0;
+
+       if (pci_dev->device.devargs) {
+               ret = rte_eth_devargs_parse(pci_dev->device.devargs->args,
+                                           &eth_da);
+               if (ret)
+                       return ret;
+       }
+
+       num_rep = eth_da.nb_representor_ports;
+       PMD_DRV_LOG(DEBUG, "nb_representor_ports = %d\n",
+                   num_rep);
+
+       /* We could come here after first level of probe is already invoked
+        * as part of an application bringup(OVS-DPDK vswitchd), so first check
+        * for already allocated eth_dev for the backing device (PF/Trusted VF)
+        */
+       backing_eth_dev = rte_eth_dev_allocated(pci_dev->device.name);
+       if (backing_eth_dev == NULL) {
+               ret = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
+                                        sizeof(struct bnxt),
+                                        eth_dev_pci_specific_init, pci_dev,
+                                        bnxt_dev_init, NULL);
+
+               if (ret || !num_rep)
+                       return ret;
+
+               backing_eth_dev = rte_eth_dev_allocated(pci_dev->device.name);
+       }
+
+       /* probe representor ports now */
+       ret = bnxt_rep_port_probe(pci_dev, eth_da, backing_eth_dev);
+
+       return ret;
+}
+
 static int bnxt_pci_remove(struct rte_pci_device *pci_dev)
 {
        struct rte_eth_dev *eth_dev;