@@ -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+
320343static 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
@@ -759,6 +789,35 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
759789 return irq_find_matching_fwnode (handle , bus_token );
760790}
761791
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+
762821static void iort_set_device_domain (struct device * dev ,
763822 struct acpi_iort_node * node )
764823{
@@ -819,8 +878,14 @@ static struct irq_domain *iort_get_platform_device_domain(struct device *dev)
819878 /* find its associated iort node */
820879 node = iort_scan_node (ACPI_IORT_NODE_NAMED_COMPONENT ,
821880 iort_match_node_callback , dev );
822- if (!node )
823- 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+ }
824889
825890 /* then find its msi parent node */
826891 for (i = 0 ; i < node -> mapping_count ; i ++ ) {
0 commit comments