+static int bnxt_pci_remove_dev_with_reps(struct rte_eth_dev *eth_dev)
+{
+ struct bnxt *bp = eth_dev->data->dev_private;
+ struct rte_eth_dev *vf_rep_eth_dev;
+ int ret = 0, i;
+
+ if (!bp)
+ return -EINVAL;
+
+ for (i = 0; i < bp->num_reps; i++) {
+ vf_rep_eth_dev = bp->rep_info[i].vfr_eth_dev;
+ if (!vf_rep_eth_dev)
+ continue;
+ rte_eth_dev_destroy(vf_rep_eth_dev, bnxt_vf_representor_uninit);
+ }
+ ret = rte_eth_dev_destroy(eth_dev, bnxt_dev_uninit);
+
+ return ret;
+}
+
+static void bnxt_free_rep_info(struct bnxt *bp)
+{
+ rte_free(bp->rep_info);
+ bp->rep_info = NULL;
+ rte_free(bp->cfa_code_map);
+ bp->cfa_code_map = NULL;
+}
+
+static int bnxt_init_rep_info(struct bnxt *bp)
+{
+ int i = 0, rc;
+
+ if (bp->rep_info)
+ return 0;
+
+ 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;
+ }
+
+ 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",
+ num_rep, BNXT_MAX_VF_REPS);
+ return -EINVAL;
+ }
+
+ 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))) {
+ PMD_DRV_LOG(ERR,
+ "Not a PF or trusted VF. No Representor support\n");
+ /* Returning an error is not an option.
+ * Applications are not handling this correctly
+ */
+ return 0;
+ }
+
+ 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_dev = backing_eth_dev
+ };
+
+ if (representor.vf_id >= BNXT_MAX_VF_REPS) {
+ PMD_DRV_LOG(ERR, "VF-Rep id %d >= %d MAX VF ID\n",
+ representor.vf_id, BNXT_MAX_VF_REPS);
+ continue;
+ }
+
+ /* representor port net_bdf_port */
+ snprintf(name, sizeof(name), "net_%s_representor_%d",
+ pci_dev->device.name, eth_da.representor_ports[i]);
+
+ ret = rte_eth_dev_create(&pci_dev->device, name,
+ sizeof(struct bnxt_vf_representor),
+ NULL, NULL,
+ bnxt_vf_representor_init,
+ &representor);
+
+ if (!ret) {
+ vf_rep_eth_dev = rte_eth_dev_allocated(name);
+ if (!vf_rep_eth_dev) {
+ PMD_DRV_LOG(ERR, "Failed to find the eth_dev"
+ " for VF-Rep: %s.", name);
+ bnxt_pci_remove_dev_with_reps(backing_eth_dev);
+ ret = -ENODEV;
+ return ret;
+ }
+ backing_bp->rep_info[representor.vf_id].vfr_eth_dev =
+ vf_rep_eth_dev;
+ backing_bp->num_reps++;
+ } else {
+ PMD_DRV_LOG(ERR, "failed to create bnxt vf "
+ "representor %s.", name);
+ bnxt_pci_remove_dev_with_reps(backing_eth_dev);
+ }
+ }
+
+ return ret;
+}
+