sfc: add skeleton ef100 VF representors
authorEdward Cree <ecree.xilinx@gmail.com>
Wed, 20 Jul 2022 18:29:28 +0000 (19:29 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 22 Jul 2022 11:50:06 +0000 (12:50 +0100)
No net_device_ops yet, just a placeholder netdev created per VF.

Signed-off-by: Edward Cree <ecree.xilinx@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/sfc/Makefile
drivers/net/ethernet/sfc/ef100_netdev.c
drivers/net/ethernet/sfc/ef100_rep.c [new file with mode: 0644]
drivers/net/ethernet/sfc/ef100_rep.h [new file with mode: 0644]
drivers/net/ethernet/sfc/ef100_sriov.c
drivers/net/ethernet/sfc/ef100_sriov.h
drivers/net/ethernet/sfc/efx_common.c
drivers/net/ethernet/sfc/net_driver.h

index b929803..7a6772b 100644 (file)
@@ -8,7 +8,7 @@ sfc-y                   += efx.o efx_common.o efx_channels.o nic.o \
                           ef100.o ef100_nic.o ef100_netdev.o \
                           ef100_ethtool.o ef100_rx.o ef100_tx.o
 sfc-$(CONFIG_SFC_MTD)  += mtd.o
-sfc-$(CONFIG_SFC_SRIOV)        += sriov.o ef10_sriov.o ef100_sriov.o
+sfc-$(CONFIG_SFC_SRIOV)        += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o
 
 obj-$(CONFIG_SFC)      += sfc.o
 
index 060392d..f4a124b 100644 (file)
@@ -312,7 +312,7 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
        unregister_netdevice_notifier(&efx->netdev_notifier);
 #if defined(CONFIG_SFC_SRIOV)
        if (!efx->type->is_vf)
-               efx_ef100_pci_sriov_disable(efx);
+               efx_ef100_pci_sriov_disable(efx, true);
 #endif
 
        ef100_unregister_netdev(efx);
diff --git a/drivers/net/ethernet/sfc/ef100_rep.c b/drivers/net/ethernet/sfc/ef100_rep.c
new file mode 100644 (file)
index 0000000..f10c25d
--- /dev/null
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2019 Solarflare Communications Inc.
+ * Copyright 2020-2022 Xilinx Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include "ef100_rep.h"
+#include "ef100_nic.h"
+
+static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv)
+{
+       efv->parent = efx;
+       INIT_LIST_HEAD(&efv->list);
+       efv->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE |
+                         NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
+                         NETIF_MSG_IFUP | NETIF_MSG_RX_ERR |
+                         NETIF_MSG_TX_ERR | NETIF_MSG_HW;
+       return 0;
+}
+
+static const struct net_device_ops efx_ef100_rep_netdev_ops = {
+};
+
+static const struct ethtool_ops efx_ef100_rep_ethtool_ops = {
+};
+
+static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,
+                                                  unsigned int i)
+{
+       struct net_device *net_dev;
+       struct efx_rep *efv;
+       int rc;
+
+       net_dev = alloc_etherdev_mq(sizeof(*efv), 1);
+       if (!net_dev)
+               return ERR_PTR(-ENOMEM);
+
+       efv = netdev_priv(net_dev);
+       rc = efx_ef100_rep_init_struct(efx, efv);
+       if (rc)
+               goto fail1;
+       efv->net_dev = net_dev;
+       rtnl_lock();
+       spin_lock_bh(&efx->vf_reps_lock);
+       list_add_tail(&efv->list, &efx->vf_reps);
+       spin_unlock_bh(&efx->vf_reps_lock);
+       netif_carrier_off(net_dev);
+       netif_tx_stop_all_queues(net_dev);
+       rtnl_unlock();
+
+       net_dev->netdev_ops = &efx_ef100_rep_netdev_ops;
+       net_dev->ethtool_ops = &efx_ef100_rep_ethtool_ops;
+       net_dev->min_mtu = EFX_MIN_MTU;
+       net_dev->max_mtu = EFX_MAX_MTU;
+       return efv;
+fail1:
+       free_netdev(net_dev);
+       return ERR_PTR(rc);
+}
+
+static void efx_ef100_rep_destroy_netdev(struct efx_rep *efv)
+{
+       struct efx_nic *efx = efv->parent;
+
+       spin_lock_bh(&efx->vf_reps_lock);
+       list_del(&efv->list);
+       spin_unlock_bh(&efx->vf_reps_lock);
+       free_netdev(efv->net_dev);
+}
+
+int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i)
+{
+       struct efx_rep *efv;
+       int rc;
+
+       efv = efx_ef100_rep_create_netdev(efx, i);
+       if (IS_ERR(efv)) {
+               rc = PTR_ERR(efv);
+               pci_err(efx->pci_dev,
+                       "Failed to create representor for VF %d, rc %d\n", i,
+                       rc);
+               return rc;
+       }
+       rc = register_netdev(efv->net_dev);
+       if (rc) {
+               pci_err(efx->pci_dev,
+                       "Failed to register representor for VF %d, rc %d\n",
+                       i, rc);
+               goto fail;
+       }
+       pci_dbg(efx->pci_dev, "Representor for VF %d is %s\n", i,
+               efv->net_dev->name);
+       return 0;
+fail:
+       efx_ef100_rep_destroy_netdev(efv);
+       return rc;
+}
+
+void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv)
+{
+       struct net_device *rep_dev;
+
+       rep_dev = efv->net_dev;
+       if (!rep_dev)
+               return;
+       netif_dbg(efx, drv, rep_dev, "Removing VF representor\n");
+       unregister_netdev(rep_dev);
+       efx_ef100_rep_destroy_netdev(efv);
+}
+
+void efx_ef100_fini_vfreps(struct efx_nic *efx)
+{
+       struct ef100_nic_data *nic_data = efx->nic_data;
+       struct efx_rep *efv, *next;
+
+       if (!nic_data->grp_mae)
+               return;
+
+       list_for_each_entry_safe(efv, next, &efx->vf_reps, list)
+               efx_ef100_vfrep_destroy(efx, efv);
+}
diff --git a/drivers/net/ethernet/sfc/ef100_rep.h b/drivers/net/ethernet/sfc/ef100_rep.h
new file mode 100644 (file)
index 0000000..7d85811
--- /dev/null
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2019 Solarflare Communications Inc.
+ * Copyright 2020-2022 Xilinx Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+/* Handling for ef100 representor netdevs */
+#ifndef EF100_REP_H
+#define EF100_REP_H
+
+#include "net_driver.h"
+
+/**
+ * struct efx_rep - Private data for an Efx representor
+ *
+ * @parent: the efx PF which manages this representor
+ * @net_dev: representor netdevice
+ * @msg_enable: log message enable flags
+ * @list: entry on efx->vf_reps
+ */
+struct efx_rep {
+       struct efx_nic *parent;
+       struct net_device *net_dev;
+       u32 msg_enable;
+       struct list_head list;
+};
+
+int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i);
+void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv);
+void efx_ef100_fini_vfreps(struct efx_nic *efx);
+
+#endif /* EF100_REP_H */
index 6645781..94bdbfc 100644 (file)
 
 #include "ef100_sriov.h"
 #include "ef100_nic.h"
