Re: [PATCH v2] ACPI: add support for CSRT table

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wednesday, January 16, 2013 06:13:43 PM Mika Westerberg wrote:
> Core System Resources Table (CSRT) is a proprietary ACPI table that
> contains resources for certain devices that are not found in the DSDT
> table. Typically a shared DMA controller might be found here.
> 
> This patch adds support for this table. We go through all entries in the
> table and make platform devices of them. The resources from the table are
> passed with the platform device.
> 
> There is one special resource in the table and it is the DMA request line
> base and number of request lines. This information might be needed by the
> DMA controller driver as it needs to map the ACPI DMA request line number
> to the actual request line understood by the hardware. This range is passed
> as IORESOURCE_DMA resource.
> 
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
> Signed-off-by: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx>
> ---
> We got a report that compiling this as 32-bit gives the following warning:
> 
>     drivers/acpi/csrt.c:42:5: warning: left shift count >= width of type [enabled by default]
> 
> Since all the CSRT tables we've seen are limited to 32-bit physical
> addresses anyway (and the LPSS itself is 32-bit only) we fix this by only
> using the low part of the MMIO address for now.
> 
> Sorry about the mess.

No biggie.

I was about to apply this, but I started to wonder ->

> 
>  drivers/acpi/Makefile |    1 +
>  drivers/acpi/csrt.c   |  160 +++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 161 insertions(+)
>  create mode 100644 drivers/acpi/csrt.c
> 
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 4ee2e75..474fcfe 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -38,6 +38,7 @@ acpi-y				+= processor_core.o
>  acpi-y				+= ec.o
>  acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
>  acpi-y				+= pci_root.o pci_link.o pci_irq.o
> +acpi-y				+= csrt.o
>  acpi-y				+= acpi_platform.o
>  acpi-y				+= power.o
>  acpi-y				+= event.o
> diff --git a/drivers/acpi/csrt.c b/drivers/acpi/csrt.c
> new file mode 100644
> index 0000000..fe69587
> --- /dev/null
> +++ b/drivers/acpi/csrt.c
> @@ -0,0 +1,160 @@
> +/*
> + * Support for Core System Resources Table (CSRT)
> + *
> + * Copyright (C) 2013, Intel Corporation
> + * Authors: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx>
> + *	    Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#define pr_fmt(fmt) "ACPI: CSRT: " fmt
> +
> +#include <linux/acpi.h>
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/sizes.h>
> +
> +ACPI_MODULE_NAME("CSRT");
> +
> +static int __init acpi_csrt_parse_shared_info(struct platform_device *pdev,
> +					      const struct acpi_csrt_group *grp)
> +{
> +	const struct acpi_csrt_shared_info *si;
> +	struct resource res[3];
> +	size_t nres;
> +	int ret;
> +
> +	memset(res, 0, sizeof(res));
> +	nres = 0;
> +
> +	si = (const struct acpi_csrt_shared_info *)&grp[1];
> +	/*
> +	 * The peripherals that are listed on CSRT typically support only
> +	 * 32-bit addresses so we only use the low part of MMIO base for
> +	 * now.
> +	 */
> +	if (!si->mmio_base_high && si->mmio_base_low) {
> +		/*
> +		 * There is no size of the memory resource in shared_info
> +		 * so we assume that it is 4k here.
> +		 */
> +		res[nres].start = si->mmio_base_low;
> +		res[nres].end = res[0].start + SZ_4K - 1;
> +		res[nres++].flags = IORESOURCE_MEM;
> +	}
> +
> +	if (si->gsi_interrupt) {
> +		int irq = acpi_register_gsi(NULL, si->gsi_interrupt,
> +					    si->interrupt_mode,
> +					    si->interrupt_polarity);
> +		res[nres].start = irq;
> +		res[nres].end = irq;
> +		res[nres++].flags = IORESOURCE_IRQ;
> +	}
> +
> +	if (si->base_request_line || si->num_handshake_signals) {
> +		/*
> +		 * We pass the driver a DMA resource describing the range
> +		 * of request lines the device supports.
> +		 */
> +		res[nres].start = si->base_request_line;
> +		res[nres].end = res[nres].start + si->num_handshake_signals - 1;
> +		res[nres++].flags = IORESOURCE_DMA;
> +	}
> +
> +	ret = platform_device_add_resources(pdev, res, nres);
> +	if (ret) {
> +		if (si->gsi_interrupt)
> +			acpi_unregister_gsi(si->gsi_interrupt);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int __init
> +acpi_csrt_parse_resource_group(const struct acpi_csrt_group *grp)
> +{
> +	struct platform_device *pdev;
> +	char vendor[5], name[16];
> +	int ret, i;
> +
> +	vendor[0] = grp->vendor_id;
> +	vendor[1] = grp->vendor_id >> 8;
> +	vendor[2] = grp->vendor_id >> 16;
> +	vendor[3] = grp->vendor_id >> 24;
> +	vendor[4] = '\0';
> +
> +	if (grp->shared_info_length != sizeof(struct acpi_csrt_shared_info))
> +		return -ENODEV;
> +
> +	snprintf(name, sizeof(name), "%s%04X", vendor, grp->device_id);
> +	pdev = platform_device_alloc(name, PLATFORM_DEVID_AUTO);
> +	if (!pdev)
> +		return -ENOMEM;
> +
> +	/* Add resources based on the shared info */
> +	ret = acpi_csrt_parse_shared_info(pdev, grp);
> +	if (ret)
> +		goto fail;
> +
> +	ret = platform_device_add(pdev);
> +	if (ret)
> +		goto fail;
> +
> +	for (i = 0; i < pdev->num_resources; i++)
> +		dev_dbg(&pdev->dev, "%pR\n", &pdev->resource[i]);
> +
> +	return 0;
> +
> +fail:
> +	platform_device_put(pdev);
> +	return ret;
> +}
> +
> +/*
> + * CSRT or Core System Resources Table is a proprietary ACPI table
> + * introduced by Microsoft. This table can contain devices that are not in
> + * the system DSDT table. In particular DMA controllers might be described
> + * here.
> + *
> + * We present these devices as normal platform devices that don't have ACPI
> + * IDs or handle. The platform device name will be something like
> + * <VENDOR><DEVID>.<n>.auto for example: INTL9C06.0.auto.
> + */
> +static int __init acpi_csrt_init(void)
> +{
> +	struct acpi_csrt_group *grp, *end;
> +	struct acpi_table_csrt *csrt;
> +	acpi_status status;
> +	int ret;
> +
> +	status = acpi_get_table(ACPI_SIG_CSRT, 0,
> +				(struct acpi_table_header **)&csrt);
> +	if (ACPI_FAILURE(status)) {
> +		if (status == AE_NOT_FOUND)
> +			return -ENOENT;
> +		return -EINVAL;
> +	}
> +
> +	pr_debug("parsing CSRT table for devices\n");
> +
> +	grp = (struct acpi_csrt_group *)(csrt + 1);
> +	end = (struct acpi_csrt_group *)((void *)csrt + csrt->header.length);
> +
> +	while (grp < end) {
> +		ret = acpi_csrt_parse_resource_group(grp);
> +		if (ret)
> +			return ret;
> +
> +		grp = (struct acpi_csrt_group *)((void *)grp + grp->length);
> +	}
> +
> +	return 0;
> +}
> +subsys_initcall(acpi_csrt_init);

-> Do we really need a separate initcall for that?  And what if ACPI is
disabled?

Perhaps it would be better to call acpi_csrt_init() directly from
acpi_init() (or from acpi_scan_init() whichever is more suitable)?

Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux