Commit 13c35c83 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branches 'acpi-numa', 'acpi-sysfs', 'acpi-pmic', 'acpi-soc' and 'acpi-ged'

* acpi-numa:
  ACPI / NUMA: ia64: Parse all entries of SRAT memory affinity table

* acpi-sysfs:
  ACPI: sysfs: Make ACPI GPE mask kernel parameter cover all GPEs

* acpi-pmic:
  ACPI / PMIC: Convert to use builtin_platform_driver() macro
  ACPI / PMIC: constify platform_device_id

* acpi-soc:
  ACPI / LPSS: Do not instiate platform_dev for devs without MMIO resources
  ACPI / LPSS: Add device link for CHT SD card dependency on I2C

* acpi-ged:
  ACPI: GED: unregister interrupts during shutdown
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -114,7 +114,6 @@
			This facility can be used to prevent such uncontrolled
			GPE floodings.
			Format: <int>
			Support masking of GPEs numbered from 0x00 to 0x7f.

	acpi_no_auto_serialize	[HW,ACPI]
			Disable auto-serialization of AML methods
+5 −0
Original line number Diff line number Diff line
@@ -504,6 +504,11 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
	if (!(ma->flags & ACPI_SRAT_MEM_ENABLED))
		return -1;

	if (num_node_memblks >= NR_NODE_MEMBLKS) {
		pr_err("NUMA: too many memblk ranges\n");
		return -EINVAL;
	}

	/* record this node in proximity bitmap */
	pxm_bit_set(pxm);

+139 −0
Original line number Diff line number Diff line
@@ -427,6 +427,142 @@ out:
	return 0;
}

struct lpss_device_links {
	const char *supplier_hid;
	const char *supplier_uid;
	const char *consumer_hid;
	const char *consumer_uid;
	u32 flags;
};

/*
 * The _DEP method is used to identify dependencies but instead of creating
 * device links for every handle in _DEP, only links in the following list are
 * created. That is necessary because, in the general case, _DEP can refer to
 * devices that might not have drivers, or that are on different buses, or where
 * the supplier is not enumerated until after the consumer is probed.
 */
static const struct lpss_device_links lpss_device_links[] = {
	{"808622C1", "7", "80860F14", "3", DL_FLAG_PM_RUNTIME},
};

static bool hid_uid_match(const char *hid1, const char *uid1,
			  const char *hid2, const char *uid2)
{
	return !strcmp(hid1, hid2) && uid1 && uid2 && !strcmp(uid1, uid2);
}

static bool acpi_lpss_is_supplier(struct acpi_device *adev,
				  const struct lpss_device_links *link)
{
	return hid_uid_match(acpi_device_hid(adev), acpi_device_uid(adev),
			     link->supplier_hid, link->supplier_uid);
}

static bool acpi_lpss_is_consumer(struct acpi_device *adev,
				  const struct lpss_device_links *link)
{
	return hid_uid_match(acpi_device_hid(adev), acpi_device_uid(adev),
			     link->consumer_hid, link->consumer_uid);
}

struct hid_uid {
	const char *hid;
	const char *uid;
};

static int match_hid_uid(struct device *dev, void *data)
{
	struct acpi_device *adev = ACPI_COMPANION(dev);
	struct hid_uid *id = data;

	if (!adev)
		return 0;

	return hid_uid_match(acpi_device_hid(adev), acpi_device_uid(adev),
			     id->hid, id->uid);
}

static struct device *acpi_lpss_find_device(const char *hid, const char *uid)
{
	struct hid_uid data = {
		.hid = hid,
		.uid = uid,
	};

	return bus_find_device(&platform_bus_type, NULL, &data, match_hid_uid);
}

static bool acpi_lpss_dep(struct acpi_device *adev, acpi_handle handle)
{
	struct acpi_handle_list dep_devices;
	acpi_status status;
	int i;

	if (!acpi_has_method(adev->handle, "_DEP"))
		return false;

	status = acpi_evaluate_reference(adev->handle, "_DEP", NULL,
					 &dep_devices);
	if (ACPI_FAILURE(status)) {
		dev_dbg(&adev->dev, "Failed to evaluate _DEP.\n");
		return false;
	}

	for (i = 0; i < dep_devices.count; i++) {
		if (dep_devices.handles[i] == handle)
			return true;
	}

	return false;
}

static void acpi_lpss_link_consumer(struct device *dev1,
				    const struct lpss_device_links *link)
{
	struct device *dev2;

	dev2 = acpi_lpss_find_device(link->consumer_hid, link->consumer_uid);
	if (!dev2)
		return;

	if (acpi_lpss_dep(ACPI_COMPANION(dev2), ACPI_HANDLE(dev1)))
		device_link_add(dev2, dev1, link->flags);

	put_device(dev2);
}

static void acpi_lpss_link_supplier(struct device *dev1,
				    const struct lpss_device_links *link)
{
	struct device *dev2;

	dev2 = acpi_lpss_find_device(link->supplier_hid, link->supplier_uid);
	if (!dev2)
		return;

	if (acpi_lpss_dep(ACPI_COMPANION(dev1), ACPI_HANDLE(dev2)))
		device_link_add(dev1, dev2, link->flags);

	put_device(dev2);
}

