Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F97487984
D25219.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D25219.diff
View Options
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -191,6 +191,7 @@
static void acpi_hint_device_unit(device_t acdev, device_t child,
const char *name, int *unitp);
static void acpi_reset_interfaces(device_t dev);
+static bus_dma_tag_t acpi_get_dma_tag(device_t dev, device_t child);
static device_method_t acpi_methods[] = {
/* Device interface */
@@ -226,6 +227,7 @@
DEVMETHOD(bus_get_cpus, acpi_get_cpus),
DEVMETHOD(bus_get_domain, acpi_get_domain),
DEVMETHOD(bus_get_property, acpi_bus_get_prop),
+ DEVMETHOD(bus_get_dma_tag, acpi_get_dma_tag),
/* ACPI bus */
DEVMETHOD(acpi_id_probe, acpi_device_id_probe),
@@ -449,6 +451,102 @@
return (0);
}
+struct dma_limits {
+ bus_addr_t lowaddr;
+};
+
+static ACPI_STATUS
+dma_on_resource(ACPI_RESOURCE *res, void *arg)
+{
+ struct dma_limits *limits = arg;
+ bus_addr_t min, len;
+
+ /*
+ * The minimum and maximum are device-side. To get the CPU-side minimum,
+ * we add the translation offset. This can overflow to signify lower addresses
+ * on the CPU than the device, e.g. "Bus 0xC0000000 -> CPU 0x00000000"
+ * on the RPi4 is represented as 0xC0000000 min + 0xFFFFFFFF40000000 offset.
+ */
+
+ switch (res->Type) {
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ min = (uint16_t)(res->Data.Address16.Address.Minimum +
+ res->Data.Address16.Address.TranslationOffset);
+ len = res->Data.Address16.Address.AddressLength;
+ break;
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ min = (uint32_t)(res->Data.Address32.Address.Minimum +
+ res->Data.Address32.Address.TranslationOffset);
+ len = res->Data.Address32.Address.AddressLength;
+ break;
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ min = (uint64_t)(res->Data.Address64.Address.Minimum +
+ res->Data.Address64.Address.TranslationOffset);
+ len = res->Data.Address64.Address.AddressLength;
+ break;
+ case ACPI_RESOURCE_TYPE_END_TAG:
+ return (AE_OK);
+ default:
+ printf("ACPI: warning: DMA limit with unsupported resource type %d\n",
+ res->Type);
+ return (AE_OK);
+ }
+
+ if (min != 0)
+ printf("ACPI: warning: DMA limit with non-zero minimum address"
+ " not supported yet\n");
+
+ limits->lowaddr = MIN(limits->lowaddr, min + len);
+
+ return (AE_OK);
+}
+
+static int
+get_dma_tag(ACPI_HANDLE handle, bus_dma_tag_t *result)
+{
+ ACPI_HANDLE parent;
+ unsigned int coherent;
+ struct dma_limits limits = {
+ .lowaddr = BUS_SPACE_MAXADDR,
+ };
+
+ if (ACPI_FAILURE(AcpiWalkResources(handle, "_DMA",
+ dma_on_resource, (void *)&limits))) {
+ /* Inherit resources from parent handle if we don't have our own */
+ if (ACPI_SUCCESS(AcpiGetParent(handle, &parent)))
+ return (get_dma_tag(parent, result));
+
+ /* The root (which has no parent) has no restrictions */
+ *result = NULL;
+ return (0);
+ }
+
+ if (ACPI_FAILURE(acpi_GetInteger(handle, "_CCA", &coherent)))
+ coherent = 0;
+
+ if (bus_dma_tag_create(NULL, 1, 0,
+ limits.lowaddr, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED, BUS_SPACE_MAXSIZE,
+ coherent ? BUS_DMA_COHERENT : 0, NULL, NULL,
+ result) != 0)
+ return (ENOMEM);
+
+ return (0);
+}
+
+static bus_dma_tag_t
+acpi_get_dma_tag(device_t dev, device_t child)
+{
+ bus_dma_tag_t result;
+
+ if (get_dma_tag(acpi_get_handle(child), &result) != 0) {
+ device_printf(child, "could not get ACPI DMA limits\n");
+ return (NULL);
+ }
+
+ return (result);
+}
+
/*
* Fetch some descriptive data from ACPI to put in our attach message.
*/
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Sep 30, 4:22 PM (22 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13191942
Default Alt Text
D25219.diff (3 KB)
Attached To
Mode
D25219: ACPI: add support for (inherited) _DMA limits
Attached
Detach File
Event Timeline
Log In to Comment