sfc: add devlink port support for ef100
authorAlejandro Lucero <alejandro.lucero-palau@amd.com>
Wed, 15 Feb 2023 09:08:25 +0000 (09:08 +0000)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 16 Feb 2023 11:03:12 +0000 (12:03 +0100)
Using the data when enumerating mports, create devlink ports just before
netdevs are registered and remove those devlink ports after netdev has
been unregistered.

Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Acked-by: Martin Habets <habetsm.xilinx@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/sfc/ef100_netdev.c
drivers/net/ethernet/sfc/ef100_rep.c
drivers/net/ethernet/sfc/ef100_rep.h
drivers/net/ethernet/sfc/efx_devlink.c
drivers/net/ethernet/sfc/efx_devlink.h
drivers/net/ethernet/sfc/mae.h
drivers/net/ethernet/sfc/net_driver.h

index 6cf7478..3681473 100644 (file)
@@ -337,6 +337,7 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
        ef100_unregister_netdev(efx);
 
 #ifdef CONFIG_SFC_SRIOV
+       ef100_pf_unset_devlink_port(efx);
        efx_fini_tc(efx);
 #endif
 
@@ -422,6 +423,9 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
                rc = ef100_probe_netdev_pf(efx);
                if (rc)
                        goto fail;
+#ifdef CONFIG_SFC_SRIOV
+               ef100_pf_set_devlink_port(efx);
+#endif
        }
 
        efx->netdev_notifier.notifier_call = ef100_netdev_event;
@@ -432,7 +436,13 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
                goto fail;
        }
 
+       efx_probe_devlink_unlock(efx);
+       return rc;
 fail:
+#ifdef CONFIG_SFC_SRIOV
+       /* remove devlink port if does exist */
+       ef100_pf_unset_devlink_port(efx);
+#endif
        efx_probe_devlink_unlock(efx);
        return rc;
 }
index 9cd1a3a..6b5bc5d 100644 (file)
@@ -16,6 +16,7 @@
 #include "mae.h"
 #include "rx_common.h"
 #include "tc_bindings.h"
+#include "efx_devlink.h"
 
 #define EFX_EF100_REP_DRIVER   "efx_ef100_rep"
 
@@ -297,6 +298,7 @@ int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i)
                        i, rc);
                goto fail1;
        }
+       ef100_rep_set_devlink_port(efv);
        rc = register_netdev(efv->net_dev);
        if (rc) {
                pci_err(efx->pci_dev,
@@ -308,6 +310,7 @@ int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i)
                efv->net_dev->name);
        return 0;
 fail2:
+       ef100_rep_unset_devlink_port(efv);
        efx_ef100_deconfigure_rep(efv);
 fail1:
        efx_ef100_rep_destroy_netdev(efv);
@@ -323,6 +326,7 @@ void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv)
                return;
        netif_dbg(efx, drv, rep_dev, "Removing VF representor\n");
        unregister_netdev(rep_dev);
+       ef100_rep_unset_devlink_port(efv);
        efx_ef100_deconfigure_rep(efv);
        efx_ef100_rep_destroy_netdev(efv);
 }
@@ -339,6 +343,24 @@ void efx_ef100_fini_vfreps(struct efx_nic *efx)
                efx_ef100_vfrep_destroy(efx, efv);
 }
 
