xref: /linux/drivers/net/ethernet/sfc/efx_cxl.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /****************************************************************************
3  *
4  * Driver for AMD network controllers and boards
5  * Copyright (C) 2025, Advanced Micro Devices, Inc.
6  */
7 
8 #include <linux/pci.h>
9 
10 #include <cxl/cxl.h>
11 #include <cxl/pci.h>
12 #include "net_driver.h"
13 #include "efx_cxl.h"
14 
15 #define EFX_CTPIO_BUFFER_SIZE	SZ_256M
16 
efx_cxl_init(struct efx_probe_data * probe_data)17 int efx_cxl_init(struct efx_probe_data *probe_data)
18 {
19 	struct efx_nic *efx = &probe_data->efx;
20 	struct pci_dev *pci_dev = efx->pci_dev;
21 	struct range cxl_pio_range;
22 	struct efx_cxl *cxl;
23 	u16 dvsec;
24 	int rc;
25 
26 	/* Is the device configured with and using CXL? */
27 	if (!pcie_is_cxl(pci_dev))
28 		return 0;
29 
30 	dvsec = pci_find_dvsec_capability(pci_dev, PCI_VENDOR_ID_CXL,
31 					  PCI_DVSEC_CXL_DEVICE);
32 	if (!dvsec) {
33 		pci_info(pci_dev, "CXL_DVSEC_PCIE_DEVICE capability not found\n");
34 		return 0;
35 	}
36 
37 	pci_dbg(pci_dev, "CXL_DVSEC_PCIE_DEVICE capability found\n");
38 
39 	/* Create a cxl_dev_state embedded in the cxl struct using cxl core api
40 	 * specifying no mbox available.
41 	 */
42 	cxl = devm_cxl_dev_state_create(&pci_dev->dev, CXL_DEVTYPE_DEVMEM,
43 					pci_get_dsn(pci_dev), dvsec,
44 					struct efx_cxl, cxlds, false);
45 
46 	if (!cxl)
47 		return -ENOMEM;
48 
49 	rc = cxl_pci_setup_regs(pci_dev, CXL_REGLOC_RBI_COMPONENT,
50 				&cxl->cxlds.reg_map);
51 	if (rc) {
52 		pci_err(pci_dev, "No component registers\n");
53 		return rc;
54 	}
55 
56 	if (!cxl->cxlds.reg_map.component_map.hdm_decoder.valid) {
57 		pci_err(pci_dev, "Expected HDM component register not found\n");
58 		return -ENODEV;
59 	}
60 
61 	if (!cxl->cxlds.reg_map.component_map.ras.valid) {
62 		pci_err(pci_dev, "Expected RAS component register not found\n");
63 		return -ENODEV;
64 	}
65 
66 	/* Set media ready explicitly as there are neither mailbox for checking
67 	 * this state nor the CXL register involved, both not mandatory for
68 	 * type2.
69 	 */
70 	cxl->cxlds.media_ready = true;
71 
72 	if (cxl_set_capacity(&cxl->cxlds, EFX_CTPIO_BUFFER_SIZE)) {
73 		pci_err(pci_dev, "dpa capacity setup failed\n");
74 		return -ENODEV;
75 	}
76 
77 	cxl->cxlmd = devm_cxl_probe_mem(&cxl->cxlds, &cxl_pio_range);
78 	if (IS_ERR(cxl->cxlmd)) {
79 		pci_err(pci_dev, "CXL accel memdev creation failed\n");
80 		return PTR_ERR(cxl->cxlmd);
81 	}
82 
83 	cxl->ctpio_cxl = ioremap_wc(cxl_pio_range.start,
84 				    range_len(&cxl_pio_range));
85 	if (!cxl->ctpio_cxl) {
86 		pci_err(pci_dev, "CXL ioremap region (%pra) failed\n",
87 			&cxl_pio_range);
88 		return -ENOMEM;
89 	}
90 
91 	probe_data->cxl_pio_initialised = true;
92 	probe_data->cxl = cxl;
93 
94 	return 0;
95 }
96 
efx_cxl_exit(struct efx_probe_data * probe_data)97 void efx_cxl_exit(struct efx_probe_data *probe_data)
98 {
99 	if (!probe_data->cxl)
100 		return;
101 
102 	iounmap(probe_data->cxl->ctpio_cxl);
103 }
104 
105 MODULE_IMPORT_NS("CXL");
106