2 * Copyright (C) 2016, Semihalf
3 * Author: Tomasz Nowicki <tn@semihalf.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * This file implements early detection/parsing of I/O mapping
15 * reported to OS through firmware via I/O Remapping Table (IORT)
16 * IORT document number: ARM DEN 0049A
19 #define pr_fmt(fmt) "ACPI: IORT: " fmt
21 #include <linux/acpi_iort.h>
22 #include <linux/kernel.h>
23 #include <linux/pci.h>
25 struct iort_its_msi_chip
{
26 struct list_head list
;
27 struct fwnode_handle
*fw_node
;
31 typedef acpi_status (*iort_find_node_callback
)
32 (struct acpi_iort_node
*node
, void *context
);
34 /* Root pointer to the mapped IORT table */
35 static struct acpi_table_header
*iort_table
;
37 static LIST_HEAD(iort_msi_chip_list
);
38 static DEFINE_SPINLOCK(iort_msi_chip_lock
);
41 * iort_register_domain_token() - register domain token and related ITS ID
42 * to the list from where we can get it back later on.
44 * @fw_node: Domain token.
46 * Returns: 0 on success, -ENOMEM if no memory when allocating list element
48 int iort_register_domain_token(int trans_id
, struct fwnode_handle
*fw_node
)
50 struct iort_its_msi_chip
*its_msi_chip
;
52 its_msi_chip
= kzalloc(sizeof(*its_msi_chip
), GFP_KERNEL
);
56 its_msi_chip
->fw_node
= fw_node
;
57 its_msi_chip
->translation_id
= trans_id
;
59 spin_lock(&iort_msi_chip_lock
);
60 list_add(&its_msi_chip
->list
, &iort_msi_chip_list
);
61 spin_unlock(&iort_msi_chip_lock
);
67 * iort_deregister_domain_token() - Deregister domain token based on ITS ID
72 void iort_deregister_domain_token(int trans_id
)
74 struct iort_its_msi_chip
*its_msi_chip
, *t
;
76 spin_lock(&iort_msi_chip_lock
);
77 list_for_each_entry_safe(its_msi_chip
, t
, &iort_msi_chip_list
, list
) {
78 if (its_msi_chip
->translation_id
== trans_id
) {
79 list_del(&its_msi_chip
->list
);
84 spin_unlock(&iort_msi_chip_lock
);
88 * iort_find_domain_token() - Find domain token based on given ITS ID
91 * Returns: domain token when find on the list, NULL otherwise
93 struct fwnode_handle
*iort_find_domain_token(int trans_id
)
95 struct fwnode_handle
*fw_node
= NULL
;
96 struct iort_its_msi_chip
*its_msi_chip
;
98 spin_lock(&iort_msi_chip_lock
);
99 list_for_each_entry(its_msi_chip
, &iort_msi_chip_list
, list
) {
100 if (its_msi_chip
->translation_id
== trans_id
) {
101 fw_node
= its_msi_chip
->fw_node
;
105 spin_unlock(&iort_msi_chip_lock
);
110 static struct acpi_iort_node
*iort_scan_node(enum acpi_iort_node_type type
,
111 iort_find_node_callback callback
,
114 struct acpi_iort_node
*iort_node
, *iort_end
;
115 struct acpi_table_iort
*iort
;
121 /* Get the first IORT node */
122 iort
= (struct acpi_table_iort
*)iort_table
;
123 iort_node
= ACPI_ADD_PTR(struct acpi_iort_node
, iort
,
125 iort_end
= ACPI_ADD_PTR(struct acpi_iort_node
, iort_table
,
128 for (i
= 0; i
< iort
->node_count
; i
++) {
129 if (WARN_TAINT(iort_node
>= iort_end
, TAINT_FIRMWARE_WORKAROUND
,
130 "IORT node pointer overflows, bad table!\n"))
133 if (iort_node
->type
== type
&&
134 ACPI_SUCCESS(callback(iort_node
, context
)))
137 iort_node
= ACPI_ADD_PTR(struct acpi_iort_node
, iort_node
,
144 static acpi_status
iort_match_node_callback(struct acpi_iort_node
*node
,
147 struct device
*dev
= context
;
150 if (node
->type
== ACPI_IORT_NODE_NAMED_COMPONENT
) {
151 struct acpi_buffer buf
= { ACPI_ALLOCATE_BUFFER
, NULL
};
152 struct acpi_device
*adev
= to_acpi_device_node(dev
->fwnode
);
153 struct acpi_iort_named_component
*ncomp
;
156 status
= AE_NOT_FOUND
;
160 status
= acpi_get_name(adev
->handle
, ACPI_FULL_PATHNAME
, &buf
);
161 if (ACPI_FAILURE(status
)) {
162 dev_warn(dev
, "Can't get device full path name\n");
166 ncomp
= (struct acpi_iort_named_component
*)node
->node_data
;
167 status
= !strcmp(ncomp
->device_name
, buf
.pointer
) ?
168 AE_OK
: AE_NOT_FOUND
;
169 acpi_os_free(buf
.pointer
);
170 } else if (node
->type
== ACPI_IORT_NODE_PCI_ROOT_COMPLEX
) {
171 struct acpi_iort_root_complex
*pci_rc
;
174 bus
= to_pci_bus(dev
);
175 pci_rc
= (struct acpi_iort_root_complex
*)node
->node_data
;
178 * It is assumed that PCI segment numbers maps one-to-one
179 * with root complexes. Each segment number can represent only
182 status
= pci_rc
->pci_segment_number
== pci_domain_nr(bus
) ?
183 AE_OK
: AE_NOT_FOUND
;
185 status
= AE_NOT_FOUND
;
191 static int iort_id_map(struct acpi_iort_id_mapping
*map
, u8 type
, u32 rid_in
,
194 /* Single mapping does not care for input id */
195 if (map
->flags
& ACPI_IORT_ID_SINGLE_MAPPING
) {
196 if (type
== ACPI_IORT_NODE_NAMED_COMPONENT
||
197 type
== ACPI_IORT_NODE_PCI_ROOT_COMPLEX
) {
198 *rid_out
= map
->output_base
;
202 pr_warn(FW_BUG
"[map %p] SINGLE MAPPING flag not allowed for node type %d, skipping ID map\n",
207 if (rid_in
< map
->input_base
||
208 (rid_in
>= map
->input_base
+ map
->id_count
))
211 *rid_out
= map
->output_base
+ (rid_in
- map
->input_base
);
215 static struct acpi_iort_node
*iort_node_map_rid(struct acpi_iort_node
*node
,
216 u32 rid_in
, u32
*rid_out
,
221 /* Parse the ID mapping tree to find specified node type */
223 struct acpi_iort_id_mapping
*map
;
226 if (node
->type
== type
) {
232 if (!node
->mapping_offset
|| !node
->mapping_count
)
235 map
= ACPI_ADD_PTR(struct acpi_iort_id_mapping
, node
,
236 node
->mapping_offset
);
239 if (!map
->output_reference
) {
240 pr_err(FW_BUG
"[node %p type %d] ID map has NULL parent reference\n",
245 /* Do the RID translation */
246 for (i
= 0; i
< node
->mapping_count
; i
++, map
++) {
247 if (!iort_id_map(map
, node
->type
, rid
, &rid
))
251 if (i
== node
->mapping_count
)
254 node
= ACPI_ADD_PTR(struct acpi_iort_node
, iort_table
,
255 map
->output_reference
);
259 /* Map input RID to output RID unchanged on mapping failure*/
266 static struct acpi_iort_node
*iort_find_dev_node(struct device
*dev
)
268 struct pci_bus
*pbus
;
270 if (!dev_is_pci(dev
))
271 return iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT
,
272 iort_match_node_callback
, dev
);
274 /* Find a PCI root bus */
275 pbus
= to_pci_dev(dev
)->bus
;
276 while (!pci_is_root_bus(pbus
))
279 return iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX
,
280 iort_match_node_callback
, &pbus
->dev
);
284 * iort_msi_map_rid() - Map a MSI requester ID for a device
285 * @dev: The device for which the mapping is to be done.
286 * @req_id: The device requester ID.
288 * Returns: mapped MSI RID on success, input requester ID otherwise
290 u32
iort_msi_map_rid(struct device
*dev
, u32 req_id
)
292 struct acpi_iort_node
*node
;
295 node
= iort_find_dev_node(dev
);
299 iort_node_map_rid(node
, req_id
, &dev_id
, ACPI_IORT_NODE_ITS_GROUP
);
304 * iort_dev_find_its_id() - Find the ITS identifier for a device
306 * @idx: Index of the ITS identifier list.
307 * @its_id: ITS identifier.
309 * Returns: 0 on success, appropriate error value otherwise
311 static int iort_dev_find_its_id(struct device
*dev
, u32 req_id
,
312 unsigned int idx
, int *its_id
)
314 struct acpi_iort_its_group
*its
;
315 struct acpi_iort_node
*node
;
317 node
= iort_find_dev_node(dev
);
321 node
= iort_node_map_rid(node
, req_id
, NULL
, ACPI_IORT_NODE_ITS_GROUP
);
325 /* Move to ITS specific data */
326 its
= (struct acpi_iort_its_group
*)node
->node_data
;
327 if (idx
>= its
->its_count
) {
328 dev_err(dev
, "requested ITS ID index [%d] overruns ITS entries [%d]\n",
329 idx
, its
->its_count
);
333 *its_id
= its
->identifiers
[idx
];
338 * iort_get_device_domain() - Find MSI domain related to a device
340 * @req_id: Requester ID for the device.
342 * Returns: the MSI domain for this device, NULL otherwise
344 struct irq_domain
*iort_get_device_domain(struct device
*dev
, u32 req_id
)
346 struct fwnode_handle
*handle
;
349 if (iort_dev_find_its_id(dev
, req_id
, 0, &its_id
))
352 handle
= iort_find_domain_token(its_id
);
356 return irq_find_matching_fwnode(handle
, DOMAIN_BUS_PCI_MSI
);
359 void __init
acpi_iort_init(void)
363 status
= acpi_get_table(ACPI_SIG_IORT
, 0, &iort_table
);
364 if (ACPI_FAILURE(status
) && status
!= AE_NOT_FOUND
) {
365 const char *msg
= acpi_format_exception(status
);
366 pr_err("Failed to get table, %s\n", msg
);