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