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

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
...@@ -114,7 +114,6 @@ ...@@ -114,7 +114,6 @@
This facility can be used to prevent such uncontrolled This facility can be used to prevent such uncontrolled
GPE floodings. GPE floodings.
Format: <int> Format: <int>
Support masking of GPEs numbered from 0x00 to 0x7f.
acpi_no_auto_serialize [HW,ACPI] acpi_no_auto_serialize [HW,ACPI]
Disable auto-serialization of AML methods Disable auto-serialization of AML methods
......
...@@ -504,6 +504,11 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) ...@@ -504,6 +504,11 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
if (!(ma->flags & ACPI_SRAT_MEM_ENABLED)) if (!(ma->flags & ACPI_SRAT_MEM_ENABLED))
return -1; 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 */ /* record this node in proximity bitmap */
pxm_bit_set(pxm); pxm_bit_set(pxm);
......
...@@ -427,6 +427,142 @@ static int register_device_clock(struct acpi_device *adev, ...@@ -427,6 +427,142 @@ static int register_device_clock(struct acpi_device *adev,
return 0; 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, static int acpi_lpss_create_device(struct acpi_device *adev,
const struct acpi_device_id *id) const struct acpi_device_id *id)
{ {
...@@ -465,6 +601,8 @@ static int acpi_lpss_create_device(struct acpi_device *adev, ...@@ -465,6 +601,8 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
acpi_dev_free_resource_list(&resource_list); acpi_dev_free_resource_list(&resource_list);
if (!pdata->mmio_base) { 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. */ /* Skip the device, but continue the namespace scan. */
ret = 0; ret = 0;
goto err_out; goto err_out;
...@@ -500,6 +638,7 @@ static int acpi_lpss_create_device(struct acpi_device *adev, ...@@ -500,6 +638,7 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
adev->driver_data = pdata; adev->driver_data = pdata;
pdev = acpi_create_platform_device(adev, dev_desc->properties); pdev = acpi_create_platform_device(adev, dev_desc->properties);
if (!IS_ERR_OR_NULL(pdev)) { if (!IS_ERR_OR_NULL(pdev)) {
acpi_lpss_create_device_links(adev, pdev);
return 1; return 1;
} }
......
...@@ -49,6 +49,11 @@ ...@@ -49,6 +49,11 @@
#define MODULE_NAME "acpi-ged" #define MODULE_NAME "acpi-ged"
struct acpi_ged_device {
struct device *dev;
struct list_head event_list;
};
struct acpi_ged_event { struct acpi_ged_event {
struct list_head node; struct list_head node;
struct device *dev; struct device *dev;
...@@ -76,7 +81,8 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares, ...@@ -76,7 +81,8 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
unsigned int irq; unsigned int irq;
unsigned int gsi; unsigned int gsi;
unsigned int irqflags = IRQF_ONESHOT; 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 handle = ACPI_HANDLE(dev);
acpi_handle evt_handle; acpi_handle evt_handle;
struct resource r; struct resource r;
...@@ -102,8 +108,6 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares, ...@@ -102,8 +108,6 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
return AE_ERROR; return AE_ERROR;
} }
dev_info(dev, "GED listening GSI %u @ IRQ %u\n", gsi, irq);
event = devm_kzalloc(dev, sizeof(*event), GFP_KERNEL); event = devm_kzalloc(dev, sizeof(*event), GFP_KERNEL);
if (!event) if (!event)
return AE_ERROR; return AE_ERROR;
...@@ -116,29 +120,58 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares, ...@@ -116,29 +120,58 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
if (r.flags & IORESOURCE_IRQ_SHAREABLE) if (r.flags & IORESOURCE_IRQ_SHAREABLE)
irqflags |= IRQF_SHARED; 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)) { irqflags, "ACPI:Ged", event)) {
dev_err(dev, "failed to setup event handler for irq %u\n", irq); dev_err(dev, "failed to setup event handler for irq %u\n", irq);
return AE_ERROR; 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; return AE_OK;
} }
static int ged_probe(struct platform_device *pdev) static int ged_probe(struct platform_device *pdev)
{ {
struct acpi_ged_device *geddev;
acpi_status acpi_ret; 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_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)) { if (ACPI_FAILURE(acpi_ret)) {
dev_err(&pdev->dev, "unable to parse the _CRS record\n"); dev_err(&pdev->dev, "unable to parse the _CRS record\n");
return -EINVAL; return -EINVAL;
} }
platform_set_drvdata(pdev, geddev);
return 0; 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[] = { static const struct acpi_device_id ged_acpi_ids[] = {
{"ACPI0013"}, {"ACPI0013"},
{}, {},
...@@ -146,6 +179,8 @@ static const struct acpi_device_id ged_acpi_ids[] = { ...@@ -146,6 +179,8 @@ static const struct acpi_device_id ged_acpi_ids[] = {
static struct platform_driver ged_driver = { static struct platform_driver ged_driver = {
.probe = ged_probe, .probe = ged_probe,
.remove = ged_remove,
.shutdown = ged_shutdown,
.driver = { .driver = {
.name = MODULE_NAME, .name = MODULE_NAME,
.acpi_match_table = ACPI_PTR(ged_acpi_ids), .acpi_match_table = ACPI_PTR(ged_acpi_ids),
......
...@@ -460,8 +460,7 @@ int __init acpi_numa_init(void) ...@@ -460,8 +460,7 @@ int __init acpi_numa_init(void)
srat_proc, ARRAY_SIZE(srat_proc), 0); srat_proc, ARRAY_SIZE(srat_proc), 0);
cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
acpi_parse_memory_affinity, acpi_parse_memory_affinity, 0);
NR_NODE_MEMBLKS);
} }
/* SLIT: System Locality Information Table */ /* SLIT: System Locality Information Table */
......
...@@ -400,7 +400,7 @@ static int intel_bxtwc_pmic_opregion_probe(struct platform_device *pdev) ...@@ -400,7 +400,7 @@ static int intel_bxtwc_pmic_opregion_probe(struct platform_device *pdev)
&intel_bxtwc_pmic_opregion_data); &intel_bxtwc_pmic_opregion_data);
} }
static struct platform_device_id bxt_wc_opregion_id_table[] = { static const struct platform_device_id bxt_wc_opregion_id_table[] = {
{ .name = "bxt_wcove_region" }, { .name = "bxt_wcove_region" },
{}, {},
}; };
...@@ -412,9 +412,4 @@ static struct platform_driver intel_bxtwc_pmic_opregion_driver = { ...@@ -412,9 +412,4 @@ static struct platform_driver intel_bxtwc_pmic_opregion_driver = {
}, },
.id_table = bxt_wc_opregion_id_table, .id_table = bxt_wc_opregion_id_table,
}; };
builtin_platform_driver(intel_bxtwc_pmic_opregion_driver);
static int __init intel_bxtwc_pmic_opregion_driver_init(void)
{
return platform_driver_register(&intel_bxtwc_pmic_opregion_driver);
}
device_initcall(intel_bxtwc_pmic_opregion_driver_init);
...@@ -131,7 +131,4 @@ static struct platform_driver chtdc_ti_pmic_opregion_driver = { ...@@ -131,7 +131,4 @@ static struct platform_driver chtdc_ti_pmic_opregion_driver = {
}, },
.id_table = chtdc_ti_pmic_opregion_id_table, .id_table = chtdc_ti_pmic_opregion_id_table,
}; };
module_platform_driver(chtdc_ti_pmic_opregion_driver); builtin_platform_driver(chtdc_ti_pmic_opregion_driver);
MODULE_DESCRIPTION("Dollar Cove TI PMIC opregion driver");
MODULE_LICENSE("GPL v2");
...@@ -260,11 +260,10 @@ static int intel_cht_wc_pmic_opregion_probe(struct platform_device *pdev) ...@@ -260,11 +260,10 @@ static int intel_cht_wc_pmic_opregion_probe(struct platform_device *pdev)
&intel_cht_wc_pmic_opregion_data); &intel_cht_wc_pmic_opregion_data);
} }
static struct platform_device_id cht_wc_opregion_id_table[] = { static const struct platform_device_id cht_wc_opregion_id_table[] = {
{ .name = "cht_wcove_region" }, { .name = "cht_wcove_region" },
{}, {},
}; };
MODULE_DEVICE_TABLE(platform, cht_wc_opregion_id_table);
static struct platform_driver intel_cht_wc_pmic_opregion_driver = { static struct platform_driver intel_cht_wc_pmic_opregion_driver = {
.probe = intel_cht_wc_pmic_opregion_probe, .probe = intel_cht_wc_pmic_opregion_probe,
...@@ -273,8 +272,4 @@ static struct platform_driver intel_cht_wc_pmic_opregion_driver = { ...@@ -273,8 +272,4 @@ static struct platform_driver intel_cht_wc_pmic_opregion_driver = {
}, },
.id_table = cht_wc_opregion_id_table, .id_table = cht_wc_opregion_id_table,
}; };
module_platform_driver(intel_cht_wc_pmic_opregion_driver); builtin_platform_driver(intel_cht_wc_pmic_opregion_driver);
MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC operation region driver");
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
MODULE_LICENSE("GPL");
...@@ -201,9 +201,4 @@ static struct platform_driver intel_crc_pmic_opregion_driver = { ...@@ -201,9 +201,4 @@ static struct platform_driver intel_crc_pmic_opregion_driver = {
.name = "crystal_cove_pmic", .name = "crystal_cove_pmic",
}, },
}; };
builtin_platform_driver(intel_crc_pmic_opregion_driver);
static int __init intel_crc_pmic_opregion_driver_init(void)
{
return platform_driver_register(&intel_crc_pmic_opregion_driver);
}
device_initcall(intel_crc_pmic_opregion_driver_init);
...@@ -278,9 +278,4 @@ static struct platform_driver intel_xpower_pmic_opregion_driver = { ...@@ -278,9 +278,4 @@ static struct platform_driver intel_xpower_pmic_opregion_driver = {
.name = "axp288_pmic_acpi", .name = "axp288_pmic_acpi",
}, },
}; };
builtin_platform_driver(intel_xpower_pmic_opregion_driver);
static int __init intel_xpower_pmic_opregion_driver_init(void)
{
return platform_driver_register(&intel_xpower_pmic_opregion_driver);
}
device_initcall(intel_xpower_pmic_opregion_driver_init);
...@@ -816,14 +816,8 @@ static ssize_t counter_set(struct kobject *kobj, ...@@ -816,14 +816,8 @@ static ssize_t counter_set(struct kobject *kobj,
* interface: * interface:
* echo unmask > /sys/firmware/acpi/interrupts/gpe00 * echo unmask > /sys/firmware/acpi/interrupts/gpe00
*/ */
#define ACPI_MASKABLE_GPE_MAX 0xFF
/* static DECLARE_BITMAP(acpi_masked_gpes_map, ACPI_MASKABLE_GPE_MAX) __initdata;
* Currently, the GPE flooding prevention only supports to mask the GPEs
* numbered from 00 to 7f.
*/
#define ACPI_MASKABLE_GPE_MAX 0x80
static u64 __initdata acpi_masked_gpes;
static int __init acpi_gpe_set_masked_gpes(char *val) static int __init acpi_gpe_set_masked_gpes(char *val)
{ {
...@@ -831,7 +825,7 @@ static int __init acpi_gpe_set_masked_gpes(char *val) ...@@ -831,7 +825,7 @@ static int __init acpi_gpe_set_masked_gpes(char *val)
if (kstrtou8(val, 0, &gpe) || gpe > ACPI_MASKABLE_GPE_MAX) if (kstrtou8(val, 0, &gpe) || gpe > ACPI_MASKABLE_GPE_MAX)
return -EINVAL; return -EINVAL;
acpi_masked_gpes |= ((u64)1<<gpe); set_bit(gpe, acpi_masked_gpes_map);
return 1; return 1;
} }
...@@ -843,17 +837,13 @@ void __init acpi_gpe_apply_masked_gpes(void) ...@@ -843,17 +837,13 @@ void __init acpi_gpe_apply_masked_gpes(void)
acpi_status status; acpi_status status;
u8 gpe; u8 gpe;
for (gpe = 0; for_each_set_bit(gpe, acpi_masked_gpes_map, ACPI_MASKABLE_GPE_MAX) {
gpe < min_t(u8, ACPI_MASKABLE_GPE_MAX, acpi_current_gpe_count);
gpe++) {
if (acpi_masked_gpes & ((u64)1<<gpe)) {
status = acpi_get_gpe_device(gpe, &handle); status = acpi_get_gpe_device(gpe, &handle);
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
pr_info("Masking GPE 0x%x.\n", gpe); pr_info("Masking GPE 0x%x.\n", gpe);
(void)acpi_mask_gpe(handle, gpe, TRUE); (void)acpi_mask_gpe(handle, gpe, TRUE);
} }
} }
}
} }
void acpi_irq_stats_init(void) void acpi_irq_stats_init(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment