Skip to content

Commit b8e069a

Browse files
Lorenzo Pieralisictmarinas
authored andcommitted
ACPI/IORT: Add an input ID to acpi_dma_configure()
Some HW devices are created as child devices of proprietary busses, that have a bus specific policy defining how the child devices wires representing the devices ID are translated into IOMMU and IRQ controllers device IDs. Current IORT code provides translations for: - PCI devices, where the device ID is well identified at bus level as the requester ID (RID) - Platform devices that are endpoint devices where the device ID is retrieved from the ACPI object IORT mappings (Named components single mappings). A platform device is represented in IORT as a named component node For devices that are child devices of proprietary busses the IORT firmware represents the bus node as a named component node in IORT and it is up to that named component node to define in/out bus specific ID translations for the bus child devices that are allocated and created in a bus specific manner. In order to make IORT ID translations available for proprietary bus child devices, the current ACPI (and IORT) code must be augmented to provide an additional ID parameter to acpi_dma_configure() representing the child devices input ID. This ID is bus specific and it is retrieved in bus specific code. By adding an ID parameter to acpi_dma_configure(), the IORT code can map the child device ID to an IOMMU stream ID through the IORT named component representing the bus in/out ID mappings. Signed-off-by: Lorenzo Pieralisi <[email protected]> Cc: Will Deacon <[email protected]> Cc: Hanjun Guo <[email protected]> Cc: Sudeep Holla <[email protected]> Cc: Robin Murphy <[email protected]> Cc: "Rafael J. Wysocki" <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent 3a3d208 commit b8e069a

File tree

5 files changed

+67
-23
lines changed

5 files changed

+67
-23
lines changed

drivers/acpi/arm64/iort.c

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -978,19 +978,54 @@ static void iort_named_component_init(struct device *dev,
978978
nc->node_flags);
979979
}
980980

981+
static int iort_nc_iommu_map(struct device *dev, struct acpi_iort_node *node)
982+
{
983+
struct acpi_iort_node *parent;
984+
int err = -ENODEV, i = 0;
985+
u32 streamid = 0;
986+
987+
do {
988+
989+
parent = iort_node_map_platform_id(node, &streamid,
990+
IORT_IOMMU_TYPE,
991+
i++);
992+
993+
if (parent)
994+
err = iort_iommu_xlate(dev, parent, streamid);
995+
} while (parent && !err);
996+
997+
return err;
998+
}
999+
1000+
static int iort_nc_iommu_map_id(struct device *dev,
1001+
struct acpi_iort_node *node,
1002+
const u32 *in_id)
1003+
{
1004+
struct acpi_iort_node *parent;
1005+
u32 streamid;
1006+
1007+
parent = iort_node_map_id(node, *in_id, &streamid, IORT_IOMMU_TYPE);
1008+
if (parent)
1009+
return iort_iommu_xlate(dev, parent, streamid);
1010+
1011+
return -ENODEV;
1012+
}
1013+
1014+
9811015
/**
982-
* iort_iommu_configure - Set-up IOMMU configuration for a device.
1016+
* iort_iommu_configure_id - Set-up IOMMU configuration for a device.
9831017
*
9841018
* @dev: device to configure
1019+
* @id_in: optional input id const value pointer
9851020
*
9861021
* Returns: iommu_ops pointer on configuration success
9871022
* NULL on configuration failure
9881023
*/
989-
const struct iommu_ops *iort_iommu_configure(struct device *dev)
1024+
const struct iommu_ops *iort_iommu_configure_id(struct device *dev,
1025+
const u32 *id_in)
9901026
{
991-
struct acpi_iort_node *node, *parent;
1027+
struct acpi_iort_node *node;
9921028
const struct iommu_ops *ops;
993-
u32 streamid = 0;
9941029
int err = -ENODEV;
9951030

9961031
/*
@@ -1019,21 +1054,13 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
10191054
if (fwspec && iort_pci_rc_supports_ats(node))
10201055
fwspec->flags |= IOMMU_FWSPEC_PCI_RC_ATS;
10211056
} else {
1022-
int i = 0;
1023-
10241057
node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
10251058
iort_match_node_callback, dev);
10261059
if (!node)
10271060
return NULL;
10281061

1029-
do {
1030-
parent = iort_node_map_platform_id(node, &streamid,
1031-
IORT_IOMMU_TYPE,
1032-
i++);
1033-
1034-
if (parent)
1035-
err = iort_iommu_xlate(dev, parent, streamid);
1036-
} while (parent && !err);
1062+
err = id_in ? iort_nc_iommu_map_id(dev, node, id_in) :
1063+
iort_nc_iommu_map(dev, node);
10371064

10381065
if (!err)
10391066
iort_named_component_init(dev, node);
@@ -1058,6 +1085,7 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
10581085

10591086
return ops;
10601087
}
1088+
10611089
#else
10621090
static inline const struct iommu_ops *iort_fwspec_iommu_ops(struct device *dev)
10631091
{ return NULL; }
@@ -1066,7 +1094,8 @@ static inline int iort_add_device_replay(const struct iommu_ops *ops,
10661094
{ return 0; }
10671095
int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
10681096
{ return 0; }
1069-
const struct iommu_ops *iort_iommu_configure(struct device *dev)
1097+
const struct iommu_ops *iort_iommu_configure_id(struct device *dev,
1098+
const u32 *input_id)
10701099
{ return NULL; }
10711100
#endif
10721101

drivers/acpi/scan.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,8 +1457,10 @@ int acpi_dma_get_range(struct device *dev, u64 *dma_addr, u64 *offset,
14571457
* acpi_dma_configure - Set-up DMA configuration for the device.
14581458
* @dev: The pointer to the device
14591459
* @attr: device dma attributes
1460+
* @input_id: input device id const value pointer
14601461
*/
1461-
int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
1462+
int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr,
1463+
const u32 *input_id)
14621464
{
14631465
const struct iommu_ops *iommu;
14641466
u64 dma_addr = 0, size = 0;
@@ -1470,7 +1472,7 @@ int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
14701472

14711473
iort_dma_setup(dev, &dma_addr, &size);
14721474

1473-
iommu = iort_iommu_configure(dev);
1475+
iommu = iort_iommu_configure_id(dev, input_id);
14741476
if (PTR_ERR(iommu) == -EPROBE_DEFER)
14751477
return -EPROBE_DEFER;
14761478

@@ -1479,7 +1481,7 @@ int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
14791481

14801482
return 0;
14811483
}
1482-
EXPORT_SYMBOL_GPL(acpi_dma_configure);
1484+
EXPORT_SYMBOL_GPL(acpi_dma_configure_id);
14831485

