--- v20
+++ v18
@@ -1,239 +1,209 @@
From: Alejandro Lucero <alucerop@amd.com>
-Add CXL initialization based on new CXL API for accel drivers and make
-it dependent on kernel CXL configuration.
+Type3 relies on mailbox CXL_MBOX_OP_IDENTIFY command for initializing
+memdev state params which end up being used for DPA initialization.
+
+Allow a Type2 driver to initialize DPA simply by giving the size of its
+volatile hardware partition.
+
+Move related functions to memdev.
+
+Add sfc driver as the client.
Signed-off-by: Alejandro Lucero <alucerop@amd.com>
-Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
-Acked-by: Edward Cree <ecree.xilinx@gmail.com>
-Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
-Reviewed-by: Dave Jiang <dave.jiang@intel.com>
---
- drivers/net/ethernet/sfc/Kconfig | 9 +++++
- drivers/net/ethernet/sfc/Makefile | 1 +
- drivers/net/ethernet/sfc/efx.c | 15 ++++++-
- drivers/net/ethernet/sfc/efx_cxl.c | 56 +++++++++++++++++++++++++++
- drivers/net/ethernet/sfc/efx_cxl.h | 40 +++++++++++++++++++
- drivers/net/ethernet/sfc/net_driver.h | 10 +++++
- 6 files changed, 130 insertions(+), 1 deletion(-)
- create mode 100644 drivers/net/ethernet/sfc/efx_cxl.c
- create mode 100644 drivers/net/ethernet/sfc/efx_cxl.h
-
-diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
-index c4c43434f314..979f2801e2a8 100644
---- a/drivers/net/ethernet/sfc/Kconfig
-+++ b/drivers/net/ethernet/sfc/Kconfig
-@@ -66,6 +66,15 @@ config SFC_MCDI_LOGGING
- Driver-Interface) commands and responses, allowing debugging of
- driver/firmware interaction. The tracing is actually enabled by
- a sysfs file 'mcdi_logging' under the PCI device.
-+config SFC_CXL
-+ bool "Solarflare SFC9100-family CXL support"
-+ depends on SFC && CXL_BUS >= SFC
-+ default SFC
-+ help
-+ This enables SFC CXL support if the kernel is configuring CXL for
-+ using CTPIO with CXL.mem. The SFC device with CXL support and
-+ with a CXL-aware firmware can be used for minimizing latencies
-+ when sending through CTPIO.
-
- source "drivers/net/ethernet/sfc/falcon/Kconfig"
- source "drivers/net/ethernet/sfc/siena/Kconfig"
-diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
-index d99039ec468d..bb0f1891cde6 100644
---- a/drivers/net/ethernet/sfc/Makefile
-+++ b/drivers/net/ethernet/sfc/Makefile
-@@ -13,6 +13,7 @@ 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 \
- tc_encap_actions.o tc_conntrack.o
-
-+sfc-$(CONFIG_SFC_CXL) += efx_cxl.o
- obj-$(CONFIG_SFC) += sfc.o
-
- obj-$(CONFIG_SFC_FALCON) += falcon/
-diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
-index 112e55b98ed3..537668278375 100644
---- a/drivers/net/ethernet/sfc/efx.c
-+++ b/drivers/net/ethernet/sfc/efx.c
-@@ -34,6 +34,7 @@
- #include "selftest.h"
- #include "sriov.h"
- #include "efx_devlink.h"
-+#include "efx_cxl.h"
-
- #include "mcdi_port_common.h"
- #include "mcdi_pcol.h"
-@@ -981,12 +982,15 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
- efx_pci_remove_main(efx);
-
- efx_fini_io(efx);
-+
-+ probe_data = container_of(efx, struct efx_probe_data, efx);
-+ efx_cxl_exit(probe_data);
-+
- pci_dbg(efx->pci_dev, "shutdown successful\n");
-
- efx_fini_devlink_and_unlock(efx);
- efx_fini_struct(efx);
- free_netdev(efx->net_dev);
-- probe_data = container_of(efx, struct efx_probe_data, efx);
- kfree(probe_data);
- };
-
-@@ -1190,6 +1194,15 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
- if (rc)
- goto fail2;
-
-+ /* A successful cxl initialization implies a CXL region created to be
-+ * used for PIO buffers. If there is no CXL support, or initialization
-+ * fails, efx_cxl_pio_initialised will be false and legacy PIO buffers
-+ * defined at specific PCI BAR regions will be used.
-+ */
-+ rc = efx_cxl_init(probe_data);
-+ if (rc)
-+ pci_err(pci_dev, "CXL initialization failed with error %d\n", rc);
-+
- rc = efx_pci_probe_post_io(efx);
- if (rc) {
- /* On failure, retry once immediately.
-diff --git a/drivers/net/ethernet/sfc/efx_cxl.c b/drivers/net/ethernet/sfc/efx_cxl.c
-new file mode 100644
-index 000000000000..8e0481d8dced
---- /dev/null
-+++ b/drivers/net/ethernet/sfc/efx_cxl.c
-@@ -0,0 +1,56 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/****************************************************************************
-+ *
-+ * Driver for AMD network controllers and boards
-+ * Copyright (C) 2025, Advanced Micro Devices, Inc.
-+ */
-+
-+#include <linux/pci.h>
-+
-+#include "net_driver.h"
-+#include "efx_cxl.h"
-+
-+#define EFX_CTPIO_BUFFER_SIZE SZ_256M
-+
-+int efx_cxl_init(struct efx_probe_data *probe_data)
+ drivers/cxl/core/core.h | 2 +
+ drivers/cxl/core/mbox.c | 51 +----------------------
+ drivers/cxl/core/memdev.c | 66 ++++++++++++++++++++++++++++++
+ drivers/net/ethernet/sfc/efx_cxl.c | 4 ++
+ include/cxl/cxl.h | 1 +
+ 5 files changed, 74 insertions(+), 50 deletions(-)
+
+diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
+index d96213c02fd6..c4dddbec5d6e 100644
+--- a/drivers/cxl/core/core.h
++++ b/drivers/cxl/core/core.h
+@@ -90,6 +90,8 @@ void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr,
+ struct dentry *cxl_debugfs_create_dir(const char *dir);
+ int cxl_dpa_set_part(struct cxl_endpoint_decoder *cxled,
+ enum cxl_partition_mode mode);
++struct cxl_memdev_state;
++int cxl_mem_get_partition_info(struct cxl_memdev_state *mds);
+ int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, u64 size);
+ int cxl_dpa_free(struct cxl_endpoint_decoder *cxled);
+ resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled);
+diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
+index bee84d0101d1..d57a0c2d39fb 100644
+--- a/drivers/cxl/core/mbox.c
++++ b/drivers/cxl/core/mbox.c
+@@ -1144,7 +1144,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, "CXL");
+ *
+ * See CXL @8.2.9.5.2.1 Get Partition Info
+ */
+-static int cxl_mem_get_partition_info(struct cxl_memdev_state *mds)
++int cxl_mem_get_partition_info(struct cxl_memdev_state *mds)
+ {
+ struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
+ struct cxl_mbox_get_partition_info pi;
+@@ -1300,55 +1300,6 @@ int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd)
+ return -EBUSY;
+ }
+
+-static void add_part(struct cxl_dpa_info *info, u64 start, u64 size, enum cxl_partition_mode mode)
+-{
+- int i = info->nr_partitions;
+-
+- if (size == 0)
+- return;
+-
+- info->part[i].range = (struct range) {
+- .start = start,
+- .end = start + size - 1,
+- };
+- info->part[i].mode = mode;
+- info->nr_partitions++;
+-}
+-
+-int cxl_mem_dpa_fetch(struct cxl_memdev_state *mds, struct cxl_dpa_info *info)
+-{
+- struct cxl_dev_state *cxlds = &mds->cxlds;
+- struct device *dev = cxlds->dev;
+- int rc;
+-
+- if (!cxlds->media_ready) {
+- info->size = 0;
+- return 0;
+- }
+-
+- info->size = mds->total_bytes;
+-
+- if (mds->partition_align_bytes == 0) {
+- add_part(info, 0, mds->volatile_only_bytes, CXL_PARTMODE_RAM);
+- add_part(info, mds->volatile_only_bytes,
+- mds->persistent_only_bytes, CXL_PARTMODE_PMEM);
+- return 0;
+- }
+-
+- rc = cxl_mem_get_partition_info(mds);
+- if (rc) {
+- dev_err(dev, "Failed to query partition information\n");
+- return rc;
+- }
+-
+- add_part(info, 0, mds->active_volatile_bytes, CXL_PARTMODE_RAM);
+- add_part(info, mds->active_volatile_bytes, mds->active_persistent_bytes,
+- CXL_PARTMODE_PMEM);
+-
+- return 0;
+-}
+-EXPORT_SYMBOL_NS_GPL(cxl_mem_dpa_fetch, "CXL");
+-
+ int cxl_get_dirty_count(struct cxl_memdev_state *mds, u32 *count)
+ {
+ struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
+diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
+index 97127d6067c4..d148a0c942aa 100644
+--- a/drivers/cxl/core/memdev.c
++++ b/drivers/cxl/core/memdev.c
+@@ -556,6 +556,72 @@ bool is_cxl_memdev(const struct device *dev)
+ }
+ EXPORT_SYMBOL_NS_GPL(is_cxl_memdev, "CXL");
+
++static void add_part(struct cxl_dpa_info *info, u64 start, u64 size, enum cxl_partition_mode mode)
+{
-+ struct efx_nic *efx = &probe_data->efx;
-+ struct pci_dev *pci_dev = efx->pci_dev;
-+ struct efx_cxl *cxl;
-+ u16 dvsec;
-+
-+ probe_data->cxl_pio_initialised = false;
-+
-+ /* Is the device configured with and using CXL? */
-+ if (!pcie_is_cxl(pci_dev))
-+ return 0;
-+
-+ dvsec = pci_find_dvsec_capability(pci_dev, PCI_VENDOR_ID_CXL,
-+ PCI_DVSEC_CXL_DEVICE);
-+ if (!dvsec) {
-+ pci_err(pci_dev, "CXL_DVSEC_PCIE_DEVICE capability not found\n");
++ int i = info->nr_partitions;
++
++ if (size == 0)
++ return;
++
++ info->part[i].range = (struct range) {
++ .start = start,
++ .end = start + size - 1,
++ };
++ info->part[i].mode = mode;
++ info->nr_partitions++;
++}
++
++int cxl_mem_dpa_fetch(struct cxl_memdev_state *mds, struct cxl_dpa_info *info)
++{
++ struct cxl_dev_state *cxlds = &mds->cxlds;
++ struct device *dev = cxlds->dev;
++ int rc;
++
++ if (!cxlds->media_ready) {
++ info->size = 0;
+ return 0;
+ }
+
-+ pci_dbg(pci_dev, "CXL_DVSEC_PCIE_DEVICE capability found\n");
-+
-+ /* Create a cxl_dev_state embedded in the cxl struct using cxl core api
-+ * specifying no mbox available.
-+ */
-+ cxl = devm_cxl_dev_state_create(&pci_dev->dev, CXL_DEVTYPE_DEVMEM,
-+ pci_dev->dev.id, dvsec, struct efx_cxl,
-+ cxlds, false);
-+
-+ if (!cxl)
-+ return -ENOMEM;
-+
-+ probe_data->cxl = cxl;
++ info->size = mds->total_bytes;
++
++ if (mds->partition_align_bytes == 0) {
++ add_part(info, 0, mds->volatile_only_bytes, CXL_PARTMODE_RAM);
++ add_part(info, mds->volatile_only_bytes,
++ mds->persistent_only_bytes, CXL_PARTMODE_PMEM);
++ return 0;
++ }
++
++ rc = cxl_mem_get_partition_info(mds);
++ if (rc) {
++ dev_err(dev, "Failed to query partition information\n");
++ return rc;
++ }
++
++ add_part(info, 0, mds->active_volatile_bytes, CXL_PARTMODE_RAM);
++ add_part(info, mds->active_volatile_bytes, mds->active_persistent_bytes,
++ CXL_PARTMODE_PMEM);
+
+ return 0;
+}
-+
-+void efx_cxl_exit(struct efx_probe_data *probe_data)
++EXPORT_SYMBOL_NS_GPL(cxl_mem_dpa_fetch, "CXL");
++
++/**
++ * cxl_set_capacity: initialize dpa by a driver without a mailbox.
++ *
++ * @cxlds: pointer to cxl_dev_state
++ * @capacity: device volatile memory size
++ */
++int cxl_set_capacity(struct cxl_dev_state *cxlds, u64 capacity)
+{
++ struct cxl_dpa_info range_info = {
++ .size = capacity,
++ };
++
++ add_part(&range_info, 0, capacity, CXL_PARTMODE_RAM);
++ return cxl_dpa_setup(cxlds, &range_info);
+}
-+
-+MODULE_IMPORT_NS("CXL");
-diff --git a/drivers/net/ethernet/sfc/efx_cxl.h b/drivers/net/ethernet/sfc/efx_cxl.h
-new file mode 100644
-index 000000000000..961639cef692
---- /dev/null
-+++ b/drivers/net/ethernet/sfc/efx_cxl.h
-@@ -0,0 +1,40 @@
-+/* SPDX-License-Identifier: GPL-2.0-only */
-+/****************************************************************************
-+ * Driver for AMD network controllers and boards
-+ * Copyright (C) 2025, 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.
-+ */
-+
-+#ifndef EFX_CXL_H
-+#define EFX_CXL_H
-+
-+#ifdef CONFIG_SFC_CXL
-+
-+#include <cxl/cxl.h>
-+
-+struct cxl_root_decoder;
-+struct cxl_port;
-+struct cxl_endpoint_decoder;
-+struct cxl_region;
-+struct efx_probe_data;
-+
-+struct efx_cxl {
-+ struct cxl_dev_state cxlds;
-+ struct cxl_memdev *cxlmd;
-+ struct cxl_root_decoder *cxlrd;
-+ struct cxl_port *endpoint;
-+ struct cxl_endpoint_decoder *cxled;
-+ struct cxl_region *efx_region;
-+ void __iomem *ctpio_cxl;
-+};
-+
-+int efx_cxl_init(struct efx_probe_data *probe_data);
-+void efx_cxl_exit(struct efx_probe_data *probe_data);
-+#else
-+static inline int efx_cxl_init(struct efx_probe_data *probe_data) { return 0; }
-+static inline void efx_cxl_exit(struct efx_probe_data *probe_data) {}
-+#endif
-+#endif
-diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
-index b98c259f672d..3964b2c56609 100644
---- a/drivers/net/ethernet/sfc/net_driver.h
-+++ b/drivers/net/ethernet/sfc/net_driver.h
-@@ -1197,14 +1197,24 @@ struct efx_nic {
- atomic_t n_rx_noskb_drops;
- };
-
-+#ifdef CONFIG_SFC_CXL
-+struct efx_cxl;
-+#endif
++EXPORT_SYMBOL_NS_GPL(cxl_set_capacity, "CXL");
+
/**
- * struct efx_probe_data - State after hardware probe
- * @pci_dev: The PCI device
- * @efx: Efx NIC details
-+ * @cxl: details of related cxl objects
-+ * @cxl_pio_initialised: cxl initialization outcome.
- */
- struct efx_probe_data {
- struct pci_dev *pci_dev;
- struct efx_nic efx;
-+#ifdef CONFIG_SFC_CXL
-+ struct efx_cxl *cxl;
-+ bool cxl_pio_initialised;
-+#endif
- };
-
- static inline struct efx_nic *efx_netdev_priv(struct net_device *dev)
+ * set_exclusive_cxl_commands() - atomically disable user cxl commands
+ * @mds: The device state to operate on
+diff --git a/drivers/net/ethernet/sfc/efx_cxl.c b/drivers/net/ethernet/sfc/efx_cxl.c
+index cdfbe546d8d8..651d26aa68dc 100644
+--- a/drivers/net/ethernet/sfc/efx_cxl.c
++++ b/drivers/net/ethernet/sfc/efx_cxl.c
+@@ -78,6 +78,10 @@ int efx_cxl_init(struct efx_probe_data *probe_data)
+ */
+ cxl->cxlds.media_ready = true;
+
++ if (cxl_set_capacity(&cxl->cxlds, EFX_CTPIO_BUFFER_SIZE))
++ return dev_err_probe(&pci_dev->dev, -ENODEV,
++ "dpa capacity setup failed\n");
++
+ probe_data->cxl = cxl;
+
+ return 0;
+diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h
+index 3b9c8cb187a3..88dea6ac3769 100644
+--- a/include/cxl/cxl.h
++++ b/include/cxl/cxl.h
+@@ -243,4 +243,5 @@ struct cxl_dev_state *_devm_cxl_dev_state_create(struct device *dev,
+ int cxl_map_component_regs(const struct cxl_register_map *map,
+ struct cxl_component_regs *regs,
+ unsigned long map_mask);
++int cxl_set_capacity(struct cxl_dev_state *cxlds, u64 capacity);
+ #endif /* __CXL_CXL_H__ */
--
2.34.1