Skip to content

Commit 04cd14f

Browse files
committed
Merge branch 'acpi-irq'
Merge ARM-related irq subsystem changes based on the recent ACPICA updates for 6.20-rc1/7.0-rc1: - Add support for GICv5 ACPI probing on ARM which is based on the GICv5 MADT structures and ARM IORT IWB node definitions recently added to ACPICA (Lorenzo Pieralisi) * acpi-irq: irqchip/gic-v5: Add ACPI IWB probing irqchip/gic-v5: Add ACPI ITS probing irqchip/gic-v5: Add ACPI IRS probing irqchip/gic-v5: Split IRS probing into OF and generic portions PCI/MSI: Make the pci_msi_map_rid_ctlr_node() interface firmware agnostic irqdomain: Add parent field to struct irqchip_fwid
2 parents 0e8ac1d + 05bff34 commit 04cd14f

14 files changed

Lines changed: 724 additions & 144 deletions

File tree

drivers/acpi/arm64/iort.c

Lines changed: 157 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -264,39 +264,47 @@ static acpi_status iort_match_node_callback(struct acpi_iort_node *node,
264264
struct device *dev = context;
265265
acpi_status status = AE_NOT_FOUND;
266266

267-
if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT) {
267+
if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT ||
268+
node->type == ACPI_IORT_NODE_IWB) {
268269
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
269-
struct acpi_device *adev;
270270
struct acpi_iort_named_component *ncomp;
271-
struct device *nc_dev = dev;
271+
struct acpi_iort_iwb *iwb;
272+
struct device *cdev = dev;
273+
struct acpi_device *adev;
274+
const char *device_name;
272275

273276
/*
274277
* Walk the device tree to find a device with an
275278
* ACPI companion; there is no point in scanning
276-
* IORT for a device matching a named component if
279+
* IORT for a device matching a named component or IWB if
277280
* the device does not have an ACPI companion to
278281
* start with.
279282
*/
280283
do {
281-
adev = ACPI_COMPANION(nc_dev);
284+
adev = ACPI_COMPANION(cdev);
282285
if (adev)
283286
break;
284287

285-
nc_dev = nc_dev->parent;
286-
} while (nc_dev);
288+
cdev = cdev->parent;
289+
} while (cdev);
287290

288291
if (!adev)
289292
goto out;
290293

291294
status = acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &buf);
292295
if (ACPI_FAILURE(status)) {
293-
dev_warn(nc_dev, "Can't get device full path name\n");
296+
dev_warn(cdev, "Can't get device full path name\n");
294297
goto out;
295298
}
296299

