1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright(c) 2021 Intel Corporation. All rights reserved. */ 3 4 #include <linux/platform_device.h> 5 #include <linux/device.h> 6 #include <linux/acpi.h> 7 #include <linux/pci.h> 8 #include <cxl.h> 9 #include "test/mock.h" 10 11 struct acpi_device *to_cxl_host_bridge(struct device *host, struct device *dev) 12 { 13 int index; 14 struct acpi_device *adev, *found = NULL; 15 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 16 17 if (ops && ops->is_mock_bridge(dev)) { 18 found = ACPI_COMPANION(dev); 19 goto out; 20 } 21 22 if (dev->bus == &platform_bus_type) 23 goto out; 24 25 adev = to_acpi_device(dev); 26 if (!acpi_pci_find_root(adev->handle)) 27 goto out; 28 29 if (strcmp(acpi_device_hid(adev), "ACPI0016") == 0) { 30 found = adev; 31 dev_dbg(host, "found host bridge %s\n", dev_name(&adev->dev)); 32 } 33 out: 34 put_cxl_mock_ops(index); 35 return found; 36 } 37 38 static int match_add_root_port(struct pci_dev *pdev, void *data) 39 { 40 struct cxl_walk_context *ctx = data; 41 struct pci_bus *root_bus = ctx->root; 42 struct cxl_port *port = ctx->port; 43 int type = pci_pcie_type(pdev); 44 struct device *dev = ctx->dev; 45 u32 lnkcap, port_num; 46 int rc; 47 48 if (pdev->bus != root_bus) 49 return 0; 50 if (!pci_is_pcie(pdev)) 51 return 0; 52 if (type != PCI_EXP_TYPE_ROOT_PORT) 53 return 0; 54 if (pci_read_config_dword(pdev, pci_pcie_cap(pdev) + PCI_EXP_LNKCAP, 55 &lnkcap) != PCIBIOS_SUCCESSFUL) 56 return 0; 57 58 /* TODO walk DVSEC to find component register base */ 59 port_num = FIELD_GET(PCI_EXP_LNKCAP_PN, lnkcap); 60 rc = cxl_add_dport(port, &pdev->dev, port_num, CXL_RESOURCE_NONE); 61 if (rc) { 62 dev_err(dev, "failed to add dport: %s (%d)\n", 63 dev_name(&pdev->dev), rc); 64 ctx->error = rc; 65 return rc; 66 } 67 ctx->count++; 68 69 dev_dbg(dev, "add dport%d: %s\n", port_num, dev_name(&pdev->dev)); 70 71 return 0; 72 } 73 74 static int mock_add_root_port(struct platform_device *pdev, void *data) 75 { 76 struct cxl_walk_context *ctx = data; 77 struct cxl_port *port = ctx->port; 78 struct device *dev = ctx->dev; 79 int rc; 80 81 rc = cxl_add_dport(port, &pdev->dev, pdev->id, CXL_RESOURCE_NONE); 82 if (rc) { 83 dev_err(dev, "failed to add dport: %s (%d)\n", 84 dev_name(&pdev->dev), rc); 85 ctx->error = rc; 86 return rc; 87 } 88 ctx->count++; 89 90 dev_dbg(dev, "add dport%d: %s\n", pdev->id, dev_name(&pdev->dev)); 91 92 return 0; 93 } 94 95 int match_add_root_ports(struct pci_dev *dev, void *data) 96 { 97 int index, rc; 98 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 99 struct platform_device *pdev = (struct platform_device *) dev; 100 101 if (ops && ops->is_mock_port(pdev)) 102 rc = mock_add_root_port(pdev, data); 103 else 104 rc = match_add_root_port(dev, data); 105 106 put_cxl_mock_ops(index); 107 108 return rc; 109 } 110