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 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 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