297-
ncomp = (struct acpi_iort_named_component *)node->node_data;
298-
status = !strcmp(ncomp->device_name, buf.pointer) ?
299-
AE_OK : AE_NOT_FOUND;
300+
if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT) {
301+
ncomp = (struct acpi_iort_named_component *)node->node_data;
302+
device_name = ncomp->device_name;
303+
} else {
304+
iwb = (struct acpi_iort_iwb *)node->node_data;
305+
device_name = iwb->device_name;
306+
}
307+
status = !strcmp(device_name, buf.pointer) ? AE_OK : AE_NOT_FOUND;
300308
acpi_os_free(buf.pointer);
301309
} else if (node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX) {
302310
struct acpi_iort_root_complex *pci_rc;
@@ -317,12 +325,28 @@ static acpi_status iort_match_node_callback(struct acpi_iort_node *node,
317325
return status;
318326
}
319327

328+
static acpi_status iort_match_iwb_callback(struct acpi_iort_node *node, void *context)
329+
{
330+
struct acpi_iort_iwb *iwb;
331+
u32 *id = context;
332+
333+
if (node->type != ACPI_IORT_NODE_IWB)
334+
return AE_NOT_FOUND;
335+
336+
iwb = (struct acpi_iort_iwb *)node->node_data;
337+
if (iwb->iwb_index != *id)
338+
return AE_NOT_FOUND;
339+
340+
return AE_OK;
341+
}
342+
320343
static int iort_id_map(struct acpi_iort_id_mapping *map, u8 type, u32 rid_in,
321344
u32 *rid_out, bool check_overlap)
322345
{
323346
/* Single mapping does not care for input id */
324347
if (map->flags & ACPI_IORT_ID_SINGLE_MAPPING) {
325348
if (type == ACPI_IORT_NODE_NAMED_COMPONENT ||
349+
type == ACPI_IORT_NODE_IWB ||
326350
type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX) {
327351
*rid_out = map->output_base;
328352
return 0;
@@ -392,6 +416,7 @@ static struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
392416

393417
if (map->flags & ACPI_IORT_ID_SINGLE_MAPPING) {
394418
if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT ||
419+
node->type == ACPI_IORT_NODE_IWB ||
395420
node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX ||
396421
node->type == ACPI_IORT_NODE_SMMU_V3 ||
397422
node->type == ACPI_IORT_NODE_PMCG) {
@@ -562,9 +587,14 @@ static struct acpi_iort_node *iort_find_dev_node(struct device *dev)
562587
return node;
563588
/*
564589
* if not, then it should be a platform device defined in
565-
* DSDT/SSDT (with Named Component node in IORT)
590+
* DSDT/SSDT (with Named Component node in IORT) or an
591+
* IWB device in the DSDT/SSDT.
566592
*/
567-
return iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
593+
node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
594+
iort_match_node_callback, dev);
595+
if (node)
596+
return node;
597+
return iort_scan_node(ACPI_IORT_NODE_IWB,
568598
iort_match_node_callback, dev);
569599
}
570600

@@ -595,45 +625,45 @@ u32 iort_msi_map_id(struct device *dev, u32 input_id)
595625
}
596626

597627
/**
598-
* iort_pmsi_get_dev_id() - Get the device id for a device
628+
* iort_msi_xlate() - Map a MSI input ID for a device
599629
* @dev: The device for which the mapping is to be done.
600-
* @dev_id: The device ID found.
630+
* @input_id: The device input ID.
631+
* @fwnode: Pointer to store the fwnode.
601632
*
602-
* Returns: 0 for successful find a dev id, -ENODEV on error
633+
* Returns: mapped MSI ID on success, input ID otherwise
634+
* On success, the fwnode pointer is initialized to the MSI
635+
* controller fwnode handle.
603636
*/
604-
int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)
637+
u32 iort_msi_xlate(struct device *dev, u32 input_id, struct fwnode_handle **fwnode)
605638
{
606-
int i, index;
639+
struct acpi_iort_its_group *its;
607640
struct acpi_iort_node *node;
641+
u32 dev_id;
608642

609643
node = iort_find_dev_node(dev);
610644
if (!node)
611-
return -ENODEV;
645+
return input_id;
612646

613-
index = iort_get_id_mapping_index(node);
614-
/* if there is a valid index, go get the dev_id directly */
615-
if (index >= 0) {
616-
if (iort_node_get_id(node, dev_id, index))
617-
return 0;
618-
} else {
619-
for (i = 0; i < node->mapping_count; i++) {
620-
if (iort_node_map_platform_id(node, dev_id,
621-
IORT_MSI_TYPE, i))
622-
return 0;
623-
}
624-
}
647+
node = iort_node_map_id(node, input_id, &dev_id, IORT_MSI_TYPE);
648+
if (!node)
649+
return input_id;
625650

626-
return -ENODEV;
651+
/* Move to ITS specific data */
652+
its = (struct acpi_iort_its_group *)node->node_data;
653+
654+
*fwnode = iort_find_domain_token(its->identifiers[0]);
655+
656+
return dev_id;
627657
}
628658

629-
static int __maybe_unused iort_find_its_base(u32 its_id, phys_addr_t *base)
659+
int iort_its_translate_pa(struct fwnode_handle *node, phys_addr_t *base)
630660
{
631661
struct iort_its_msi_chip *its_msi_chip;
632662
int ret = -ENODEV;
633663

634664
spin_lock(&iort_msi_chip_lock);
635665
list_for_each_entry(its_msi_chip, &iort_msi_chip_list, list) {
636-
if (its_msi_chip->translation_id == its_id) {
666+
if (its_msi_chip->fw_node == node) {
637667
*base = its_msi_chip->base_addr;
638668
ret = 0;
639669
break;
@@ -644,6 +674,62 @@ static int __maybe_unused iort_find_its_base(u32 its_id, phys_addr_t *base)
644674
return ret;
645675
}
646676

677+
static int __maybe_unused iort_find_its_base(u32 its_id, phys_addr_t *base)
678+
{
679+
struct fwnode_handle *fwnode = iort_find_domain_token(its_id);
680+
681+
if (!fwnode)
682+
return -ENODEV;
683+
684+
return iort_its_translate_pa(fwnode, base);
685+
}
686+
687+
/**
688+
* iort_pmsi_get_msi_info() - Get the device id and translate frame PA for a device
689+
* @dev: The device for which the mapping is to be done.
690+
* @dev_id: The device ID found.
691+
* @pa: optional pointer to store translate frame address.
692+
*
693+
* Returns: 0 for successful devid and pa retrieval, -ENODEV on error
694+
*/
695+
int iort_pmsi_get_msi_info(struct device *dev, u32 *dev_id, phys_addr_t *pa)
696+
{
697+
struct acpi_iort_node *node, *parent = NULL;
698+
struct acpi_iort_its_group *its;
699+
int i, index;
700+
701+
node = iort_find_dev_node(dev);
702+
if (!node)
703+
return -ENODEV;
704+
705+
index = iort_get_id_mapping_index(node);
706+
/* if there is a valid index, go get the dev_id directly */
707+
if (index >= 0) {
708+
parent = iort_node_get_id(node, dev_id, index);
709+
} else {
710+
for (i = 0; i < node->mapping_count; i++) {
711+
parent = iort_node_map_platform_id(node, dev_id,
712+
IORT_MSI_TYPE, i);
713+
if (parent)
714+
break;
715+
}
716+
}
717+
718+
if (!parent)
719+
return -ENODEV;
720+
721+
if (pa) {
722+
int ret;
723+
724+
its = (struct acpi_iort_its_group *)node->node_data;
725+
ret = iort_find_its_base(its->identifiers[0], pa);
726+
if (ret)
727+
return ret;
728+
}
729+
730+
return 0;
731+
}
732+
647733
/**
648734
* iort_dev_find_its_id() - Find the ITS identifier for a device
649735
* @dev: The device.
@@ -703,6 +789,35 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
703789
return irq_find_matching_fwnode(handle, bus_token);
704790
}
705791

792+
struct fwnode_handle *iort_iwb_handle(u32 iwb_id)
793+
{
794+
struct fwnode_handle *fwnode;
795+
struct acpi_iort_node *node;
796+
struct acpi_device *device;
797+
struct acpi_iort_iwb *iwb;
798+
acpi_status status;
799+
acpi_handle handle;
800+
801+
/* find its associated IWB node */
802+
node = iort_scan_node(ACPI_IORT_NODE_IWB, iort_match_iwb_callback, &iwb_id);
803+
if (!node)
804+
return NULL;
805+
806+
iwb = (struct acpi_iort_iwb *)node->node_data;
807+
status = acpi_get_handle(NULL, iwb->device_name, &handle);
808+
if (ACPI_FAILURE(status))
809+
return NULL;
810+
811+
device = acpi_get_acpi_dev(handle);
812+
if (!device)
813+
return NULL;
814+
815+
fwnode = acpi_fwnode_handle(device);
816+
acpi_put_acpi_dev(device);
817+
818+
return fwnode;
819+
}
820+
706821
static void iort_set_device_domain(struct device *dev,
707822
struct acpi_iort_node *node)
708823
{
@@ -763,8 +878,14 @@ static struct irq_domain *iort_get_platform_device_domain(struct device *dev)
763878
/* find its associated iort node */
764879
node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
765880
iort_match_node_callback, dev);
766-
if (!node)
767-
return NULL;
881+
if (!node) {
882+
/* find its associated iort node */
883+
node = iort_scan_node(ACPI_IORT_NODE_IWB,
884+
iort_match_node_callback, dev);
885+
886+
if (!node)
887+
return NULL;
888+
}
768889

769890
/* then find its msi parent node */
770891
for (i = 0; i < node->mapping_count; i++) {

drivers/acpi/bus.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,6 +1197,9 @@ static int __init acpi_bus_init_irq(void)
11971197
case ACPI_IRQ_MODEL_GIC:
11981198
message = "GIC";
11991199
break;
1200+
case ACPI_IRQ_MODEL_GIC_V5:
1201+
message = "GICv5";
1202+
break;
12001203
case ACPI_IRQ_MODEL_PLATFORM:
12011204
message = "platform specific model";
12021205
break;

0 commit comments

Comments
 (0)