[PATCH net-next v4 05/14] sfc: implement init and fini functions for vDPA personality

Gautam Dawar
2023-04-07T08:12:39Z

When the bar_config for a PCIe function is changed from
EF100 to vDPA or vice-versa, corresponding EF100/vDPA fini/init
functions are invoked.
Also, because of the fact that a vDPA device doesn't have an
associated net device i.e. efx->net_dev is NULL, the code in
efx_mcdi_filter_table_probe() has been re-structured to have
the common code for both EF100 and vDPA personalities first
and then return early for vDPA case (before efx->net_dev is
accessed for EF100 personality).

Signed-off-by: Gautam Dawar <gautam.dawar@amd.com>
---
drivers/net/ethernet/sfc/Makefile | 2 +-
drivers/net/ethernet/sfc/ef100_nic.c | 7 ++-
drivers/net/ethernet/sfc/ef100_vdpa.c | 57 +++++++++++++++++++++++++
drivers/net/ethernet/sfc/ef100_vdpa.h | 2 +
drivers/net/ethernet/sfc/mcdi_filters.c | 51 ++++++++++++----------
drivers/net/ethernet/sfc/net_driver.h | 1 +
6 files changed, 95 insertions(+), 25 deletions(-)
create mode 100644 drivers/net/ethernet/sfc/ef100_vdpa.c

diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
index fb94fe3a9dfc..3a2bb98d1c3f 100644
--- a/drivers/net/ethernet/sfc/Makefile
+++ b/drivers/net/ethernet/sfc/Makefile
@@ -12,7 +12,7 @@ sfc-$(CONFIG_SFC_MTD) += mtd.o
sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \
mae.o tc.o tc_bindings.o tc_counters.o

-sfc-$(CONFIG_SFC_VDPA) += mcdi_vdpa.o
+sfc-$(CONFIG_SFC_VDPA) += mcdi_vdpa.o ef100_vdpa.o
obj-$(CONFIG_SFC) += sfc.o

obj-$(CONFIG_SFC_FALCON) += falcon/
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index e6e67a50610f..bc010b504b4a 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -28,6 +28,9 @@
#include "tc.h"
#include "mae.h"
#include "rx_common.h"
+#ifdef CONFIG_SFC_VDPA
+#include "ef100_vdpa.h"
+#endif