+static bool ef100_mport_is_pcie_vnic(struct mae_mport_desc *mport_desc)
+{
+       return mport_desc->mport_type == MAE_MPORT_DESC_MPORT_TYPE_VNIC &&
+              mport_desc->vnic_client_type == MAE_MPORT_DESC_VNIC_CLIENT_TYPE_FUNCTION;
+}
+
+bool ef100_mport_on_local_intf(struct efx_nic *efx,
+                              struct mae_mport_desc *mport_desc)
+{
+       struct ef100_nic_data *nic_data = efx->nic_data;
+       bool pcie_func;
+
+       pcie_func = ef100_mport_is_pcie_vnic(mport_desc);
+
+       return nic_data->have_local_intf && pcie_func &&
+                    mport_desc->interface_idx == nic_data->local_mae_intf;
+}
+
 void efx_ef100_init_reps(struct efx_nic *efx)
 {
        struct ef100_nic_data *nic_data = efx->nic_data;
index 328ac0c..ae6add4 100644 (file)
@@ -22,6 +22,8 @@ struct efx_rep_sw_stats {
        atomic64_t rx_dropped, tx_errors;
 };
 
+struct devlink_port;
+
 /**
  * struct efx_rep - Private data for an Efx representor
  *
@@ -39,6 +41,7 @@ struct efx_rep_sw_stats {
  * @rx_lock: protects @rx_list
  * @napi: NAPI control structure
  * @stats: software traffic counters for netdev stats
+ * @dl_port: devlink port associated to this netdev representor
  */
 struct efx_rep {
        struct efx_nic *parent;
@@ -54,6 +57,7 @@ struct efx_rep {
        spinlock_t rx_lock;
        struct napi_struct napi;
        struct efx_rep_sw_stats stats;
+       struct devlink_port *dl_port;
 };
 
 int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i);
@@ -69,4 +73,7 @@ struct efx_rep *efx_ef100_find_rep_by_mport(struct efx_nic *efx, u16 mport);
 extern const struct net_device_ops efx_ef100_rep_netdev_ops;
 void efx_ef100_init_reps(struct efx_nic *efx);
 void efx_ef100_fini_reps(struct efx_nic *efx);
+struct mae_mport_desc;
+bool ef100_mport_on_local_intf(struct efx_nic *efx,
+                              struct mae_mport_desc *mport_desc);
 #endif /* EF100_REP_H */
index 76d5404..01e75eb 100644 (file)
 #include "mcdi.h"
 #include "mcdi_functions.h"
 #include "mcdi_pcol.h"
+#ifdef CONFIG_SFC_SRIOV
+#include "mae.h"
+#include "ef100_rep.h"
+#endif
 
 struct efx_devlink {
        struct efx_nic *efx;
 };
 
+#ifdef CONFIG_SFC_SRIOV
+static void efx_devlink_del_port(struct devlink_port *dl_port)
+{
+       if (!dl_port)
+               return;
+       devl_port_unregister(dl_port);
+}
+
+static int efx_devlink_add_port(struct efx_nic *efx,
+                               struct mae_mport_desc *mport)
+{
+       bool external = false;
+
+       if (!ef100_mport_on_local_intf(efx, mport))
+               external = true;
+
+       switch (mport->mport_type) {
+       case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
+               if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
+                       devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
+                                                     mport->vf_idx,
+                                                     external);
+               else
+                       devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
+                                                     external);
+               break;
+       default:
+               /* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
+               return 0;
+       }
+
+       mport->dl_port.index = mport->mport_id;
+
+       return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id);
+}
+#endif
+
 static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
                                            struct devlink_info_req *req,
                                            unsigned int partition_type,
@@ -475,6 +516,70 @@ static const struct devlink_ops sfc_devlink_ops = {
        .info_get                       = efx_devlink_info_get,
 };
 
+#ifdef CONFIG_SFC_SRIOV
+static struct devlink_port *ef100_set_devlink_port(struct efx_nic *efx, u32 idx)
+{
+       struct mae_mport_desc *mport;
+       u32 id;
+       int rc;
+
+       if (efx_mae_lookup_mport(efx, idx, &id)) {
+               /* This should not happen. */
+               if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
+                       pci_warn_once(efx->pci_dev, "No mport ID found for PF.\n");
+               else
+                       pci_warn_once(efx->pci_dev, "No mport ID found for VF %u.\n",
+                                     idx);
+               return NULL;
+       }
+
+       mport = efx_mae_get_mport(efx, id);
+       if (!mport) {
+               /* This should not happen. */
+               if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
+                       pci_warn_once(efx->pci_dev, "No mport found for PF.\n");
+               else
+                       pci_warn_once(efx->pci_dev, "No mport found for VF %u.\n",
+                                     idx);
+               return NULL;
+       }
+
+       rc = efx_devlink_add_port(efx, mport);
+       if (rc) {
+               if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
+                       pci_warn(efx->pci_dev,
+                                "devlink port creation for PF failed.\n");
+               else
+                       pci_warn(efx->pci_dev,
+                                "devlink_port creationg for VF %u failed.\n",
+                                idx);
+               return NULL;
+       }
+
+       return &mport->dl_port;
+}
+
+void ef100_rep_set_devlink_port(struct efx_rep *efv)
+{
+       efv->dl_port = ef100_set_devlink_port(efv->parent, efv->idx);
+}
+
+void ef100_pf_set_devlink_port(struct efx_nic *efx)
+{
+       efx->dl_port = ef100_set_devlink_port(efx, MAE_MPORT_DESC_VF_IDX_NULL);
+}
+
+void ef100_rep_unset_devlink_port(struct efx_rep *efv)
+{
+       efx_devlink_del_port(efv->dl_port);
+}
+
+void ef100_pf_unset_devlink_port(struct efx_nic *efx)
+{
+       efx_devlink_del_port(efx->dl_port);
+}
+#endif
+
 void efx_fini_devlink_lock(struct efx_nic *efx)
 {
        if (efx->devlink)
index a526936..e5fd5e1 100644 (file)
@@ -36,4 +36,12 @@ void efx_probe_devlink_unlock(struct efx_nic *efx);
 void efx_fini_devlink_lock(struct efx_nic *efx);
 void efx_fini_devlink_and_unlock(struct efx_nic *efx);
 
+#ifdef CONFIG_SFC_SRIOV
+struct efx_rep;
+
+void ef100_pf_set_devlink_port(struct efx_nic *efx);
+void ef100_rep_set_devlink_port(struct efx_rep *efv);
+void ef100_pf_unset_devlink_port(struct efx_nic *efx);
+void ef100_rep_unset_devlink_port(struct efx_rep *efv);
+#endif
 #endif /* _EFX_DEVLINK_H */
index b9bf86c..bec293a 100644 (file)
@@ -13,6 +13,7 @@
 #define EF100_MAE_H
 /* MCDI interface for the ef100 Match-Action Engine */
 
+#include <net/devlink.h>
 #include "net_driver.h"
 #include "tc.h"
 #include "mcdi_pcol.h" /* needed for various MC_CMD_MAE_*_NULL defines */
@@ -43,6 +44,7 @@ struct mae_mport_desc {
                };
        };
        struct rhash_head linkage;
+       struct devlink_port dl_port;
 };
 
 int efx_mae_enumerate_mports(struct efx_nic *efx);
index bc9efbf..fcd51d3 100644 (file)
@@ -998,6 +998,7 @@ struct efx_mae;
  * @netdev_notifier: Netdevice notifier.
  * @tc: state for TC offload (EF100).
  * @devlink: reference to devlink structure owned by this device
+ * @dl_port: devlink port associated with the PF
  * @mem_bar: The BAR that is mapped into membase.
  * @reg_base: Offset from the start of the bar to the function control window.
  * @monitor_work: Hardware monitor workitem
@@ -1185,6 +1186,7 @@ struct efx_nic {
        struct efx_tc_state *tc;
 
        struct devlink *devlink;
+       struct devlink_port *dl_port;
        unsigned int mem_bar;
        u32 reg_base;