+#include "ef100_rep.h"
 
 static int efx_ef100_pci_sriov_enable(struct efx_nic *efx, int num_vfs)
 {
+       struct ef100_nic_data *nic_data = efx->nic_data;
        struct pci_dev *dev = efx->pci_dev;
-       int rc;
+       struct efx_rep *efv, *next;
+       int rc, i;
 
        efx->vf_count = num_vfs;
        rc = pci_enable_sriov(dev, num_vfs);
        if (rc)
-               goto fail;
+               goto fail1;
 
+       if (!nic_data->grp_mae)
+               return 0;
+
+       for (i = 0; i < num_vfs; i++) {
+               rc = efx_ef100_vfrep_create(efx, i);
+               if (rc)
+                       goto fail2;
+       }
        return 0;
 
-fail:
+fail2:
+       list_for_each_entry_safe(efv, next, &efx->vf_reps, list)
+               efx_ef100_vfrep_destroy(efx, efv);
+       pci_disable_sriov(dev);
+fail1:
        netif_err(efx, probe, efx->net_dev, "Failed to enable SRIOV VFs\n");
        efx->vf_count = 0;
        return rc;
 }
 
-int efx_ef100_pci_sriov_disable(struct efx_nic *efx)
+int efx_ef100_pci_sriov_disable(struct efx_nic *efx, bool force)
 {
        struct pci_dev *dev = efx->pci_dev;
        unsigned int vfs_assigned;
 
        vfs_assigned = pci_vfs_assigned(dev);
-       if (vfs_assigned) {
+       if (vfs_assigned && !force) {
                netif_info(efx, drv, efx->net_dev, "VFs are assigned to guests; "
                           "please detach them before disabling SR-IOV\n");
                return -EBUSY;
        }
 
-       pci_disable_sriov(dev);
-
+       efx_ef100_fini_vfreps(efx);
+       if (!vfs_assigned)
+               pci_disable_sriov(dev);
        return 0;
 }
 
 int efx_ef100_sriov_configure(struct efx_nic *efx, int num_vfs)
 {
        if (num_vfs == 0)
-               return efx_ef100_pci_sriov_disable(efx);
+               return efx_ef100_pci_sriov_disable(efx, false);
        else
                return efx_ef100_pci_sriov_enable(efx, num_vfs);
 }
index c48fccd..8ffdf46 100644 (file)
@@ -11,4 +11,4 @@
 #include "net_driver.h"
 
 int efx_ef100_sriov_configure(struct efx_nic *efx, int num_vfs);
-int efx_ef100_pci_sriov_disable(struct efx_nic *efx);
+int efx_ef100_pci_sriov_disable(struct efx_nic *efx, bool force);
index 56eb717..fb6b66b 100644 (file)
@@ -1021,6 +1021,8 @@ int efx_init_struct(struct efx_nic *efx, struct pci_dev *pci_dev)
        efx->rps_hash_table = kcalloc(EFX_ARFS_HASH_TABLE_SIZE,
                                      sizeof(*efx->rps_hash_table), GFP_KERNEL);
 #endif
+       spin_lock_init(&efx->vf_reps_lock);
+       INIT_LIST_HEAD(&efx->vf_reps);
        INIT_WORK(&efx->mac_work, efx_mac_work);
        init_waitqueue_head(&efx->flush_wq);
 
index 2228c88..037cfa1 100644 (file)
@@ -966,6 +966,8 @@ enum efx_xdp_tx_queues_mode {
  * @vf_count: Number of VFs intended to be enabled.
  * @vf_init_count: Number of VFs that have been fully initialised.
  * @vi_scale: log2 number of vnics per VF.
+ * @vf_reps_lock: Protects vf_reps list
+ * @vf_reps: local VF reps
  * @ptp_data: PTP state data
  * @ptp_warned: has this NIC seen and warned about unexpected PTP events?
  * @vpd_sn: Serial number read from VPD
@@ -1145,6 +1147,8 @@ struct efx_nic {
        unsigned vf_init_count;
        unsigned vi_scale;
 #endif
+       spinlock_t vf_reps_lock;
+       struct list_head vf_reps;
 
        struct efx_ptp_data *ptp_data;
        bool ptp_warned;