static void acpi_lpss_create_device_links(struct acpi_device *adev,
					  struct platform_device *pdev)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(lpss_device_links); i++) {
		const struct lpss_device_links *link = &lpss_device_links[i];

		if (acpi_lpss_is_supplier(adev, link))
			acpi_lpss_link_consumer(&pdev->dev, link);

		if (acpi_lpss_is_consumer(adev, link))
			acpi_lpss_link_supplier(&pdev->dev, link);
	}
}

static int acpi_lpss_create_device(struct acpi_device *adev,
				   const struct acpi_device_id *id)
{
@@ -465,6 +601,8 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
	acpi_dev_free_resource_list(&resource_list);

	if (!pdata->mmio_base) {
		/* Avoid acpi_bus_attach() instantiating a pdev for this dev. */
		adev->pnp.type.platform_id = 0;
		/* Skip the device, but continue the namespace scan. */
		ret = 0;
		goto err_out;
@@ -500,6 +638,7 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
	adev->driver_data = pdata;
	pdev = acpi_create_platform_device(adev, dev_desc->properties);
	if (!IS_ERR_OR_NULL(pdev)) {
		acpi_lpss_create_device_links(adev, pdev);
		return 1;
	}

+41 −6
Original line number Diff line number Diff line
@@ -49,6 +49,11 @@

#define MODULE_NAME	"acpi-ged"

struct acpi_ged_device {
	struct device *dev;
	struct list_head event_list;
};

struct acpi_ged_event {
	struct list_head node;
	struct device *dev;
@@ -76,7 +81,8 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
	unsigned int irq;
	unsigned int gsi;
	unsigned int irqflags = IRQF_ONESHOT;
	struct device *dev = context;
	struct acpi_ged_device *geddev = context;
	struct device *dev = geddev->dev;
	acpi_handle handle = ACPI_HANDLE(dev);
	acpi_handle evt_handle;
	struct resource r;
@@ -102,8 +108,6 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
		return AE_ERROR;
	}

	dev_info(dev, "GED listening GSI %u @ IRQ %u\n", gsi, irq);

	event = devm_kzalloc(dev, sizeof(*event), GFP_KERNEL);
	if (!event)
		return AE_ERROR;
@@ -116,29 +120,58 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
	if (r.flags & IORESOURCE_IRQ_SHAREABLE)
		irqflags |= IRQF_SHARED;

	if (devm_request_threaded_irq(dev, irq, NULL, acpi_ged_irq_handler,
	if (request_threaded_irq(irq, NULL, acpi_ged_irq_handler,
				 irqflags, "ACPI:Ged", event)) {
		dev_err(dev, "failed to setup event handler for irq %u\n", irq);
		return AE_ERROR;
	}

	dev_dbg(dev, "GED listening GSI %u @ IRQ %u\n", gsi, irq);
	list_add_tail(&event->node, &geddev->event_list);
	return AE_OK;
}

static int ged_probe(struct platform_device *pdev)
{
	struct acpi_ged_device *geddev;
	acpi_status acpi_ret;

	geddev = devm_kzalloc(&pdev->dev, sizeof(*geddev), GFP_KERNEL);
	if (!geddev)
		return -ENOMEM;

	geddev->dev = &pdev->dev;
	INIT_LIST_HEAD(&geddev->event_list);
	acpi_ret = acpi_walk_resources(ACPI_HANDLE(&pdev->dev), "_CRS",
				       acpi_ged_request_interrupt, &pdev->dev);
				       acpi_ged_request_interrupt, geddev);
	if (ACPI_FAILURE(acpi_ret)) {
		dev_err(&pdev->dev, "unable to parse the _CRS record\n");
		return -EINVAL;
	}
	platform_set_drvdata(pdev, geddev);

	return 0;
}

static void ged_shutdown(struct platform_device *pdev)
{
	struct acpi_ged_device *geddev = platform_get_drvdata(pdev);
	struct acpi_ged_event *event, *next;

	list_for_each_entry_safe(event, next, &geddev->event_list, node) {
		free_irq(event->irq, event);
		list_del(&event->node);
		dev_dbg(geddev->dev, "GED releasing GSI %u @ IRQ %u\n",
			 event->gsi, event->irq);
	}
}

static int ged_remove(struct platform_device *pdev)
{
	ged_shutdown(pdev);
	return 0;
}

static const struct acpi_device_id ged_acpi_ids[] = {
	{"ACPI0013"},
	{},
@@ -146,6 +179,8 @@ static const struct acpi_device_id ged_acpi_ids[] = {

static struct platform_driver ged_driver = {
	.probe = ged_probe,
	.remove = ged_remove,
	.shutdown = ged_shutdown,
	.driver = {
		.name = MODULE_NAME,
		.acpi_match_table = ACPI_PTR(ged_acpi_ids),
+1 −2
Original line number Diff line number Diff line
@@ -460,8 +460,7 @@ int __init acpi_numa_init(void)
					srat_proc, ARRAY_SIZE(srat_proc), 0);

		cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
					    acpi_parse_memory_affinity,
					    NR_NODE_MEMBLKS);
					    acpi_parse_memory_affinity, 0);
	}

	/* SLIT: System Locality Information Table */
Loading