From patchwork Mon Feb 29 12:42:00 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksey Makarov X-Patchwork-Id: 63210 Delivered-To: patch@linaro.org Received: by 10.112.199.169 with SMTP id jl9csp1224557lbc; Mon, 29 Feb 2016 04:44:47 -0800 (PST) X-Received: by 10.98.0.194 with SMTP id 185mr22035660pfa.139.1456749887819; Mon, 29 Feb 2016 04:44:47 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id kg1si3495102pad.81.2016.02.29.04.44.47; Mon, 29 Feb 2016 04:44:47 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dkim=pass header.i=@linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755393AbcB2Mop (ORCPT + 30 others); Mon, 29 Feb 2016 07:44:45 -0500 Received: from mail-lf0-f52.google.com ([209.85.215.52]:36131 "EHLO mail-lf0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754737AbcB2MnP (ORCPT ); Mon, 29 Feb 2016 07:43:15 -0500 Received: by mail-lf0-f52.google.com with SMTP id l83so43119931lfd.3 for ; Mon, 29 Feb 2016 04:43:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=s1HbZqxqlGerrRs+lAYtX2utH34gYofvPeP0AIedyJg=; b=Frn99yPvM72McQlM6MINkvFQDkETqAtxMcaGlEnsdqoTTGr1/Vl/erYWKsLu3EiO1+ +2gE9qGYHblUgMlb38S4/DGtqcIZxVo52eC78kWFaSHueG8F3Wx5OLqQkItSg/87kH0g S4GicT/BvdL9RyJKJ3hkaVCDs7Kr2JV1quE34= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=s1HbZqxqlGerrRs+lAYtX2utH34gYofvPeP0AIedyJg=; b=Ro+TH048sEFllmWFS1NZaF1nvcPo1PNbGR6RE1+hHm3l2h1iE5K4oEuZSIthDroO0O URcI80r5wb2asXsQQ9NbID9OvmupEo2M/9dS6S4ujsjV1O6WzBxqeRRdDOimTK9JSqho nxqwQxEsECiTn10X8Cvz/XU7Gntt6pP+GIt55DkdcsGGL834zrSfikiNBVGTsi86J7c2 hkClqyAm62dmgOsLM3FmslFYtyOtCH/CZl5JyGpldn/5JjxjiJwOR9suWI8yxEf65ui+ vU57h5WvYHhP2mNKdLd1k9+7yrnBlWI9c+SmoqtCEHpRMFd5OBMl7mZ83wSZZ6OCByxM 6OtA== X-Gm-Message-State: AD7BkJLuPv961zqXp/2ysHw0cPeTY4ofg3bHvzZBCuUtIaKMC+IC5UcoGHtWISLXv0oJI0h+ X-Received: by 10.25.161.131 with SMTP id k125mr5452113lfe.83.1456749788926; Mon, 29 Feb 2016 04:43:08 -0800 (PST) Received: from turnip.localdomain (nivc-213.auriga.ru. [80.240.102.213]) by smtp.gmail.com with ESMTPSA id ke9sm3929150lbc.28.2016.02.29.04.43.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 29 Feb 2016 04:43:08 -0800 (PST) From: Aleksey Makarov To: linux-acpi@vger.kernel.org Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Aleksey Makarov , Russell King , Greg Kroah-Hartman , "Rafael J . Wysocki" , Leif Lindholm , Graeme Gregory , Al Stone , Christopher Covington , Matthias Brugger , Len Brown , Daniel Lezcano , Thomas Gleixner , Jason Cooper , Marc Zyngier , John Stultz Subject: [PATCH v3 3/7] ACPI: genaralize iterating over subtables in ACPI_PROBE_TABLE() Date: Mon, 29 Feb 2016 15:42:00 +0300 Message-Id: <1456749726-30261-4-git-send-email-aleksey.makarov@linaro.org> X-Mailer: git-send-email 2.7.1 In-Reply-To: <1456749726-30261-1-git-send-email-aleksey.makarov@linaro.org> References: <1456749726-30261-1-git-send-email-aleksey.makarov@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Refactor ACPI_PROBE_TABLE() so that it is possible to iterate over subtables that do not have acpi_subtype header (for example over subtables of DBG2 table) To do so: - Add void * data pointer argument for callback. It will allow to parse the table and iterate over subtables calling the subtable callbacks that are provided via this data pointer. - Save only ACPI table id, callback and callback data in the linker tables. This makes tables more terse and simplifies the semantics of the fields of it's elements. The additional data that required for subtable parsing are saved in static namespace without increasing the size of linker tables. - Introduce two macros with clear meaning of arguments, instead one. The old ACPI_DECLARE_PROBE_ENTRY() macros has arguments that have different meaning if the entry is for table or for subtable. The arguments of the new macroses ACPI_DECLARE_PROBE_ENTRY() and ACPI_DECLARE_PROBE_SUBTYPE_ENTRY() have unambiguous meaning. - Document arguments of those macroses instead of the fields of linker table data. - Fix the issue that prevents using this macros for parsing subtables other than MADT. In the original code, MADT-specific function was used to iterate over subtables, while the name was common. Introduce a new parameter to macors that specifies the size of the table to do it in common way. - Don't expose the internals of the tables to the drivers passing a pointer to struct acpi_probe_entry to the subtable callback validator. Instead, pass the sideband data specified by the driver. - Fix the driver's callback signatures: a. Add an unused pointer to void for table matchers (currently only clocksource callback) b. Change the type of sideband data to kernel_ulong_t. Signed-off-by: Aleksey Makarov --- drivers/acpi/scan.c | 44 ++++++++++----- drivers/clocksource/arm_arch_timer.c | 3 +- drivers/irqchip/irq-gic.c | 4 +- include/linux/acpi.h | 104 ++++++++++++++++++++++++----------- include/linux/clocksource.h | 2 +- include/linux/irqchip.h | 5 +- 6 files changed, 109 insertions(+), 53 deletions(-) -- 2.7.1 diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5f28cf7..09b5f63 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1969,16 +1969,38 @@ static struct acpi_probe_entry *ape; static int acpi_probe_count; static DEFINE_SPINLOCK(acpi_probe_lock); -static int __init acpi_match_madt(struct acpi_subtable_header *header, - const unsigned long end) +static int __init acpi_match_and_setup(struct acpi_subtable_header *header, + const unsigned long end) { - if (!ape->subtable_valid || ape->subtable_valid(header, ape)) - if (!ape->probe_subtbl(header, end)) + const struct acpi_probe_subtype_data *data = ape->data; + + if (data->valid(header, data->data)) + if (!data->setup(header, end)) acpi_probe_count++; return 0; } +int __init acpi_probe_subtype_setup(struct acpi_table_header *table, + const void *data) +{ + const struct acpi_probe_subtype_data *data_subtype = data; + + return acpi_parse_entries(ape->id, data_subtype->size, + acpi_match_and_setup, table, + data_subtype->subtype, 0); +} + +static int __init acpi_probe_table_handler(struct acpi_table_header *table) +{ + int err = ape->setup(table, ape->data); + + if (ape->setup != acpi_probe_subtype_setup && err >= 0) + acpi_probe_count++; + + return err; +} + int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr) { int count = 0; @@ -1988,16 +2010,10 @@ int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr) spin_lock(&acpi_probe_lock); for (ape = ap_head; nr; ape++, nr--) { - if (ACPI_COMPARE_NAME(ACPI_SIG_MADT, ape->id)) { - acpi_probe_count = 0; - acpi_table_parse_madt(ape->type, acpi_match_madt, 0); - count += acpi_probe_count; - } else { - int res; - res = acpi_table_parse(ape->id, ape->probe_table); - if (!res) - count++; - } + acpi_probe_count = 0; + if (acpi_table_parse(ape->id, acpi_probe_table_handler) < 0) + continue; + count += acpi_probe_count; } spin_unlock(&acpi_probe_lock); diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index f492ced..c0df7cb 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -868,7 +868,8 @@ static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags) } /* Initialize per-processor generic timer */ -static int __init arch_timer_acpi_init(struct acpi_table_header *table) +static int __init arch_timer_acpi_init(struct acpi_table_header *table, + const void *data) { struct acpi_table_gtdt *gtdt; diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 282344b..13d8323 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -1287,12 +1287,12 @@ static bool __init acpi_gic_redist_is_present(void) } static bool __init gic_validate_dist(struct acpi_subtable_header *header, - struct acpi_probe_entry *ape) + kernel_ulong_t driver_data) { struct acpi_madt_generic_distributor *dist; dist = (struct acpi_madt_generic_distributor *)header; - return (dist->version == ape->driver_data && + return (dist->version == driver_data && (dist->version != ACPI_MADT_GIC_VERSION_NONE || !acpi_gic_redist_is_present())); } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 06ed7e5..9636c32 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -879,47 +879,76 @@ int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, struct fwnode_handle *acpi_get_next_subnode(struct device *dev, struct fwnode_handle *subnode); -struct acpi_probe_entry; typedef bool (*acpi_probe_entry_validate_subtbl)(struct acpi_subtable_header *, - struct acpi_probe_entry *); + kernel_ulong_t); + +typedef int (*acpi_probe_entry_setup)(struct acpi_table_header *, const void *); #define ACPI_TABLE_ID_LEN 5 -/** - * struct acpi_probe_entry - boot-time probing entry - * @id: ACPI table name - * @type: Optional subtable type to match - * (if @id contains subtables) - * @subtable_valid: Optional callback to check the validity of - * the subtable - * @probe_table: Callback to the driver being probed when table - * match is successful - * @probe_subtbl: Callback to the driver being probed when table and - * subtable match (and optional callback is successful) - * @driver_data: Sideband data provided back to the driver - */ struct acpi_probe_entry { __u8 id[ACPI_TABLE_ID_LEN]; - __u8 type; - acpi_probe_entry_validate_subtbl subtable_valid; - union { - acpi_tbl_table_handler probe_table; - acpi_tbl_entry_handler probe_subtbl; - }; - kernel_ulong_t driver_data; + acpi_probe_entry_setup setup; + const void *data; }; -#define ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, subtable, valid, data, fn) \ +/** + * ACPI_DECLARE_PROBE_ENTRY() - declare boot-time probing entry + * @table: Name of subsystem to match + * @name: Identifier to compose name of table data + * @table_id: ACPI table name + * @setup_fn: Callback to the driver being probed when table + * matches (of type acpi_probe_entry_setup) + * @data_ptr: Sideband data provided back to the driver + */ +#define ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, setup_fn, data_ptr) \ static const struct acpi_probe_entry __acpi_probe_##name \ __used __section(__##table##_acpi_probe_table) \ = { \ .id = table_id, \ - .type = subtable, \ - .subtable_valid = valid, \ - .probe_table = (acpi_tbl_table_handler)fn, \ - .driver_data = data, \ + .setup = setup_fn, \ + .data = data_ptr, \ } +struct acpi_probe_subtype_data { + u8 subtype; + unsigned long size; + acpi_probe_entry_validate_subtbl valid; + acpi_tbl_entry_handler setup; + kernel_ulong_t data; +}; + +int acpi_probe_subtype_setup(struct acpi_table_header *table, const void *data); + +/** + * ACPI_DECLARE_PROBE_SUBTYPE_ENTRY() - declare boot-time probing entry that + * matches subtables + * @table: Name of subsystem to match + * @name: Identifier to compose name of table data + * @table_id: ACPI table name + * @table_size: Size of the table (without subtables) of type table_id + * @subtable: Subtable type to match + * @valid_fn: Callback to check the validity of the subtable + * (of type acpi_probe_entry_validate_subtbl) + * @data_int: Sideband data provided back to the driver + * (of type kernel_ulong_t) + * @setup_fn: Callback to the driver being probed when table and + * subtable match and valid_fn callback is successful + * (of type acpi_tbl_entry_handler) + */ +#define ACPI_DECLARE_PROBE_SUBTYPE_ENTRY(table, name, table_id, table_size, \ + subtable, valid_fn, data_int, setup_fn) \ + static const struct acpi_probe_subtype_data \ + __acpi_probe_subtype_##name __used = { \ + .subtype = subtable, \ + .size = table_size, \ + .valid = valid_fn, \ + .setup = setup_fn, \ + .data = data_int, \ + }; \ + ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, \ + acpi_probe_subtype_setup, &__acpi_probe_subtype_##name) + #define ACPI_PROBE_TABLE(name) __##name##_acpi_probe_table #define ACPI_PROBE_TABLE_END(name) __##name##_acpi_probe_table_end @@ -992,14 +1021,23 @@ static inline struct fwnode_handle *acpi_get_next_subnode(struct device *dev, return NULL; } -#define ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, subtable, validate, data, fn) \ +#define ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, match, data) \ static const void * __acpi_table_##name[] \ __attribute__((unused)) \ - = { (void *) table_id, \ - (void *) subtable, \ - (void *) valid, \ - (void *) fn, \ - (void *) data } + = { (void *)table_id, \ + (void *)match, \ + (void *)data } + +#define ACPI_DECLARE_PROBE_SUBTYPE_ENTRY(table, name, table_id, table_size, \ + subtable, valid_fn, data_int, setup_fn) \ + static const void *__acpi_table_##name[] \ + __attribute__((unused)) \ + = { (void *)table_id, \ + (void *)table_size, \ + (void *)subtable, \ + (void *)valid_fn, \ + (void *)data_int, \ + (void *)setup_fn } #define acpi_probe_device_table(t) ({ int __r = 0; __r;}) #endif diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 6013021..2bb5d51 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -259,6 +259,6 @@ static inline void clocksource_probe(void) {} #endif #define CLOCKSOURCE_ACPI_DECLARE(name, table_id, fn) \ - ACPI_DECLARE_PROBE_ENTRY(clksrc, name, table_id, 0, NULL, 0, fn) + ACPI_DECLARE_PROBE_ENTRY(clksrc, name, table_id, fn, NULL) #endif /* _LINUX_CLOCKSOURCE_H */ diff --git a/include/linux/irqchip.h b/include/linux/irqchip.h index 89c34b2..cc4c455 100644 --- a/include/linux/irqchip.h +++ b/include/linux/irqchip.h @@ -39,8 +39,9 @@ * @fn: initialization function */ #define IRQCHIP_ACPI_DECLARE(name, subtable, validate, data, fn) \ - ACPI_DECLARE_PROBE_ENTRY(irqchip, name, ACPI_SIG_MADT, \ - subtable, validate, data, fn) + ACPI_DECLARE_PROBE_SUBTYPE_ENTRY(irqchip, name, ACPI_SIG_MADT, \ + sizeof(struct acpi_table_madt),\ + subtable, validate, data, fn) #ifdef CONFIG_IRQCHIP void irqchip_init(void);