14841486
static void acpi_init_coherency(struct acpi_device *adev)
14851487
{

include/acpi/acpi_bus.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,8 +588,13 @@ bool acpi_dma_supported(struct acpi_device *adev);
588588
enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
589589
int acpi_dma_get_range(struct device *dev, u64 *dma_addr, u64 *offset,
590590
u64 *size);
591-
int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr);
592-
591+
int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr,
592+
const u32 *input_id);
593+
static inline int acpi_dma_configure(struct device *dev,
594+
enum dev_dma_attr attr)
595+
{
596+
return acpi_dma_configure_id(dev, attr, NULL);
597+
}
593598
struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
594599
u64 address, bool check_children);
595600
int acpi_is_root_bridge(acpi_handle);

include/linux/acpi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,13 @@ static inline int acpi_dma_configure(struct device *dev,
905905
return 0;
906906
}
907907

908+
static inline int acpi_dma_configure_id(struct device *dev,
909+
enum dev_dma_attr attr,
910+
const u32 *input_id)
911+
{
912+
return 0;
913+
}
914+
908915
#define ACPI_PTR(_ptr) (NULL)
909916

910917
static inline void acpi_device_set_enumerated(struct acpi_device *adev)

include/linux/acpi_iort.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ void acpi_configure_pmsi_domain(struct device *dev);
3535
int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
3636
/* IOMMU interface */
3737
void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *size);
38-
const struct iommu_ops *iort_iommu_configure(struct device *dev);
38+
const struct iommu_ops *iort_iommu_configure_id(struct device *dev,
39+
const u32 *id_in);
3940
int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head);
4041
#else
4142
static inline void acpi_iort_init(void) { }
@@ -48,8 +49,8 @@ static inline void acpi_configure_pmsi_domain(struct device *dev) { }
4849
/* IOMMU interface */
4950
static inline void iort_dma_setup(struct device *dev, u64 *dma_addr,
5051
u64 *size) { }
51-
static inline const struct iommu_ops *iort_iommu_configure(
52-
struct device *dev)
52+
static inline const struct iommu_ops *iort_iommu_configure_id(
53+
struct device *dev, const u32 *id_in)
5354
{ return NULL; }
5455
static inline
5556
int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)

0 commit comments

Comments
 (0)