#define EF100_MAX_VIS 4096
#define EF100_NUM_MCDI_BUFFERS 1
@@ -786,8 +789,8 @@ static const struct ef100_bar_config_ops bar_config_ops[] = {
},
#ifdef CONFIG_SFC_VDPA
[EF100_BAR_CONFIG_VDPA] = {
- .init = NULL,
- .fini = NULL
+ .init = ef100_vdpa_init,
+ .fini = ef100_vdpa_fini
},
#endif
[EF100_BAR_CONFIG_NONE] = {
diff --git a/drivers/net/ethernet/sfc/ef100_vdpa.c b/drivers/net/ethernet/sfc/ef100_vdpa.c
new file mode 100644
index 000000000000..268c973f7376
--- /dev/null
+++ b/drivers/net/ethernet/sfc/ef100_vdpa.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Driver for AMD network controllers and boards
+ * Copyright(C) 2023, Advanced Micro Devices, 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 <linux/err.h>
+#include <linux/vdpa.h>
+#include <linux/virtio_net.h>
+#include "ef100_vdpa.h"
+#include "mcdi_vdpa.h"
+#include "mcdi_filters.h"
+#include "ef100_netdev.h"
+
+int ef100_vdpa_init(struct efx_probe_data *probe_data)
+{
+ struct efx_nic *efx = &probe_data->efx;
+ int rc;
+
+ if (efx->state != STATE_PROBED) {
+ pci_err(efx->pci_dev, "Invalid efx state %u", efx->state);
+ return -EBUSY;
+ }
+
+ efx->state = STATE_VDPA;
+ down_write(&efx->filter_sem);
+ rc = ef100_filter_table_probe(efx);
+ up_write(&efx->filter_sem);
+ if (rc) {
+ pci_err(efx->pci_dev, "filter probe failed, err: %d\n", rc);
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ efx->state = STATE_PROBED;
+ return rc;
+}
+
+void ef100_vdpa_fini(struct efx_probe_data *probe_data)
+{
+ struct efx_nic *efx = &probe_data->efx;
+
+ if (efx->state != STATE_VDPA && efx->state != STATE_DISABLED) {
+ pci_err(efx->pci_dev, "Invalid efx state %u", efx->state);
+ return;
+ }
+
+ efx->state = STATE_PROBED;
+ down_write(&efx->filter_sem);
+ efx_mcdi_filter_table_remove(efx);
+ up_write(&efx->filter_sem);
+}
diff --git a/drivers/net/ethernet/sfc/ef100_vdpa.h b/drivers/net/ethernet/sfc/ef100_vdpa.h
index 90062fd8a25d..ccc5eb0a2a84 100644
--- a/drivers/net/ethernet/sfc/ef100_vdpa.h
+++ b/drivers/net/ethernet/sfc/ef100_vdpa.h
@@ -27,5 +27,7 @@ enum ef100_vdpa_vq_type {
EF100_VDPA_VQ_NTYPES
};

+int ef100_vdpa_init(struct efx_probe_data *probe_data);
+void ef100_vdpa_fini(struct efx_probe_data *probe_data);
#endif /* CONFIG_SFC_VDPA */
#endif /* __EF100_VDPA_H__ */
diff --git a/drivers/net/ethernet/sfc/mcdi_filters.c b/drivers/net/ethernet/sfc/mcdi_filters.c
index 4ff6586116ee..fde2b5b50ade 100644
--- a/drivers/net/ethernet/sfc/mcdi_filters.c
+++ b/drivers/net/ethernet/sfc/mcdi_filters.c
@@ -1282,14 +1282,14 @@ efx_mcdi_filter_table_probe_matches(struct efx_nic *efx,
pd_match_pri);
rc = efx_mcdi_filter_match_flags_from_mcdi(encap, mcdi_flags);
if (rc < 0) {
- netif_dbg(efx, probe, efx->net_dev,
- "%s: fw flags %#x pri %u not supported in driver\n",
- __func__, mcdi_flags, pd_match_pri);
+ pci_dbg(efx->pci_dev,
+ "%s: fw flags %#x pri %u not supported in driver\n",
+ __func__, mcdi_flags, pd_match_pri);
} else {
- netif_dbg(efx, probe, efx->net_dev,
- "%s: fw flags %#x pri %u supported as driver flags %#x pri %u\n",
- __func__, mcdi_flags, pd_match_pri,
- rc, table->rx_match_count);
+ pci_dbg(efx->pci_dev,
+ "%s: fw flags %#x pri %u supported as driver flags %#x pri %u\n",
+ __func__, mcdi_flags, pd_match_pri,
+ rc, table->rx_match_count);
table->rx_match_mcdi_flags[table->rx_match_count] = mcdi_flags;
table->rx_match_count++;
}
@@ -1318,11 +1318,26 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining)
table->rx_match_count = 0;
rc = efx_mcdi_filter_table_probe_matches(efx, table, false);
if (rc)
- goto fail;
+ goto fail1;
+ table->entry = vzalloc(array_size(EFX_MCDI_FILTER_TBL_ROWS,
+ sizeof(*table->entry)));
+ if (!table->entry) {
+ rc = -ENOMEM;
+ goto fail1;
+ }
+
+ table->mc_promisc_last = false;
+ INIT_LIST_HEAD(&table->vlan_list);
+ init_rwsem(&table->lock);
+
+ efx->filter_state = table;
+ if (efx->state == STATE_VDPA)
+ return 0;
+
if (efx_has_cap(efx, VXLAN_NVGRE))
rc = efx_mcdi_filter_table_probe_matches(efx, table, true);
if (rc)
- goto fail;
+ goto fail2;
if ((efx_supported_features(efx) & NETIF_F_HW_VLAN_CTAG_FILTER) &&
!(efx_mcdi_filter_match_supported(table, false,
(EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC)) &&
@@ -1335,24 +1350,16 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining)
net_dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
}

- table->entry = vzalloc(array_size(EFX_MCDI_FILTER_TBL_ROWS,
- sizeof(*table->entry)));
- if (!table->entry) {
- rc = -ENOMEM;
- goto fail;
- }
-
- table->mc_promisc_last = false;
table->vlan_filter =
!!(efx->net_dev->features & NETIF_F_HW_VLAN_CTAG_FILTER);
- INIT_LIST_HEAD(&table->vlan_list);
- init_rwsem(&table->lock);
-
- efx->filter_state = table;

return 0;
-fail:
+
+fail2:
+ vfree(table->entry);
+fail1:
kfree(table);
+ efx->filter_state = NULL;
return rc;
}

diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index fcd51d3992fa..3dc9eae5a81d 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -646,6 +646,7 @@ enum nic_state {
STATE_NET_DOWN, /* netdev registered */
STATE_NET_UP, /* ready for traffic */
STATE_DISABLED, /* device disabled due to hardware errors */
+ STATE_VDPA, /* device bar_config changed to vDPA */

STATE_RECOVERY = 0x100,/* recovering from PCI error */
STATE_FROZEN = 0x200, /* frozen by power management */
--
2.30.1