1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2024-2025, Ventana Micro Systems Inc 4 * Author: Sunil V L <sunilvl@ventanamicro.com> 5 * 6 */ 7 8 #define pr_fmt(fmt) "ACPI: RIMT: " fmt 9 10 #include <linux/acpi.h> 11 #include <linux/acpi_rimt.h> 12 #include <linux/iommu.h> 13 #include <linux/list.h> 14 #include <linux/pci.h> 15 #include <linux/platform_device.h> 16 #include "init.h" 17 18 struct rimt_fwnode { 19 struct list_head list; 20 struct acpi_rimt_node *rimt_node; 21 struct fwnode_handle *fwnode; 22 }; 23 24 static LIST_HEAD(rimt_fwnode_list); 25 static DEFINE_SPINLOCK(rimt_fwnode_lock); 26 27 #define RIMT_TYPE_MASK(type) (1 << (type)) 28 #define RIMT_IOMMU_TYPE BIT(0) 29 30 /* Root pointer to the mapped RIMT table */ 31 static struct acpi_table_header *rimt_table; 32 33 /** 34 * rimt_set_fwnode() - Create rimt_fwnode and use it to register 35 * iommu data in the rimt_fwnode_list 36 * 37 * @rimt_node: RIMT table node associated with the IOMMU 38 * @fwnode: fwnode associated with the RIMT node 39 * 40 * Returns: 0 on success 41 * <0 on failure 42 */ 43 static int rimt_set_fwnode(struct acpi_rimt_node *rimt_node, 44 struct fwnode_handle *fwnode) 45 { 46 struct rimt_fwnode *np; 47 48 np = kzalloc_obj(*np, GFP_ATOMIC); 49 50 if (WARN_ON(!np)) 51 return -ENOMEM; 52 53 INIT_LIST_HEAD(&np->list); 54 np->rimt_node = rimt_node; 55 np->fwnode = fwnode; 56 57 spin_lock(&rimt_fwnode_lock); 58 list_add_tail(&np->list, &rimt_fwnode_list); 59 spin_unlock(&rimt_fwnode_lock); 60 61 return 0; 62 } 63 64 static acpi_status rimt_match_node_callback(struct acpi_rimt_node *node, 65 void *context) 66 { 67 acpi_status status = AE_NOT_FOUND; 68 struct device *dev = context; 69 70 if (node->type == ACPI_RIMT_NODE_TYPE_IOMMU) { 71 struct acpi_rimt_iommu *iommu_node = (struct acpi_rimt_iommu *)&node->node_data; 72 73 if (dev_is_pci(dev)) { 74 struct pci_dev *pdev; 75 u16 bdf; 76 77 pdev = to_pci_dev(dev); 78 bdf = PCI_DEVID(pdev->bus->number, pdev->devfn); 79 if ((pci_domain_nr(pdev->bus) == iommu_node->pcie_segment_number) && 80 bdf == iommu_node->pcie_bdf) { 81 status = AE_OK; 82 } else { 83 status = AE_NOT_FOUND; 84 } 85 } else { 86 struct platform_device *pdev = to_platform_device(dev); 87 struct resource *res; 88 89 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 90 if (res && res->start == iommu_node->base_address) 91 status = AE_OK; 92 else 93 status = AE_NOT_FOUND; 94 } 95 } else if (node->type == ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX) { 96 struct acpi_rimt_pcie_rc *pci_rc; 97 struct pci_bus *bus; 98 99 bus = to_pci_bus(dev); 100 pci_rc = (struct acpi_rimt_pcie_rc *)node->node_data; 101 102 /* 103 * It is assumed that PCI segment numbers maps one-to-one 104 * with root complexes. Each segment number can represent only 105 * one root complex. 106 */ 107 status = pci_rc->pcie_segment_number == pci_domain_nr(bus) ? 108 AE_OK : AE_NOT_FOUND; 109 } else if (node->type == ACPI_RIMT_NODE_TYPE_PLAT_DEVICE) { 110 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; 111 struct acpi_rimt_platform_device *ncomp; 112 struct device *plat_dev = dev; 113 struct acpi_device *adev; 114 115 /* 116 * Walk the device tree to find a device with an 117 * ACPI companion; there is no point in scanning 118 * RIMT for a device matching a platform device if 119 * the device does not have an ACPI companion to 120 * start with. 121 */ 122 do { 123 adev = ACPI_COMPANION(plat_dev); 124 if (adev) 125 break; 126 127 plat_dev = plat_dev->parent; 128 } while (plat_dev); 129 130 if (!adev) 131 return status; 132 133 status = acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &buf); 134 if (ACPI_FAILURE(status)) { 135 dev_warn(plat_dev, "Can't get device full path name\n"); 136 return status; 137 } 138 139 ncomp = (struct acpi_rimt_platform_device *)node->node_data; 140 status = !strcmp(ncomp->device_name, buf.pointer) ? 141 AE_OK : AE_NOT_FOUND; 142 acpi_os_free(buf.pointer); 143 } 144 145 return status; 146 } 147 148 static struct acpi_rimt_node *rimt_scan_node(enum acpi_rimt_node_type type, 149 void *context) 150 { 151 struct acpi_rimt_node *rimt_node, *rimt_end; 152 struct acpi_table_rimt *rimt; 153 int i; 154 155 if (!rimt_table) 156 return NULL; 157 158 /* Get the first RIMT node */ 159 rimt = (struct acpi_table_rimt *)rimt_table; 160 rimt_node = ACPI_ADD_PTR(struct acpi_rimt_node, rimt, 161 rimt->node_offset); 162 rimt_end = ACPI_ADD_PTR(struct acpi_rimt_node, rimt_table, 163 rimt_table->length); 164 165 for (i = 0; i < rimt->num_nodes; i++) { 166 if (WARN_TAINT(rimt_node >= rimt_end, TAINT_FIRMWARE_WORKAROUND, 167 "RIMT node pointer overflows, bad table!\n")) 168 return NULL; 169 170 if (rimt_node->type == type && 171 ACPI_SUCCESS(rimt_match_node_callback(rimt_node, context))) 172 return rimt_node; 173 174 rimt_node = ACPI_ADD_PTR(struct acpi_rimt_node, rimt_node, 175 rimt_node->length); 176 } 177 178 return NULL; 179 } 180 181 /* 182 * RISC-V supports IOMMU as a PCI device or a platform device. 183 * When it is a platform device, there should be a namespace device as 184 * well along with RIMT. To create the link between RIMT information and 185 * the platform device, the IOMMU driver should register itself with the 186 * RIMT module. This is true for PCI based IOMMU as well. 187 */ 188 int rimt_iommu_register(struct device *dev) 189 { 190 struct fwnode_handle *rimt_fwnode; 191 struct acpi_rimt_node *node; 192 193 node = rimt_scan_node(ACPI_RIMT_NODE_TYPE_IOMMU, dev); 194 if (!node) { 195 pr_err("Could not find IOMMU node in RIMT\n"); 196 return -ENODEV; 197 } 198 199 if (dev_is_pci(dev)) { 200 rimt_fwnode = acpi_alloc_fwnode_static(); 201 if (!rimt_fwnode) 202 return -ENOMEM; 203 204 rimt_fwnode->dev = dev; 205 if (!dev->fwnode) 206 dev->fwnode = rimt_fwnode; 207 208 rimt_set_fwnode(node, rimt_fwnode); 209 } else { 210 rimt_set_fwnode(node, dev->fwnode); 211 } 212 213 return 0; 214 } 215 216 #ifdef CONFIG_IOMMU_API 217 218 /** 219 * rimt_get_fwnode() - Retrieve fwnode associated with an RIMT node 220 * 221 * @node: RIMT table node to be looked-up 222 * 223 * Returns: fwnode_handle pointer on success, NULL on failure 224 */ 225 static struct fwnode_handle *rimt_get_fwnode(struct acpi_rimt_node *node) 226 { 227 struct fwnode_handle *fwnode = NULL; 228 struct rimt_fwnode *curr; 229 230 spin_lock(&rimt_fwnode_lock); 231 list_for_each_entry(curr, &rimt_fwnode_list, list) { 232 if (curr->rimt_node == node) { 233 fwnode = curr->fwnode; 234 break; 235 } 236 } 237 spin_unlock(&rimt_fwnode_lock); 238 239 return fwnode; 240 } 241 242 static bool rimt_pcie_rc_supports_ats(struct acpi_rimt_node *node) 243 { 244 struct acpi_rimt_pcie_rc *pci_rc; 245 246 pci_rc = (struct acpi_rimt_pcie_rc *)node->node_data; 247 return pci_rc->flags & ACPI_RIMT_PCIE_ATS_SUPPORTED; 248 } 249 250 static int rimt_iommu_xlate(struct device *dev, struct acpi_rimt_node *node, u32 deviceid) 251 { 252 struct fwnode_handle *rimt_fwnode; 253 254 if (!node) 255 return -ENODEV; 256 257 rimt_fwnode = rimt_get_fwnode(node); 258 259 /* 260 * The IOMMU drivers may not be probed yet. 261 * Defer the IOMMU configuration 262 */ 263 if (!rimt_fwnode) 264 return -EPROBE_DEFER; 265 266 /* 267 * EPROBE_DEFER ensures IOMMU is probed before the devices that 268 * depend on them. During shutdown, however, the IOMMU may be removed 269 * first, leading to issues. To avoid this, a device link is added 270 * which enforces the correct removal order. 271 */ 272 device_link_add(dev, rimt_fwnode->dev, DL_FLAG_AUTOREMOVE_CONSUMER); 273 return acpi_iommu_fwspec_init(dev, deviceid, rimt_fwnode); 274 } 275 276 struct rimt_pci_alias_info { 277 struct device *dev; 278 struct acpi_rimt_node *node; 279 const struct iommu_ops *ops; 280 }; 281 282 static int rimt_id_map(struct acpi_rimt_id_mapping *map, u8 type, u32 rid_in, u32 *rid_out) 283 { 284 if (rid_in < map->source_id_base || 285 (rid_in > map->source_id_base + map->num_ids)) 286 return -ENXIO; 287 288 *rid_out = map->dest_id_base + (rid_in - map->source_id_base); 289 return 0; 290 } 291 292 static struct acpi_rimt_node *rimt_node_get_id(struct acpi_rimt_node *node, 293 u32 *id_out, int index) 294 { 295 struct acpi_rimt_platform_device *plat_node; 296 u32 id_mapping_offset, num_id_mapping; 297 struct acpi_rimt_pcie_rc *pci_node; 298 struct acpi_rimt_id_mapping *map; 299 struct acpi_rimt_node *parent; 300 301 if (node->type == ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX) { 302 pci_node = (struct acpi_rimt_pcie_rc *)&node->node_data; 303 id_mapping_offset = pci_node->id_mapping_offset; 304 num_id_mapping = pci_node->num_id_mappings; 305 } else if (node->type == ACPI_RIMT_NODE_TYPE_PLAT_DEVICE) { 306 plat_node = (struct acpi_rimt_platform_device *)&node->node_data; 307 id_mapping_offset = plat_node->id_mapping_offset; 308 num_id_mapping = plat_node->num_id_mappings; 309 } else { 310 return NULL; 311 } 312 313 if (!id_mapping_offset || !num_id_mapping || index >= num_id_mapping) 314 return NULL; 315 316 map = ACPI_ADD_PTR(struct acpi_rimt_id_mapping, node, 317 id_mapping_offset + index * sizeof(*map)); 318 319 /* Firmware bug! */ 320 if (!map->dest_offset) { 321 pr_err(FW_BUG "[node %p type %d] ID map has NULL parent reference\n", 322 node, node->type); 323 return NULL; 324 } 325 326 parent = ACPI_ADD_PTR(struct acpi_rimt_node, rimt_table, map->dest_offset); 327 328 if (node->type == ACPI_RIMT_NODE_TYPE_PLAT_DEVICE || 329 node->type == ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX) { 330 *id_out = map->dest_id_base; 331 return parent; 332 } 333 334 return NULL; 335 } 336 337 static struct acpi_rimt_node *rimt_node_map_id(struct acpi_rimt_node *node, 338 u32 id_in, u32 *id_out, 339 u8 type_mask) 340 { 341 struct acpi_rimt_platform_device *plat_node; 342 u32 id_mapping_offset, num_id_mapping; 343 struct acpi_rimt_pcie_rc *pci_node; 344 u32 id = id_in; 345 346 /* Parse the ID mapping tree to find specified node type */ 347 while (node) { 348 struct acpi_rimt_id_mapping *map; 349 int i, rc = 0; 350 u32 map_id = id; 351 352 if (RIMT_TYPE_MASK(node->type) & type_mask) { 353 if (id_out) 354 *id_out = id; 355 return node; 356 } 357 358 if (node->type == ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX) { 359 pci_node = (struct acpi_rimt_pcie_rc *)&node->node_data; 360 id_mapping_offset = pci_node->id_mapping_offset; 361 num_id_mapping = pci_node->num_id_mappings; 362 } else if (node->type == ACPI_RIMT_NODE_TYPE_PLAT_DEVICE) { 363 plat_node = (struct acpi_rimt_platform_device *)&node->node_data; 364 id_mapping_offset = plat_node->id_mapping_offset; 365 num_id_mapping = plat_node->num_id_mappings; 366 } else { 367 goto fail_map; 368 } 369 370 if (!id_mapping_offset || !num_id_mapping) 371 goto fail_map; 372 373 map = ACPI_ADD_PTR(struct acpi_rimt_id_mapping, node, 374 id_mapping_offset); 375 376 /* Firmware bug! */ 377 if (!map->dest_offset) { 378 pr_err(FW_BUG "[node %p type %d] ID map has NULL parent reference\n", 379 node, node->type); 380 goto fail_map; 381 } 382 383 /* Do the ID translation */ 384 for (i = 0; i < num_id_mapping; i++, map++) { 385 rc = rimt_id_map(map, node->type, map_id, &id); 386 if (!rc) 387 break; 388 } 389 390 if (i == num_id_mapping) 391 goto fail_map; 392 393 node = ACPI_ADD_PTR(struct acpi_rimt_node, rimt_table, 394 rc ? 0 : map->dest_offset); 395 } 396 397 fail_map: 398 /* Map input ID to output ID unchanged on mapping failure */ 399 if (id_out) 400 *id_out = id_in; 401 402 return NULL; 403 } 404 405 static struct acpi_rimt_node *rimt_node_map_platform_id(struct acpi_rimt_node *node, u32 *id_out, 406 u8 type_mask, int index) 407 { 408 struct acpi_rimt_node *parent; 409 u32 id; 410 411 parent = rimt_node_get_id(node, &id, index); 412 if (!parent) 413 return NULL; 414 415 if (!(RIMT_TYPE_MASK(parent->type) & type_mask)) 416 parent = rimt_node_map_id(parent, id, id_out, type_mask); 417 else 418 if (id_out) 419 *id_out = id; 420 421 return parent; 422 } 423 424 static int rimt_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data) 425 { 426 struct rimt_pci_alias_info *info = data; 427 struct acpi_rimt_node *parent; 428 u32 deviceid; 429 430 parent = rimt_node_map_id(info->node, alias, &deviceid, RIMT_IOMMU_TYPE); 431 return rimt_iommu_xlate(info->dev, parent, deviceid); 432 } 433 434 static int rimt_plat_iommu_map(struct device *dev, struct acpi_rimt_node *node) 435 { 436 struct acpi_rimt_node *parent; 437 int err = -ENODEV, i = 0; 438 u32 deviceid = 0; 439 440 do { 441 parent = rimt_node_map_platform_id(node, &deviceid, 442 RIMT_IOMMU_TYPE, 443 i++); 444 445 if (parent) 446 err = rimt_iommu_xlate(dev, parent, deviceid); 447 } while (parent && !err); 448 449 return err; 450 } 451 452 static int rimt_plat_iommu_map_id(struct device *dev, 453 struct acpi_rimt_node *node, 454 const u32 *in_id) 455 { 456 struct acpi_rimt_node *parent; 457 u32 deviceid; 458 459 parent = rimt_node_map_id(node, *in_id, &deviceid, RIMT_IOMMU_TYPE); 460 if (parent) 461 return rimt_iommu_xlate(dev, parent, deviceid); 462 463 return -ENODEV; 464 } 465 466 /** 467 * rimt_iommu_configure_id - Set-up IOMMU configuration for a device. 468 * 469 * @dev: device to configure 470 * @id_in: optional input id const value pointer 471 * 472 * Returns: 0 on success, <0 on failure 473 */ 474 int rimt_iommu_configure_id(struct device *dev, const u32 *id_in) 475 { 476 struct acpi_rimt_node *node; 477 int err = -ENODEV; 478 479 if (dev_is_pci(dev)) { 480 struct iommu_fwspec *fwspec; 481 struct pci_bus *bus = to_pci_dev(dev)->bus; 482 struct rimt_pci_alias_info info = { .dev = dev }; 483 484 node = rimt_scan_node(ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX, &bus->dev); 485 if (!node) 486 return -ENODEV; 487 488 info.node = node; 489 err = pci_for_each_dma_alias(to_pci_dev(dev), 490 rimt_pci_iommu_init, &info); 491 492 fwspec = dev_iommu_fwspec_get(dev); 493 if (fwspec && rimt_pcie_rc_supports_ats(node)) 494 fwspec->flags |= IOMMU_FWSPEC_PCI_RC_ATS; 495 } else { 496 node = rimt_scan_node(ACPI_RIMT_NODE_TYPE_PLAT_DEVICE, dev); 497 if (!node) 498 return -ENODEV; 499 500 err = id_in ? rimt_plat_iommu_map_id(dev, node, id_in) : 501 rimt_plat_iommu_map(dev, node); 502 } 503 504 return err; 505 } 506 507 #endif 508 509 void __init riscv_acpi_rimt_init(void) 510 { 511 acpi_status status; 512 513 /* rimt_table will be used at runtime after the rimt init, 514 * so we don't need to call acpi_put_table() to release 515 * the RIMT table mapping. 516 */ 517 status = acpi_get_table(ACPI_SIG_RIMT, 0, &rimt_table); 518 if (ACPI_FAILURE(status)) { 519 if (status != AE_NOT_FOUND) { 520 const char *msg = acpi_format_exception(status); 521 522 pr_err("Failed to get table, %s\n", msg); 523 } 524 525 return; 526 } 527 } 528