diff options
101 files changed, 1315 insertions, 665 deletions
diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt index 9b121a569ab4..750401f91341 100644 --- a/Documentation/acpi/enumeration.txt +++ b/Documentation/acpi/enumeration.txt @@ -254,8 +254,13 @@ GPIO support ~~~~~~~~~~~~ ACPI 5 introduced two new resources to describe GPIO connections: GpioIo and GpioInt. These resources are used be used to pass GPIO numbers used by -the device to the driver. For example: +the device to the driver. ACPI 5.1 extended this with _DSD (Device +Specific Data) which made it possible to name the GPIOs among other things. +For example: + +Device (DEV) +{ Method (_CRS, 0, NotSerialized) { Name (SBUF, ResourceTemplate() @@ -285,6 +290,18 @@ the device to the driver. For example: Return (SBUF) } + // ACPI 5.1 _DSD used for naming the GPIOs + Name (_DSD, Package () + { + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + Package () + { + Package () {"power-gpios", Package() {^DEV, 0, 0, 0 }}, + Package () {"irq-gpios", Package() {^DEV, 1, 0, 0 }}, + } + }) + ... + These GPIO numbers are controller relative and path "\\_SB.PCI0.GPI0" specifies the path to the controller. In order to use these GPIOs in Linux we need to translate them to the corresponding Linux GPIO descriptors. @@ -300,11 +317,11 @@ a code like this: struct gpio_desc *irq_desc, *power_desc; - irq_desc = gpiod_get_index(dev, NULL, 1); + irq_desc = gpiod_get(dev, "irq"); if (IS_ERR(irq_desc)) /* handle error */ - power_desc = gpiod_get_index(dev, NULL, 0); + power_desc = gpiod_get(dev, "power"); if (IS_ERR(power_desc)) /* handle error */ @@ -313,6 +330,9 @@ a code like this: There are also devm_* versions of these functions which release the descriptors once the device is released. +See Documentation/acpi/gpio-properties.txt for more information about the +_DSD binding related to GPIOs. + MFD devices ~~~~~~~~~~~ The MFD devices register their children as platform devices. For the child diff --git a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt index 43404b197933..332e625f6ed0 100644 --- a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt @@ -4,7 +4,7 @@ Required properties: - compatible : "renesas,thermal-<soctype>", "renesas,rcar-thermal" as fallback. Examples with soctypes are: - - "renesas,thermal-r8a73a4" (R-Mobile AP6) + - "renesas,thermal-r8a73a4" (R-Mobile APE6) - "renesas,thermal-r8a7779" (R-Car H1) - "renesas,thermal-r8a7790" (R-Car H2) - "renesas,thermal-r8a7791" (R-Car M2-W) @@ -1,7 +1,7 @@ VERSION = 4 PATCHLEVEL = 0 SUBLEVEL = 0 -EXTRAVERSION = -rc7 +EXTRAVERSION = NAME = Hurr durr I'ma sheep # *DOCUMENTATION* diff --git a/arch/arm/include/asm/cpuidle.h b/arch/arm/include/asm/cpuidle.h index af319ac4960c..0f8424924902 100644 --- a/arch/arm/include/asm/cpuidle.h +++ b/arch/arm/include/asm/cpuidle.h @@ -1,6 +1,8 @@ #ifndef __ASM_ARM_CPUIDLE_H #define __ASM_ARM_CPUIDLE_H +#include <asm/proc-fns.h> + #ifdef CONFIG_CPU_IDLE extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index); @@ -25,4 +27,25 @@ static inline int arm_cpuidle_simple_enter(struct cpuidle_device *dev, */ #define ARM_CPUIDLE_WFI_STATE ARM_CPUIDLE_WFI_STATE_PWR(UINT_MAX) +struct device_node; + +struct cpuidle_ops { + int (*suspend)(int cpu, unsigned long arg); + int (*init)(struct device_node *, int cpu); +}; + +struct of_cpuidle_method { + const char *method; + struct cpuidle_ops *ops; +}; + +#define CPUIDLE_METHOD_OF_DECLARE(name, _method, _ops) \ + static const struct of_cpuidle_method __cpuidle_method_of_table_##name \ + __used __section(__cpuidle_method_of_table) \ + = { .method = _method, .ops = _ops } + +extern int arm_cpuidle_suspend(int index); + +extern int arm_cpuidle_init(int cpu); + #endif diff --git a/arch/arm/kernel/cpuidle.c b/arch/arm/kernel/cpuidle.c index 89545f6c8403..318da33465f4 100644 --- a/arch/arm/kernel/cpuidle.c +++ b/arch/arm/kernel/cpuidle.c @@ -10,8 +10,28 @@ */ #include <linux/cpuidle.h> -#include <asm/proc-fns.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <asm/cpuidle.h> +extern struct of_cpuidle_method __cpuidle_method_of_table[]; + +static const struct of_cpuidle_method __cpuidle_method_of_table_sentinel + __used __section(__cpuidle_method_of_table_end); + +static struct cpuidle_ops cpuidle_ops[NR_CPUS]; + +/** + * arm_cpuidle_simple_enter() - a wrapper to cpu_do_idle() + * @dev: not used + * @drv: not used + * @index: not used + * + * A trivial wrapper to allow the cpu_do_idle function to be assigned as a + * cpuidle callback by matching the function signature. + * + * Returns the index passed as parameter + */ int arm_cpuidle_simple_enter(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { @@ -19,3 +39,114 @@ int arm_cpuidle_simple_enter(struct cpuidle_device *dev, return index; } + +/** + * arm_cpuidle_suspend() - function to enter low power idle states + * @index: an integer used as an identifier for the low level PM callbacks + * + * This function calls the underlying arch specific low level PM code as + * registered at the init time. + * + * Returns -EOPNOTSUPP if no suspend callback is defined, the result of the + * callback otherwise. + */ +int arm_cpuidle_suspend(int index) +{ + int ret = -EOPNOTSUPP; + int cpu = smp_processor_id(); + + if (cpuidle_ops[cpu].suspend) + ret = cpuidle_ops[cpu].suspend(cpu, index); + + return ret; +} + +/** + * arm_cpuidle_get_ops() - find a registered cpuidle_ops by name + * @method: the method name + * + * Search in the __cpuidle_method_of_table array the cpuidle ops matching the + * method name. + * + * Returns a struct cpuidle_ops pointer, NULL if not found. + */ +static struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method) +{ + struct of_cpuidle_method *m = __cpuidle_method_of_table; + + for (; m->method; m++) + if (!strcmp(m->method, method)) + return m->ops; + + return NULL; +} + +/** + * arm_cpuidle_read_ops() - Initialize the cpuidle ops with the device tree + * @dn: a pointer to a struct device node corresponding to a cpu node + * @cpu: the cpu identifier + * + * Get the method name defined in the 'enable-method' property, retrieve the + * associated cpuidle_ops and do a struct copy. This copy is needed because all + * cpuidle_ops are tagged __initdata and will be unloaded after the init + * process. + * + * Return 0 on sucess, -ENOENT if no 'enable-method' is defined, -EOPNOTSUPP if + * no cpuidle_ops is registered for the 'enable-method'. + */ +static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu) +{ + const char *enable_method; + struct cpuidle_ops *ops; + + enable_method = of_get_property(dn, "enable-method", NULL); + if (!enable_method) + return -ENOENT; + + ops = arm_cpuidle_get_ops(enable_method); + if (!ops) { + pr_warn("%s: unsupported enable-method property: %s\n", + dn->full_name, enable_method); + return -EOPNOTSUPP; + } + + cpuidle_ops[cpu] = *ops; /* structure copy */ + + pr_notice("cpuidle: enable-method property '%s'" + " found operations\n", enable_method); + + return 0; +} + +/** + * arm_cpuidle_init() - Initialize cpuidle_ops for a specific cpu + * @cpu: the cpu to be initialized + * + * Initialize the cpuidle ops with the device for the cpu and then call + * the cpu's idle initialization callback. This may fail if the underlying HW + * is not operational. + * + * Returns: + * 0 on success, + * -ENODEV if it fails to find the cpu node in the device tree, + * -EOPNOTSUPP if it does not find a registered cpuidle_ops for this cpu, + * -ENOENT if it fails to find an 'enable-method' property, + * -ENXIO if the HW reports a failure or a misconfiguration, + * -ENOMEM if the HW report an memory allocation failure + */ +int __init arm_cpuidle_init(int cpu) +{ + struct device_node *cpu_node = of_cpu_device_node_get(cpu); + int ret; + + if (!cpu_node) + return -ENODEV; + + ret = arm_cpuidle_read_ops(cpu_node, cpu); + if (!ret && cpuidle_ops[cpu].init) + ret = cpuidle_ops[cpu].init(cpu_node, cpu); + + of_node_put(cpu_node); + + return ret; +} diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index e365c1bb1265..306ebc51599a 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -17,7 +17,6 @@ #include <linux/cpuidle.h> #include <linux/io.h> #include <linux/export.h> -#include <asm/proc-fns.h> #include <asm/cpuidle.h> #include <mach/cpuidle.h> diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c index d76d08623f9f..8e21ccc1eda2 100644 --- a/arch/arm/mach-imx/cpuidle-imx6q.c +++ b/arch/arm/mach-imx/cpuidle-imx6q.c @@ -9,7 +9,6 @@ #include <linux/cpuidle.h> #include <linux/module.h> #include <asm/cpuidle.h> -#include <asm/proc-fns.h> #include "common.h" #include "cpuidle.h" diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c index 7d92e6584551..5742a9fd1ef2 100644 --- a/arch/arm/mach-imx/cpuidle-imx6sl.c +++ b/arch/arm/mach-imx/cpuidle-imx6sl.c @@ -9,7 +9,6 @@ #include <linux/cpuidle.h> #include <linux/module.h> #include <asm/cpuidle.h> -#include <asm/proc-fns.h> #include "common.h" #include "cpuidle.h" diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c index 5a36722b089d..2c9f1a8bf245 100644 --- a/arch/arm/mach-imx/cpuidle-imx6sx.c +++ b/arch/arm/mach-imx/cpuidle-imx6sx.c @@ -10,7 +10,6 @@ #include <linux/cpu_pm.h> #include <linux/module.h> #include <asm/cpuidle.h> -#include <asm/proc-fns.h> #include <asm/suspend.h> #include "common.h" diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c index 01e398a868bc..7622dbb05083 100644 --- a/arch/arm/mach-omap2/cpuidle44xx.c +++ b/arch/arm/mach-omap2/cpuidle44xx.c @@ -17,7 +17,6 @@ #include <linux/clockchips.h> #include <asm/cpuidle.h> -#include <asm/proc-fns.h> #include "common.h" #include "pm.h" diff --git a/arch/arm/mach-s3c64xx/cpuidle.c b/arch/arm/mach-s3c64xx/cpuidle.c index 2eb072440dfa..93aa8cb70195 100644 --- a/arch/arm/mach-s3c64xx/cpuidle.c +++ b/arch/arm/mach-s3c64xx/cpuidle.c @@ -16,7 +16,7 @@ #include <linux/export.h> #include <linux/time.h> -#include <asm/proc-fns.h> +#include <asm/cpuidle.h> #include <mach/map.h> diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c index 4f25a7c7ca0f..e22b0d9fdc88 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra20.c +++ b/arch/arm/mach-tegra/cpuidle-tegra20.c @@ -27,7 +27,6 @@ #include <linux/module.h> #include <asm/cpuidle.h> -#include <asm/proc-fns.h> #include <asm/smp_plat.h> #include <asm/suspend.h> diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c index f8815ed65d9d..a2400ab44daa 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra30.c +++ b/arch/arm/mach-tegra/cpuidle-tegra30.c @@ -27,7 +27,6 @@ #include <linux/module.h> #include <asm/cpuidle.h> -#include <asm/proc-fns.h> #include <asm/smp_plat.h> #include <asm/suspend.h> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index be1f12a5a5f0..af6a452b1aac 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -48,7 +48,7 @@ CONFIG_CMDLINE="console=ttyAMA0" # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_COMPAT=y CONFIG_CPU_IDLE=y -CONFIG_ARM64_CPUIDLE=y +CONFIG_ARM_CPUIDLE=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y diff --git a/arch/arm64/include/asm/cpuidle.h b/arch/arm64/include/asm/cpuidle.h index c60643f14cda..141b2fcabaa6 100644 --- a/arch/arm64/include/asm/cpuidle.h +++ b/arch/arm64/include/asm/cpuidle.h @@ -4,10 +4,10 @@ #include <asm/proc-fns.h> #ifdef CONFIG_CPU_IDLE -extern int cpu_init_idle(unsigned int cpu); +extern int arm_cpuidle_init(unsigned int cpu); extern int cpu_suspend(unsigned long arg); #else -static inline int cpu_init_idle(unsigned int cpu) +static inline int arm_cpuidle_init(unsigned int cpu) { return -EOPNOTSUPP; } @@ -17,5 +17,8 @@ static inline int cpu_suspend(unsigned long arg) return -EOPNOTSUPP; } #endif - +static inline int arm_cpuidle_suspend(int index) +{ + return cpu_suspend(index); +} #endif diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c index 5c0896647fd1..a78143a5c99f 100644 --- a/arch/arm64/kernel/cpuidle.c +++ b/arch/arm64/kernel/cpuidle.c @@ -15,7 +15,7 @@ #include <asm/cpuidle.h> #include <asm/cpu_ops.h> -int cpu_init_idle(unsigned int cpu) +int arm_cpuidle_init(unsigned int cpu) { int ret = -EOPNOTSUPP; struct device_node *cpu_node = of_cpu_device_node_get(cpu); diff --git a/arch/nios2/include/asm/thread_info.h b/arch/nios2/include/asm/thread_info.h index 1f266575beb5..a16e55cbd8ad 100644 --- a/arch/nios2/include/asm/thread_info.h +++ b/arch/nios2/include/asm/thread_info.h @@ -47,7 +47,6 @@ struct thread_info { 0-0x7FFFFFFF for user-thead 0-0xFFFFFFFF for kernel-thread */ - struct restart_block restart_block; struct pt_regs *regs; }; @@ -64,9 +63,6 @@ struct thread_info { .cpu = 0, \ .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ - .restart_block = { \ - .fn = do_no_restart_syscall, \ - }, \ } #define init_thread_info (init_thread_union.thread_info) diff --git a/arch/nios2/include/uapi/asm/ptrace.h b/arch/nios2/include/uapi/asm/ptrace.h index 71a330597adf..eff00e67c0a2 100644 --- a/arch/nios2/include/uapi/asm/ptrace.h +++ b/arch/nios2/include/uapi/asm/ptrace.h @@ -60,12 +60,17 @@ #define PTR_IPENDING 37 #define PTR_CPUID 38 #define PTR_CTL6 39 -#define PTR_CTL7 40 +#define PTR_EXCEPTION 40 #define PTR_PTEADDR 41 #define PTR_TLBACC 42 #define PTR_TLBMISC 43 +#define PTR_ECCINJ 44 +#define PTR_BADADDR 45 +#define PTR_CONFIG 46 +#define PTR_MPUBASE 47 +#define PTR_MPUACC 48 -#define NUM_PTRACE_REG (PTR_TLBMISC + 1) +#define NUM_PTRACE_REG (PTR_MPUACC + 1) /* User structures for general purpose registers. */ struct user_pt_regs { diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S index 7729bd3f2e79..27b006c52e12 100644 --- a/arch/nios2/kernel/entry.S +++ b/arch/nios2/kernel/entry.S @@ -161,7 +161,7 @@ ENTRY(inthandler) *********************************************************************** */ ENTRY(handle_trap) - ldw r24, -4(ea) /* instruction that caused the exception */ + ldwio r24, -4(ea) /* instruction that caused the exception */ srli r24, r24, 4 andi r24, r24, 0x7c movia r9,trap_table diff --git a/arch/nios2/kernel/signal.c b/arch/nios2/kernel/signal.c index dda41e4fe707..20662b0f6c9e 100644 --- a/arch/nios2/kernel/signal.c +++ b/arch/nios2/kernel/signal.c @@ -43,7 +43,7 @@ static inline int rt_restore_ucontext(struct pt_regs *regs, int err; /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; + current->restart_block.fn = do_no_restart_syscall; err = __get_user(temp, &uc->uc_mcontext.version); if (temp != MCONTEXT_VERSION) diff --git a/arch/nios2/mm/cacheflush.c b/arch/nios2/mm/cacheflush.c index 2ae482b42669..796642932e2e 100644 --- a/arch/nios2/mm/cacheflush.c +++ b/arch/nios2/mm/cacheflush.c @@ -23,9 +23,6 @@ static void __flush_dcache(unsigned long start, unsigned long end) end += (cpuinfo.dcache_line_size - 1); end &= ~(cpuinfo.dcache_line_size - 1); - if (end > start + cpuinfo.dcache_size) - end = start + cpuinfo.dcache_size; - for (addr = start; addr < end; addr += cpuinfo.dcache_line_size) { __asm__ __volatile__ (" flushda 0(%0)\n" : /* Outputs */ diff --git a/block/blk-mq.c b/block/blk-mq.c index b7b8933ec241..33c428530193 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1457,7 +1457,7 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set, do { page = alloc_pages_node(set->numa_node, - GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY, + GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO, this_order); if (page) break; @@ -1479,8 +1479,6 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set, left -= to_do * rq_size; for (j = 0; j < to_do; j++) { tags->rqs[i] = p; - tags->rqs[i]->atomic_flags = 0; - tags->rqs[i]->cmd_flags = 0; if (set->ops->init_request) { if (set->ops->init_request(set->driver_data, tags->rqs[i], hctx_idx, i, diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 1284138e42ab..4bf75597f732 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -102,7 +102,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev) pdevinfo.id = -1; pdevinfo.res = resources; pdevinfo.num_res = count; - pdevinfo.acpi_node.companion = adev; + pdevinfo.fwnode = acpi_fwnode_handle(adev); pdevinfo.dma_mask = DMA_BIT_MASK(32); pdev = platform_device_register_full(&pdevinfo); if (IS_ERR(pdev)) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index d98ba4355819..baebd1a9b811 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -530,8 +530,8 @@ static int acpi_battery_get_state(struct acpi_battery *battery) battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN && (s16)(battery->rate_now) < 0) { battery->rate_now = abs((s16)battery->rate_now); - printk_once(KERN_WARNING FW_BUG "battery: (dis)charge rate" - " invalid.\n"); + printk_once(KERN_WARNING FW_BUG + "battery: (dis)charge rate invalid.\n"); } if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 9b693d54c743..1d1791935c31 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -215,6 +215,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { .callback = dmi_disable_osi_vista, + .ident = "VGN-SR19XN", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR19XN"), + }, + }, + { + .callback = dmi_disable_osi_vista, .ident = "Toshiba Satellite L355", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index d9339b442a4e..a688aa243f6c 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -615,7 +615,7 @@ void acpi_dock_add(struct acpi_device *adev) memset(&pdevinfo, 0, sizeof(pdevinfo)); pdevinfo.name = "dock"; pdevinfo.id = dock_station_count; - pdevinfo.acpi_node.companion = adev; + pdevinfo.fwnode = acpi_fwnode_handle(adev); pdevinfo.data = &ds; pdevinfo.size_data = sizeof(ds); dd = platform_device_register_full(&pdevinfo); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index a8dd2f763382..220d6406c9e9 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -137,6 +137,50 @@ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */ /* -------------------------------------------------------------------------- + * Logging/Debugging + * -------------------------------------------------------------------------- */ + +/* + * Splitters used by the developers to track the boundary of the EC + * handling processes. + */ +#ifdef DEBUG +#define EC_DBG_SEP " " +#define EC_DBG_DRV "+++++" +#define EC_DBG_STM "=====" +#define EC_DBG_REQ "*****" +#define EC_DBG_EVT "#####" +#else +#define EC_DBG_SEP "" +#define EC_DBG_DRV +#define EC_DBG_STM +#define EC_DBG_REQ +#define EC_DBG_EVT +#endif + +#define ec_log_raw(fmt, ...) \ + pr_info(fmt "\n", ##__VA_ARGS__) +#define ec_dbg_raw(fmt, ...) \ + pr_debug(fmt "\n", ##__VA_ARGS__) +#define ec_log(filter, fmt, ...) \ + ec_log_raw(filter EC_DBG_SEP fmt EC_DBG_SEP filter, ##__VA_ARGS__) +#define ec_dbg(filter, fmt, ...) \ + ec_dbg_raw(filter EC_DBG_SEP fmt EC_DBG_SEP filter, ##__VA_ARGS__) + +#define ec_log_drv(fmt, ...) \ + ec_log(EC_DBG_DRV, fmt, ##__VA_ARGS__) +#define ec_dbg_drv(fmt, ...) \ + ec_dbg(EC_DBG_DRV, fmt, ##__VA_ARGS__) +#define ec_dbg_stm(fmt, ...) \ + ec_dbg(EC_DBG_STM, fmt, ##__VA_ARGS__) +#define ec_dbg_req(fmt, ...) \ + ec_dbg(EC_DBG_REQ, fmt, ##__VA_ARGS__) +#define ec_dbg_evt(fmt, ...) \ + ec_dbg(EC_DBG_EVT, fmt, ##__VA_ARGS__) +#define ec_dbg_ref(ec, fmt, ...) \ + ec_dbg_raw("%lu: " fmt, ec->reference_count, ## __VA_ARGS__) + +/* -------------------------------------------------------------------------- * Device Flags * -------------------------------------------------------------------------- */ @@ -159,14 +203,14 @@ static inline u8 acpi_ec_read_status(struct acpi_ec *ec) { u8 x = inb(ec->command_addr); - pr_debug("EC_SC(R) = 0x%2.2x " - "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d\n", - x, - !!(x & ACPI_EC_FLAG_SCI), - !!(x & ACPI_EC_FLAG_BURST), - !!(x & ACPI_EC_FLAG_CMD), - !!(x & ACPI_EC_FLAG_IBF), - !!(x & ACPI_EC_FLAG_OBF)); + ec_dbg_raw("EC_SC(R) = 0x%2.2x " + "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d", + x, + !!(x & ACPI_EC_FLAG_SCI), + !!(x & ACPI_EC_FLAG_BURST), + !!(x & ACPI_EC_FLAG_CMD), + !!(x & ACPI_EC_FLAG_IBF), + !!(x & ACPI_EC_FLAG_OBF)); return x; } @@ -175,20 +219,20 @@ static inline u8 acpi_ec_read_data(struct acpi_ec *ec) u8 x = inb(ec->data_addr); ec->curr->timestamp = jiffies; - pr_debug("EC_DATA(R) = 0x%2.2x\n", x); + ec_dbg_raw("EC_DATA(R) = 0x%2.2x", x); return x; } static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) { - pr_debug("EC_SC(W) = 0x%2.2x\n", command); + ec_dbg_raw("EC_SC(W) = 0x%2.2x", command); outb(command, ec->command_addr); ec->curr->timestamp = jiffies; } static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) { - pr_debug("EC_DATA(W) = 0x%2.2x\n", data); + ec_dbg_raw("EC_DATA(W) = 0x%2.2x", data); outb(data, ec->data_addr); ec->curr->timestamp = jiffies; } @@ -240,7 +284,7 @@ static inline void acpi_ec_enable_gpe(struct acpi_ec *ec, bool open) * software need to manually trigger a pseudo GPE event on * EN=1 writes. */ - pr_debug("***** Polling quirk *****\n"); + ec_dbg_raw("Polling quirk"); advance_transaction(ec); } } @@ -299,7 +343,7 @@ static void acpi_ec_set_storm(struct acpi_ec *ec, u8 flag) { if (!test_bit(flag, &ec->flags)) { acpi_ec_disable_gpe(ec, false); - pr_debug("+++++ Polling enabled +++++\n"); + ec_dbg_drv("Polling enabled"); set_bit(flag, &ec->flags); } } @@ -309,7 +353,7 @@ static void acpi_ec_clear_storm(struct acpi_ec *ec, u8 flag) if (test_bit(flag, &ec->flags)) { clear_bit(flag, &ec->flags); acpi_ec_enable_gpe(ec, false); - pr_debug("+++++ Polling disabled +++++\n"); + ec_dbg_drv("Polling disabled"); } } @@ -335,7 +379,7 @@ static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec) static void acpi_ec_submit_query(struct acpi_ec *ec) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { - pr_debug("***** Event started *****\n"); + ec_dbg_req("Event started"); schedule_work(&ec->work); } } @@ -344,7 +388,7 @@ static void acpi_ec_complete_query(struct acpi_ec *ec) { if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); - pr_debug("***** Event stopped *****\n"); + ec_dbg_req("Event stopped"); } } @@ -366,8 +410,8 @@ static void advance_transaction(struct acpi_ec *ec) u8 status; bool wakeup = false; - pr_debug("===== %s (%d) =====\n", - in_interrupt() ? "IRQ" : "TASK", smp_processor_id()); + ec_dbg_stm("%s (%d)", in_interrupt() ? "IRQ" : "TASK", + smp_processor_id()); /* * By always clearing STS before handling all indications, we can * ensure a hardware STS 0->1 change after this clearing can always @@ -390,8 +434,8 @@ static void advance_transaction(struct acpi_ec *ec) if (t->rlen == t->ri) { t->flags |= ACPI_EC_COMMAND_COMPLETE; if (t->command == ACPI_EC_COMMAND_QUERY) - pr_debug("***** Command(%s) hardware completion *****\n", - acpi_ec_cmd_string(t->command)); + ec_dbg_req("Command(%s) hardware completion", + acpi_ec_cmd_string(t->command)); wakeup = true; } } else @@ -410,8 +454,8 @@ static void advance_transaction(struct acpi_ec *ec) acpi_ec_complete_query(ec); t->rdata[t->ri++] = 0x00; t->flags |= ACPI_EC_COMMAND_COMPLETE; - pr_debug("***** Command(%s) software completion *****\n", - acpi_ec_cmd_string(t->command)); + ec_dbg_req("Command(%s) software completion", + acpi_ec_cmd_string(t->command)); wakeup = true; } else if ((status & ACPI_EC_FLAG_IBF) == 0) { acpi_ec_write_cmd(ec, t->command); @@ -502,21 +546,21 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, ret = -EINVAL; goto unlock; } + ec_dbg_ref(ec, "Increase command"); /* following two actions should be kept atomic */ ec->curr = t; - pr_debug("***** Command(%s) started *****\n", - acpi_ec_cmd_string(t->command)); + ec_dbg_req("Command(%s) started", acpi_ec_cmd_string(t->command)); start_transaction(ec); spin_unlock_irqrestore(&ec->lock, tmp); ret = ec_poll(ec); spin_lock_irqsave(&ec->lock, tmp); if (t->irq_count == ec_storm_threshold) acpi_ec_clear_storm(ec, EC_FLAGS_COMMAND_STORM); - pr_debug("***** Command(%s) stopped *****\n", - acpi_ec_cmd_string(t->command)); + ec_dbg_req("Command(%s) stopped", acpi_ec_cmd_string(t->command)); ec->curr = NULL; /* Disable GPE for command processing (IBF=0/OBF=1) */ acpi_ec_complete_request(ec); + ec_dbg_ref(ec, "Decrease command"); unlock: spin_unlock_irqrestore(&ec->lock, tmp); return ret; @@ -676,11 +720,13 @@ static void acpi_ec_start(struct acpi_ec *ec, bool resuming) spin_lock_irqsave(&ec->lock, flags); if (!test_and_set_bit(EC_FLAGS_STARTED, &ec->flags)) { - pr_debug("+++++ Starting EC +++++\n"); + ec_dbg_drv("Starting EC"); /* Enable GPE for event processing (SCI_EVT=1) */ - if (!resuming) + if (!resuming) { acpi_ec_submit_request(ec); - pr_debug("EC started\n"); + ec_dbg_ref(ec, "Increase driver"); + } + ec_log_drv("EC started"); } spin_unlock_irqrestore(&ec->lock, flags); } @@ -702,17 +748,19 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending) spin_lock_irqsave(&ec->lock, flags); if (acpi_ec_started(ec)) { - pr_debug("+++++ Stopping EC +++++\n"); + ec_dbg_drv("Stopping EC"); set_bit(EC_FLAGS_STOPPED, &ec->flags); spin_unlock_irqrestore(&ec->lock, flags); wait_event(ec->wait, acpi_ec_stopped(ec)); spin_lock_irqsave(&ec->lock, flags); /* Disable GPE for event processing (SCI_EVT=1) */ - if (!suspending) + if (!suspending) { acpi_ec_complete_request(ec); + ec_dbg_ref(ec, "Decrease driver"); + } clear_bit(EC_FLAGS_STARTED, &ec->flags); clear_bit(EC_FLAGS_STOPPED, &ec->flags); - pr_debug("EC stopped\n"); + ec_log_drv("EC stopped"); } spin_unlock_irqrestore(&ec->lock, flags); } @@ -824,12 +872,12 @@ static void acpi_ec_run(void *cxt) if (!handler) return; - pr_debug("##### Query(0x%02x) started #####\n", handler->query_bit); + ec_dbg_evt("Query(0x%02x) started", handler->query_bit); if (handler->func) handler->func(handler->data); else if (handler->handle) acpi_evaluate_object(handler->handle, NULL, NULL, NULL); - pr_debug("##### Query(0x%02x) stopped #####\n", handler->query_bit); + ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit); acpi_ec_put_query_handler(handler); } @@ -861,8 +909,8 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data) if (value == handler->query_bit) { /* have custom handler for this bit */ handler = acpi_ec_get_query_handler(handler); - pr_debug("##### Query(0x%02x) scheduled #####\n", - handler->query_bit); + ec_dbg_evt("Query(0x%02x) scheduled", + handler->query_bit); status = acpi_os_execute((handler->func) ? OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, acpi_ec_run, handler); @@ -1099,6 +1147,9 @@ static int acpi_ec_add(struct acpi_device *device) ret = ec_install_handlers(ec); + /* Reprobe devices depending on the EC */ + acpi_walk_dep_device_list(ec->handle); + /* EC is fully operational, allow queries */ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index f774c65ecb8b..39c485b0c25c 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -168,7 +168,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev) unsigned int node_id; int retval = -EINVAL; - if (ACPI_COMPANION(dev)) { + if (has_acpi_companion(dev)) { if (acpi_dev) { dev_warn(dev, "ACPI companion already set\n"); return -EINVAL; @@ -220,7 +220,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev) list_add(&physical_node->node, physnode_list); acpi_dev->physical_node_count++; - if (!ACPI_COMPANION(dev)) + if (!has_acpi_companion(dev)) ACPI_COMPANION_SET(dev, acpi_dev); acpi_physnode_link_name(physical_node_name, node_id); diff --git a/drivers/acpi/pmic/intel_pmic_crc.c b/drivers/acpi/pmic/intel_pmic_crc.c index ef7d8ff95abe..42df46a86c25 100644 --- a/drivers/acpi/pmic/intel_pmic_crc.c +++ b/drivers/acpi/pmic/intel_pmic_crc.c @@ -207,5 +207,5 @@ static int __init intel_crc_pmic_opregion_driver_init(void) } module_init(intel_crc_pmic_opregion_driver_init); -MODULE_DESCRIPTION("CrystalCove ACPI opration region driver"); +MODULE_DESCRIPTION("CrystalCove ACPI operation region driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index bbca7830e18a..d2e3c3e3f9c9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -114,7 +114,12 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler, return 0; } -/* +/** + * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent + * @acpi_dev: ACPI device object. + * @modalias: Buffer to print into. + * @size: Size of the buffer. + * * Creates hid/cid(s) string needed for modalias and uevent * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: * char *modalias: "acpi:IBM0001:ACPI0001" @@ -122,68 +127,98 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler, * -EINVAL: output error * -ENOMEM: output is truncated */ -static int create_modalias(struct acpi_device *acpi_dev, char *modalias, - int size) +static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias, + int size) { int len; int count; struct acpi_hardware_id *id; - if (list_empty(&acpi_dev->pnp.ids)) - return 0; - /* - * If the device has PRP0001 we expose DT compatible modalias - * instead in form of of:NnameTCcompatible. + * Since we skip PRP0001 from the modalias below, 0 should be returned + * if PRP0001 is the only ACPI/PNP ID in the device's list. */ - if (acpi_dev->data.of_compatible) { - struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; - const union acpi_object *of_compatible, *obj; - int i, nval; - char *c; - - acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf); - /* DT strings are all in lower case */ - for (c = buf.pointer; *c != '\0'; c++) - *c = tolower(*c); - - len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer); - ACPI_FREE(buf.pointer); - - of_compatible = acpi_dev->data.of_compatible; - if (of_compatible->type == ACPI_TYPE_PACKAGE) { - nval = of_compatible->package.count; - obj = of_compatible->package.elements; - } else { /* Must be ACPI_TYPE_STRING. */ - nval = 1; - obj = of_compatible; - } - for (i = 0; i < nval; i++, obj++) { - count = snprintf(&modalias[len], size, "C%s", - obj->string.pointer); - if (count < 0) - return -EINVAL; - if (count >= size) - return -ENOMEM; - - len += count; - size -= count; - } - } else { - len = snprintf(modalias, size, "acpi:"); - size -= len; + count = 0; + list_for_each_entry(id, &acpi_dev->pnp.ids, list) + if (strcmp(id->id, "PRP0001")) + count++; - list_for_each_entry(id, &acpi_dev->pnp.ids, list) { - count = snprintf(&modalias[len], size, "%s:", id->id); - if (count < 0) - return -EINVAL; - if (count >= size) - return -ENOMEM; - len += count; - size -= count; - } + if (!count) + return 0; + + len = snprintf(modalias, size, "acpi:"); + if (len <= 0) + return len; + + size -= len; + + list_for_each_entry(id, &acpi_dev->pnp.ids, list) { + if (!strcmp(id->id, "PRP0001")) + continue; + + count = snprintf(&modalias[len], size, "%s:", id->id); + if (count < 0) + return -EINVAL; + + if (count >= size) + return -ENOMEM; + + len += count; + size -= count; } + modalias[len] = '\0'; + return len; +} +/** + * create_of_modalias - Creates DT compatible string for modalias and uevent + * @acpi_dev: ACPI device object. + * @modalias: Buffer to print into. + * @size: Size of the buffer. + * + * Expose DT compatible modalias as of:NnameTCcompatible. This function should + * only be called for devices having PRP0001 in their list of ACPI/PNP IDs. + */ +static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias, + int size) +{ + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; + const union acpi_object *of_compatible, *obj; + int len, count; + int i, nval; + char *c; + + acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf); + /* DT strings are all in lower case */ + for (c = buf.pointer; *c != '\0'; c++) + *c = tolower(*c); + + len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer); + ACPI_FREE(buf.pointer); + + if (len <= 0) + return len; + + of_compatible = acpi_dev->data.of_compatible; + if (of_compatible->type == ACPI_TYPE_PACKAGE) { + nval = of_compatible->package.count; + obj = of_compatible->package.elements; + } else { /* Must be ACPI_TYPE_STRING. */ + nval = 1; + obj = of_compatible; + } + for (i = 0; i < nval; i++, obj++) { + count = snprintf(&modalias[len], size, "C%s", + obj->string.pointer); + if (count < 0) + return -EINVAL; + + if (count >= size) + return -ENOMEM; + + len += count; + size -= count; + } modalias[len] = '\0'; return len; } @@ -194,7 +229,8 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, * * Check if the given device has an ACPI companion and if that companion has * a valid list of PNP IDs, and if the device is the first (primary) physical - * device associated with it. + * device associated with it. Return the companion pointer if that's the case + * or NULL otherwise. * * If multiple physical devices are attached to a single ACPI companion, we need * to be careful. The usage scenario for this kind of relationship is that all @@ -208,88 +244,127 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, * resources available from it but they will be matched normally using functions * provided by their bus types (and analogously for their modalias). */ -static bool acpi_companion_match(const struct device *dev) +static struct acpi_device *acpi_companion_match(const struct device *dev) { struct acpi_device *adev; - bool ret; adev = ACPI_COMPANION(dev); if (!adev) - return false; + return NULL; if (list_empty(&adev->pnp.ids)) - return false; + return NULL; mutex_lock(&adev->physical_node_lock); if (list_empty(&adev->physical_node_list)) { - ret = false; + adev = NULL; } else { const struct acpi_device_physical_node *node; node = list_first_entry(&adev->physical_node_list, struct acpi_device_physical_node, node); - ret = node->dev == dev; + if (node->dev != dev) + adev = NULL; } mutex_unlock(&adev->physical_node_lock); - return ret; + return adev; } -/* - * Creates uevent modalias field for ACPI enumerated devices. - * Because the other buses does not support ACPI HIDs & CIDs. - * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: - * "acpi:IBM0001:ACPI0001" - */ -int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) +static int __acpi_device_uevent_modalias(struct acpi_device *adev, + struct kobj_uevent_env *env) { int len; - if (!acpi_companion_match(dev)) + if (!adev) return -ENODEV; + if (list_empty(&adev->pnp.ids)) + return 0; + if (add_uevent_var(env, "MODALIAS=")) return -ENOMEM; - len = create_modalias(ACPI_COMPANION(dev), &env->buf[env->buflen - 1], - sizeof(env->buf) - env->buflen); - if (len <= 0) + + len = create_pnp_modalias(adev, &env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen); + if (len < 0) + return len; + + env->buflen += len; + if (!adev->data.of_compatible) + return 0; + + if (len > 0 && add_uevent_var(env, "MODALIAS=")) + return -ENOMEM; + + len = create_of_modalias(adev, &env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen); + if (len < 0) return len; + env->buflen += len; + return 0; } -EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias); /* - * Creates modalias sysfs attribute for ACPI enumerated devices. + * Creates uevent modalias field for ACPI enumerated devices. * Because the other buses does not support ACPI HIDs & CIDs. * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: * "acpi:IBM0001:ACPI0001" */ -int acpi_device_modalias(struct device *dev, char *buf, int size) +int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) { - int len; + return __acpi_device_uevent_modalias(acpi_companion_match(dev), env); +} +EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias); + +static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size) +{ + int len, count; - if (!acpi_companion_match(dev)) + if (!adev) return -ENODEV; - len = create_modalias(ACPI_COMPANION(dev), buf, size -1); - if (len <= 0) + if (list_empty(&adev->pnp.ids)) + return 0; + + len = create_pnp_modalias(adev, buf, size - 1); + if (len < 0) { + return len; + } else if (len > 0) { + buf[len++] = '\n'; + size -= len; + } + if (!adev->data.of_compatible) return len; - buf[len++] = '\n'; + + count = create_of_modalias(adev, buf + len, size - 1); + if (count < 0) { + return count; + } else if (count > 0) { + len += count; + buf[len++] = '\n'; + } + return len; } + +/* + * Creates modalias sysfs attribute for ACPI enumerated devices. + * Because the other buses does not support ACPI HIDs & CIDs. + * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: + * "acpi:IBM0001:ACPI0001" + */ +int acpi_device_modalias(struct device *dev, char *buf, int size) +{ + return __acpi_device_modalias(acpi_companion_match(dev), buf, size); +} EXPORT_SYMBOL_GPL(acpi_device_modalias); static ssize_t acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct acpi_device *acpi_dev = to_acpi_device(dev); - int len; - - len = create_modalias(acpi_dev, buf, 1024); - if (len <= 0) - return len; - buf[len++] = '\n'; - return len; + return __acpi_device_modalias(to_acpi_device(dev), buf, 1024); } static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); @@ -894,8 +969,51 @@ static void acpi_device_remove_files(struct acpi_device *dev) ACPI Bus operations -------------------------------------------------------------------------- */ +/** + * acpi_of_match_device - Match device object using the "compatible" property. + * @adev: ACPI device object to match. + * @of_match_table: List of device IDs to match against. + * + * If @dev has an ACPI companion which has the special PRP0001 device ID in its + * list of identifiers and a _DSD object with the "compatible" property, use + * that property to match against the given list of identifiers. + */ +static bool acpi_of_match_device(struct acpi_device *adev, + const struct of_device_id *of_match_table) +{ + const union acpi_object *of_compatible, *obj; + int i, nval; + + if (!adev) + return false; + + of_compatible = adev->data.of_compatible; + if (!of_match_table || !of_compatible) + return false; + + if (of_compatible->type == ACPI_TYPE_PACKAGE) { + nval = of_compatible->package.count; + obj = of_compatible->package.elements; + } else { /* Must be ACPI_TYPE_STRING. */ + nval = 1; + obj = of_compatible; + } + /* Now we can look for the driver DT compatible strings */ + for (i = 0; i < nval; i++, obj++) { + const struct of_device_id *id; + + for (id = of_match_table; id->compatible[0]; id++) + if (!strcasecmp(obj->string.pointer, id->compatible)) + return true; + } + + return false; +} + static const struct acpi_device_id *__acpi_match_device( - struct acpi_device *device, const struct acpi_device_id *ids) + struct acpi_device *device, + const struct acpi_device_id *ids, + const struct of_device_id *of_ids) { const struct acpi_device_id *id; struct acpi_hardware_id *hwid; @@ -904,14 +1022,27 @@ static const struct acpi_device_id *__acpi_match_device( * If the device is not present, it is unnecessary to load device * driver for it. */ - if (!device->status.present) + if (!device || !device->status.present) return NULL; - for (id = ids; id->id[0]; id++) - list_for_each_entry(hwid, &device->pnp.ids, list) + list_for_each_entry(hwid, &device->pnp.ids, list) { + /* First, check the ACPI/PNP IDs provided by the caller. */ + for (id = ids; id->id[0]; id++) if (!strcmp((char *) id->id, hwid->id)) return id; + /* + * Next, check the special "PRP0001" ID and try to match the + * "compatible" property if found. + * + * The id returned by the below is not valid, but the only + * caller passing non-NULL of_ids here is only interested in + * whether or not the return value is NULL. + */ + if (!strcmp("PRP0001", hwid->id) + && acpi_of_match_device(device, of_ids)) + return id; + } return NULL; } @@ -929,68 +1060,26 @@ static const struct acpi_device_id *__acpi_match_device( const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, const struct device *dev) { - struct acpi_device *adev; - acpi_handle handle = ACPI_HANDLE(dev); - - if (!ids || !handle || acpi_bus_get_device(handle, &adev)) - return NULL; - - if (!acpi_companion_match(dev)) - return NULL; - - return __acpi_match_device(adev, ids); + return __acpi_match_device(acpi_companion_match(dev), ids, NULL); } EXPORT_SYMBOL_GPL(acpi_match_device); int acpi_match_device_ids(struct acpi_device *device, const struct acpi_device_id *ids) { - return __acpi_match_device(device, ids) ? 0 : -ENOENT; + return __acpi_match_device(device, ids, NULL) ? 0 : -ENOENT; } EXPORT_SYMBOL(acpi_match_device_ids); -/* Performs match against special "PRP0001" shoehorn ACPI ID */ -static bool acpi_of_driver_match_device(struct device *dev, - const struct device_driver *drv) -{ - const union acpi_object *of_compatible, *obj; - struct acpi_device *adev; - int i, nval; - - adev = ACPI_COMPANION(dev); - if (!adev) - return false; - - of_compatible = adev->data.of_compatible; - if (!drv->of_match_table || !of_compatible) - return false; - - if (of_compatible->type == ACPI_TYPE_PACKAGE) { - nval = of_compatible->package.count; - obj = of_compatible->package.elements; - } else { /* Must be ACPI_TYPE_STRING. */ - nval = 1; - obj = of_compatible; - } - /* Now we can look for the driver DT compatible strings */ - for (i = 0; i < nval; i++, obj++) { - const struct of_device_id *id; - - for (id = drv->of_match_table; id->compatible[0]; id++) - if (!strcasecmp(obj->string.pointer, id->compatible)) - return true; - } - - return false; -} - bool acpi_driver_match_device(struct device *dev, const struct device_driver *drv) { if (!drv->acpi_match_table) - return acpi_of_driver_match_device(dev, drv); + return acpi_of_match_device(ACPI_COMPANION(dev), + drv->of_match_table); - return !!acpi_match_device(drv->acpi_match_table, dev); + return !!__acpi_match_device(acpi_companion_match(dev), + drv->acpi_match_table, drv->of_match_table); } EXPORT_SYMBOL_GPL(acpi_driver_match_device); @@ -1031,20 +1120,7 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) { - struct acpi_device *acpi_dev = to_acpi_device(dev); - int len; - - if (list_empty(&acpi_dev->pnp.ids)) - return 0; - - if (add_uevent_var(env, "MODALIAS=")) - return -ENOMEM; - len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], - sizeof(env->buf) - env->buflen); - if (len <= 0) - return len; - env->buflen += len; - return 0; + return __acpi_device_uevent_modalias(to_acpi_device(dev), env); } static void acpi_device_notify(acpi_handle handle, u32 event, void *data) @@ -1062,10 +1138,10 @@ static void acpi_device_notify_fixed(void *data) acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device); } -static acpi_status acpi_device_fixed_event(void *data) +static u32 acpi_device_fixed_event(void *data) { acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data); - return AE_OK; + return ACPI_INTERRUPT_HANDLED; } static int acpi_device_install_notify_handler(struct acpi_device *device) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 7f251dd1a687..2f0d4db40a9e 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -629,6 +629,7 @@ static int acpi_freeze_begin(void) static int acpi_freeze_prepare(void) { + acpi_enable_wakeup_devices(ACPI_STATE_S0); acpi_enable_all_wakeup_gpes(); acpi_os_wait_events_complete(); enable_irq_wake(acpi_gbl_FADT.sci_interrupt); @@ -637,6 +638,7 @@ static int acpi_freeze_prepare(void) static void acpi_freeze_restore(void) { + acpi_disable_wakeup_devices(ACPI_STATE_S0); disable_irq_wake(acpi_gbl_FADT.sci_interrupt); acpi_enable_all_runtime_gpes(); } @@ -806,21 +808,6 @@ static void acpi_sleep_hibernate_setup(void) static inline void acpi_sleep_hibernate_setup(void) {} #endif /* !CONFIG_HIBERNATION */ -int acpi_suspend(u32 acpi_state) -{ - suspend_state_t states[] = { - [1] = PM_SUSPEND_STANDBY, - [3] = PM_SUSPEND_MEM, - [5] = PM_SUSPEND_MAX - }; - - if (acpi_state < 6 && states[acpi_state]) - return pm_suspend(states[acpi_state]); - if (acpi_state == 4) - return hibernate(); - return -EINVAL; -} - static void acpi_power_off_prepare(void) { /* Prepare to power off the system */ diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h index 0143540a2519..c797ffa568d5 100644 --- a/drivers/acpi/sleep.h +++ b/drivers/acpi/sleep.h @@ -1,6 +1,4 @@ -extern int acpi_suspend(u32 state); - extern void acpi_enable_wakeup_devices(u8 sleep_state); extern void acpi_disable_wakeup_devices(u8 sleep_state); diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 13e577c80201..0876d77b3206 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -527,7 +527,7 @@ static ssize_t counter_show(struct kobject *kobj, acpi_irq_not_handled; all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count = acpi_gpe_count; - size = sprintf(buf, "%8d", all_counters[index].count); + size = sprintf(buf, "%8u", all_counters[index].count); /* "gpe_all" or "sci" */ if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 26eb70c8f518..cc79d3fedfb2 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -82,9 +82,15 @@ module_param(allow_duplicates, bool, 0644); * For Windows 8 systems: used to decide if video module * should skip registering backlight interface of its own. */ -static int use_native_backlight_param = -1; +enum { + NATIVE_BACKLIGHT_NOT_SET = -1, + NATIVE_BACKLIGHT_OFF, + NATIVE_BACKLIGHT_ON, +}; + +static int use_native_backlight_param = NATIVE_BACKLIGHT_NOT_SET; module_param_named(use_native_backlight, use_native_backlight_param, int, 0444); -static bool use_native_backlight_dmi = true; +static int use_native_backlight_dmi = NATIVE_BACKLIGHT_NOT_SET; static int register_count; static struct mutex video_list_lock; @@ -237,15 +243,16 @@ static void acpi_video_switch_brightness(struct work_struct *work); static bool acpi_video_use_native_backlight(void) { - if (use_native_backlight_param != -1) + if (use_native_backlight_param != NATIVE_BACKLIGHT_NOT_SET) return use_native_backlight_param; - else + else if (use_native_backlight_dmi != NATIVE_BACKLIGHT_NOT_SET) return use_native_backlight_dmi; + return acpi_osi_is_win8(); } bool acpi_video_verify_backlight_support(void) { - if (acpi_osi_is_win8() && acpi_video_use_native_backlight() && + if (acpi_video_use_native_backlight() && backlight_device_registered(BACKLIGHT_RAW)) return false; return acpi_video_backlight_support(); @@ -414,7 +421,13 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d) static int __init video_disable_native_backlight(const struct dmi_system_id *d) { - use_native_backlight_dmi = false; + use_native_backlight_dmi = NATIVE_BACKLIGHT_OFF; + return 0; +} + +static int __init video_enable_native_backlight(const struct dmi_system_id *d) +{ + use_native_backlight_dmi = NATIVE_BACKLIGHT_ON; return 0; } @@ -559,6 +572,17 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "XPS L521X"), }, }, + + /* Non win8 machines which need native backlight nevertheless */ + { + /* https://bugzilla.redhat.com/show_bug.cgi?id=1187004 */ + .callback = video_enable_native_backlight, + .ident = "Lenovo Ideapad Z570", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "102434U"), + }, + }, {} }; diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 27c43499977a..c42feb2bacd0 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -174,14 +174,6 @@ static struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5737"), }, }, - { - .callback = video_detect_force_vendor, - .ident = "Lenovo IdeaPad Z570", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"), - }, - }, { }, }; diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index b33d1f99b3a4..994f168b54a8 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -128,20 +128,8 @@ static struct pnp_driver isapnp_driver = { .remove = isapnp_remove_one, }; -static int __init isapnp_init(void) -{ - return pnp_register_driver(&isapnp_driver); -} - -static void __exit isapnp_exit(void) -{ - pnp_unregister_driver(&isapnp_driver); -} - +module_pnp_driver(isapnp_driver); MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("low-level driver for ISA PnP ATA"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); - -module_init(isapnp_init); -module_exit(isapnp_exit); diff --git a/drivers/base/core.c b/drivers/base/core.c index 07304a3b9ee2..c7e2a9a70865 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -12,6 +12,7 @@ #include <linux/device.h> #include <linux/err.h> +#include <linux/fwnode.h> #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> @@ -2133,3 +2134,53 @@ define_dev_printk_level(dev_notice, KERN_NOTICE); define_dev_printk_level(_dev_info, KERN_INFO); #endif + +static inline bool fwnode_is_primary(struct fwnode_handle *fwnode) +{ + return fwnode && !IS_ERR(fwnode->secondary); +} + +/** + * set_primary_fwnode - Change the primary firmware node of a given device. + * @dev: Device to handle. + * @fwnode: New primary firmware node of the device. + * + * Set the device's firmware node pointer to @fwnode, but if a secondary + * firmware node of the device is present, preserve it. + */ +void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode) +{ + if (fwnode) { + struct fwnode_handle *fn = dev->fwnode; + + if (fwnode_is_primary(fn)) + fn = fn->secondary; + + fwnode->secondary = fn; + dev->fwnode = fwnode; + } else { + dev->fwnode = fwnode_is_primary(dev->fwnode) ? + dev->fwnode->secondary : NULL; + } +} +EXPORT_SYMBOL_GPL(set_primary_fwnode); + +/** + * set_secondary_fwnode - Change the secondary firmware node of a given device. + * @dev: Device to handle. + * @fwnode: New secondary firmware node of the device. + * + * If a primary firmware node of the device is present, set its secondary + * pointer to @fwnode. Otherwise, set the device's firmware node pointer to + * @fwnode. + */ +void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode) +{ + if (fwnode) + fwnode->secondary = ERR_PTR(-ENODEV); + + if (fwnode_is_primary(dev->fwnode)) + dev->fwnode->secondary = fwnode; + else + dev->fwnode = fwnode; +} diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 9421fed40905..17f0204fabef 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -454,7 +454,7 @@ struct platform_device *platform_device_register_full( goto err_alloc; pdev->dev.parent = pdevinfo->parent; - ACPI_COMPANION_SET(&pdev->dev, pdevinfo->acpi_node.companion); + pdev->dev.fwnode = pdevinfo->fwnode; if (pdevinfo->dma_mask) { /* diff --git a/drivers/base/property.c b/drivers/base/property.c index c45845874d4f..6a3f7d8af341 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -10,10 +10,102 @@ * published by the Free Software Foundation. */ -#include <linux/property.h> -#include <linux/export.h> #include <linux/acpi.h> +#include <linux/export.h> +#include <linux/kernel.h> #include <linux/of.h> +#include <linux/property.h> + +/** + * device_add_property_set - Add a collection of properties to a device object. + * @dev: Device to add properties to. + * @pset: Collection of properties to add. + * + * Associate a collection of device properties represented by @pset with @dev + * as its secondary firmware node. + */ +void device_add_property_set(struct device *dev, struct property_set *pset) +{ + if (pset) + pset->fwnode.type = FWNODE_PDATA; + + set_secondary_fwnode(dev, &pset->fwnode); +} +EXPORT_SYMBOL_GPL(device_add_property_set); + +static inline bool is_pset(struct fwnode_handle *fwnode) +{ + return fwnode && fwnode->type == FWNODE_PDATA; +} + +static inline struct property_set *to_pset(struct fwnode_handle *fwnode) +{ + return is_pset(fwnode) ? + container_of(fwnode, struct property_set, fwnode) : NULL; +} + +static struct property_entry *pset_prop_get(struct property_set *pset, + const char *name) +{ + struct property_entry *prop; + + if (!pset || !pset->properties) + return NULL; + + for (prop = pset->properties; prop->name; prop++) + if (!strcmp(name, prop->name)) + return prop; + + return NULL; +} + +static int pset_prop_read_array(struct property_set *pset, const char *name, + enum dev_prop_type type, void *val, size_t nval) +{ + struct property_entry *prop; + unsigned int item_size; + + prop = pset_prop_get(pset, name); + if (!prop) + return -ENODATA; + + if (prop->type != type) + return -EPROTO; + + if (!val) + return prop->nval; + + if (prop->nval < nval) + return -EOVERFLOW; + + switch (type) { + case DEV_PROP_U8: + item_size = sizeof(u8); + break; + case DEV_PROP_U16: + item_size = sizeof(u16); + break; + case DEV_PROP_U32: + item_size = sizeof(u32); + break; + case DEV_PROP_U64: + item_size = sizeof(u64); + break; + case DEV_PROP_STRING: + item_size = sizeof(const char *); + break; + default: + return -EINVAL; + } + memcpy(val, prop->value.raw_data, nval * item_size); + return 0; +} + +static inline struct fwnode_handle *dev_fwnode(struct device *dev) +{ + return IS_ENABLED(CONFIG_OF) && dev->of_node ? + &dev->of_node->fwnode : dev->fwnode; +} /** * device_property_present - check if a property of a device is present @@ -24,10 +116,7 @@ */ bool device_property_present(struct device *dev, const char *propname) { - if (IS_ENABLED(CONFIG_OF) && dev->of_node) - return of_property_read_bool(dev->of_node, propname); - - return !acpi_dev_prop_get(ACPI_COMPANION(dev), propname, NULL); + return fwnode_property_present(dev_fwnode(dev), propname); } EXPORT_SYMBOL_GPL(device_property_present); @@ -43,32 +132,22 @@ bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname) else if (is_acpi_node(fwnode)) return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL); - return false; + return !!pset_prop_get(to_pset(fwnode), propname); } EXPORT_SYMBOL_GPL(fwnode_property_present); -#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ - (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ - : of_property_count_elems_of_size((node), (propname), sizeof(type)) - -#define DEV_PROP_READ_ARRAY(_dev_, _propname_, _type_, _proptype_, _val_, _nval_) \ - IS_ENABLED(CONFIG_OF) && _dev_->of_node ? \ - (OF_DEV_PROP_READ_ARRAY(_dev_->of_node, _propname_, _type_, \ - _val_, _nval_)) : \ - acpi_dev_prop_read(ACPI_COMPANION(_dev_), _propname_, \ - _proptype_, _val_, _nval_) - /** * device_property_read_u8_array - return a u8 array property of a device * @dev: Device to get the property of * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values * @nval: Size of the @val array * * Function reads an array of u8 properties with @propname from the device * firmware description and stores them to @val if found. * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO if the property is not an array of numbers, @@ -77,7 +156,7 @@ EXPORT_SYMBOL_GPL(fwnode_property_present); int device_property_read_u8_array(struct device *dev, const char *propname, u8 *val, size_t nval) { - return DEV_PROP_READ_ARRAY(dev, propname, u8, DEV_PROP_U8, val, nval); + return fwnode_property_read_u8_array(dev_fwnode(dev), propname, val, nval); } EXPORT_SYMBOL_GPL(device_property_read_u8_array); @@ -85,13 +164,14 @@ EXPORT_SYMBOL_GPL(device_property_read_u8_array); * device_property_read_u16_array - return a u16 array property of a device * @dev: Device to get the property of * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values * @nval: Size of the @val array * * Function reads an array of u16 properties with @propname from the device * firmware description and stores them to @val if found. * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO if the property is not an array of numbers, @@ -100,7 +180,7 @@ EXPORT_SYMBOL_GPL(device_property_read_u8_array); int device_property_read_u16_array(struct device *dev, const char *propname, u16 *val, size_t nval) { - return DEV_PROP_READ_ARRAY(dev, propname, u16, DEV_PROP_U16, val, nval); + return fwnode_property_read_u16_array(dev_fwnode(dev), propname, val, nval); } EXPORT_SYMBOL_GPL(device_property_read_u16_array); @@ -108,13 +188,14 @@ EXPORT_SYMBOL_GPL(device_property_read_u16_array); * device_property_read_u32_array - return a u32 array property of a device * @dev: Device to get the property of * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values * @nval: Size of the @val array * * Function reads an array of u32 properties with @propname from the device * firmware description and stores them to @val if found. * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO if the property is not an array of numbers, @@ -123,7 +204,7 @@ EXPORT_SYMBOL_GPL(device_property_read_u16_array); int device_property_read_u32_array(struct device *dev, const char *propname, u32 *val, size_t nval) { - return DEV_PROP_READ_ARRAY(dev, propname, u32, DEV_PROP_U32, val, nval); + return fwnode_property_read_u32_array(dev_fwnode(dev), propname, val, nval); } EXPORT_SYMBOL_GPL(device_property_read_u32_array); @@ -131,13 +212,14 @@ EXPORT_SYMBOL_GPL(device_property_read_u32_array); * device_property_read_u64_array - return a u64 array property of a device * @dev: Device to get the property of * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values * @nval: Size of the @val array * * Function reads an array of u64 properties with @propname from the device * firmware description and stores them to @val if found. * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO if the property is not an array of numbers, @@ -146,7 +228,7 @@ EXPORT_SYMBOL_GPL(device_property_read_u32_array); int device_property_read_u64_array(struct device *dev, const char *propname, u64 *val, size_t nval) { - return DEV_PROP_READ_ARRAY(dev, propname, u64, DEV_PROP_U64, val, nval); + return fwnode_property_read_u64_array(dev_fwnode(dev), propname, val, nval); } EXPORT_SYMBOL_GPL(device_property_read_u64_array); @@ -154,13 +236,14 @@ EXPORT_SYMBOL_GPL(device_property_read_u64_array); * device_property_read_string_array - return a string array property of device * @dev: Device to get the property of * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values * @nval: Size of the @val array * * Function reads an array of string properties with @propname from the device * firmware description and stores them to @val if found. * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO or %-EILSEQ if the property is not an array of strings, @@ -169,10 +252,7 @@ EXPORT_SYMBOL_GPL(device_property_read_u64_array); int device_property_read_string_array(struct device *dev, const char *propname, const char **val, size_t nval) { - return IS_ENABLED(CONFIG_OF) && dev->of_node ? - of_property_read_string_array(dev->of_node, propname, val, nval) : - acpi_dev_prop_read(ACPI_COMPANION(dev), propname, - DEV_PROP_STRING, val, nval); + return fwnode_property_read_string_array(dev_fwnode(dev), propname, val, nval); } EXPORT_SYMBOL_GPL(device_property_read_string_array); @@ -193,13 +273,14 @@ EXPORT_SYMBOL_GPL(device_property_read_string_array); int device_property_read_string(struct device *dev, const char *propname, const char **val) { - return IS_ENABLED(CONFIG_OF) && dev->of_node ? - of_property_read_string(dev->of_node, propname, val) : - acpi_dev_prop_read(ACPI_COMPANION(dev), propname, - DEV_PROP_STRING, val, 1); + return fwnode_property_read_string(dev_fwnode(dev), propname, val); } EXPORT_SYMBOL_GPL(device_property_read_string); +#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ + (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ + : of_property_count_elems_of_size((node), (propname), sizeof(type)) + #define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \ ({ \ int _ret_; \ @@ -210,7 +291,8 @@ EXPORT_SYMBOL_GPL(device_property_read_string); _ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \ _proptype_, _val_, _nval_); \ else \ - _ret_ = -ENXIO; \ + _ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \ + _proptype_, _val_, _nval_); \ _ret_; \ }) @@ -218,13 +300,14 @@ EXPORT_SYMBOL_GPL(device_property_read_string); * fwnode_property_read_u8_array - return a u8 array property of firmware node * @fwnode: Firmware node to get the property of * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values * @nval: Size of the @val array * * Read an array of u8 properties with @propname from @fwnode and stores them to * @val if found. * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO if the property is not an array of numbers, @@ -243,13 +326,14 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array); * fwnode_property_read_u16_array - return a u16 array property of firmware node * @fwnode: Firmware node to get the property of * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values * @nval: Size of the @val array * * Read an array of u16 properties with @propname from @fwnode and store them to * @val if found. * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO if the property is not an array of numbers, @@ -268,13 +352,14 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array); * fwnode_property_read_u32_array - return a u32 array property of firmware node * @fwnode: Firmware node to get the property of * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values * @nval: Size of the @val array * * Read an array of u32 properties with @propname from @fwnode store them to * @val if found. * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO if the property is not an array of numbers, @@ -293,13 +378,14 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array); * fwnode_property_read_u64_array - return a u64 array property firmware node * @fwnode: Firmware node to get the property of * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values * @nval: Size of the @val array * * Read an array of u64 properties with @propname from @fwnode and store them to * @val if found. * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO if the property is not an array of numbers, @@ -318,13 +404,14 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array); * fwnode_property_read_string_array - return string array property of a node * @fwnode: Firmware node to get the property of * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values * @nval: Size of the @val array * * Read an string list property @propname from the given firmware node and store * them to @val if found. * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO if the property is not an array of strings, @@ -336,13 +423,16 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode, size_t nval) { if (is_of_node(fwnode)) - return of_property_read_string_array(of_node(fwnode), propname, - val, nval); + return val ? + of_property_read_string_array(of_node(fwnode), propname, + val, nval) : + of_property_count_strings(of_node(fwnode), propname); else if (is_acpi_node(fwnode)) return acpi_dev_prop_read(acpi_node(fwnode), propname, DEV_PROP_STRING, val, nval); - return -ENXIO; + return pset_prop_read_array(to_pset(fwnode), propname, + DEV_PROP_STRING, val, nval); } EXPORT_SYMBOL_GPL(fwnode_property_read_string_array); diff --git a/drivers/char/ipmi/ipmi_powernv.c b/drivers/char/ipmi/ipmi_powernv.c index 79524ed2a3cb..8753b0f6a317 100644 --- a/drivers/char/ipmi/ipmi_powernv.c +++ b/drivers/char/ipmi/ipmi_powernv.c @@ -125,6 +125,7 @@ static int ipmi_powernv_recv(struct ipmi_smi_powernv *smi) spin_lock_irqsave(&smi->msg_lock, flags); if (!smi->cur_msg) { + spin_unlock_irqrestore(&smi->msg_lock, flags); pr_warn("no current message?\n"); return 0; } diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index f6646ed3047e..518585c1ce94 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -263,6 +263,11 @@ struct smi_info { bool supports_event_msg_buff; /* + * Can we clear the global enables receive irq bit? + */ + bool cannot_clear_recv_irq_bit; + + /* * Did we get an attention that we did not handle? */ bool got_attn; @@ -461,6 +466,9 @@ static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val) * allocate messages, we just leave them in the BMC and run the system * polled until we can allocate some memory. Once we have some * memory, we will re-enable the interrupt. + * + * Note that we cannot just use disable_irq(), since the interrupt may + * be shared. */ static inline bool disable_si_irq(struct smi_info *smi_info) { @@ -549,20 +557,15 @@ static u8 current_global_enables(struct smi_info *smi_info, u8 base, if (smi_info->supports_event_msg_buff) enables |= IPMI_BMC_EVT_MSG_BUFF; - else - enables &= ~IPMI_BMC_EVT_MSG_BUFF; - if (smi_info->irq && !smi_info->interrupt_disabled) + if ((smi_info->irq && !smi_info->interrupt_disabled) || + smi_info->cannot_clear_recv_irq_bit) enables |= IPMI_BMC_RCV_MSG_INTR; - else - enables &= ~IPMI_BMC_RCV_MSG_INTR; if (smi_info->supports_event_msg_buff && smi_info->irq && !smi_info->interrupt_disabled) enables |= IPMI_BMC_EVT_MSG_INTR; - else - enables &= ~IPMI_BMC_EVT_MSG_INTR; *irq_on = enables & (IPMI_BMC_EVT_MSG_INTR | IPMI_BMC_RCV_MSG_INTR); @@ -2900,6 +2903,96 @@ static int try_get_dev_id(struct smi_info *smi_info) return rv; } +/* + * Some BMCs do not support clearing the receive irq bit in the global + * enables (even if they don't support interrupts on the BMC). Check + * for this and handle it properly. + */ +static void check_clr_rcv_irq(struct smi_info *smi_info) +{ + unsigned char msg[3]; + unsigned char *resp; + unsigned long resp_len; + int rv; + + resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); + if (!resp) { + printk(KERN_WARNING PFX "Out of memory allocating response for" + " global enables command, cannot check recv irq bit" + " handling.\n"); + return; + } + + msg[0] = IPMI_NETFN_APP_REQUEST << 2; + msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; + smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); + + rv = wait_for_msg_done(smi_info); + if (rv) { + printk(KERN_WARNING PFX "Error getting response from get" + " global enables command, cannot check recv irq bit" + " handling.\n"); + goto out; + } + + resp_len = smi_info->handlers->get_result(smi_info->si_sm, + resp, IPMI_MAX_MSG_LENGTH); + + if (resp_len < 4 || + resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || + resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD || + resp[2] != 0) { + printk(KERN_WARNING PFX "Invalid return from get global" + " enables command, cannot check recv irq bit" + " handling.\n"); + rv = -EINVAL; + goto out; + } + + if ((resp[3] & IPMI_BMC_RCV_MSG_INTR) == 0) + /* Already clear, should work ok. */ + goto out; + + msg[0] = IPMI_NETFN_APP_REQUEST << 2; + msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; + msg[2] = resp[3] & ~IPMI_BMC_RCV_MSG_INTR; + smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3); + + rv = wait_for_msg_done(smi_info); + if (rv) { + printk(KERN_WARNING PFX "Error getting response from set" + " global enables command, cannot check recv irq bit" + " handling.\n"); + goto out; + } + + resp_len = smi_info->handlers->get_result(smi_info->si_sm, + resp, IPMI_MAX_MSG_LENGTH); + + if (resp_len < 3 || + resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || + resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) { + printk(KERN_WARNING PFX "Invalid return from get global" + " enables command, cannot check recv irq bit" + " handling.\n"); + rv = -EINVAL; + goto out; + } + + if (resp[2] != 0) { + /* + * An error when setting the event buffer bit means + * clearing the bit is not supported. + */ + printk(KERN_WARNING PFX "The BMC does not support clearing" + " the recv irq bit, compensating, but the BMC needs to" + " be fixed.\n"); + smi_info->cannot_clear_recv_irq_bit = true; + } + out: + kfree(resp); +} + static int try_enable_event_buffer(struct smi_info *smi_info) { unsigned char msg[3]; @@ -3395,6 +3488,8 @@ static int try_smi_init(struct smi_info *new_smi) goto out_err; } + check_clr_rcv_irq(new_smi); + setup_oem_data_handler(new_smi); setup_xaction_handlers(new_smi); diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index f6e378dac5f5..f40e3bd2c69c 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -468,11 +468,13 @@ static int ipmi_ssif_thread(void *data) int result; /* Wait for something to do */ - wait_for_completion(&ssif_info->wake_thread); - init_completion(&ssif_info->wake_thread); - + result = wait_for_completion_interruptible( + &ssif_info->wake_thread); if (ssif_info->stopping) break; + if (result == -ERESTARTSYS) + continue; + init_completion(&ssif_info->wake_thread); if (ssif_info->i2c_read_write == I2C_SMBUS_WRITE) { result = i2c_smbus_write_block_data( diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 6d492132ad2b..29ba520ac24d 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -637,18 +637,7 @@ static struct pnp_driver tpm_inf_pnp_driver = { .remove = tpm_inf_pnp_remove }; -static int __init init_inf(void) -{ - return pnp_register_driver(&tpm_inf_pnp_driver); -} - -static void __exit cleanup_inf(void) -{ - pnp_unregister_driver(&tpm_inf_pnp_driver); -} - -module_init(init_inf); -module_exit(cleanup_inf); +module_pnp_driver(tpm_inf_pnp_driver); MODULE_AUTHOR("Marcel Selhorst <tpmdd@sirrix.com>"); MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index c5029c1209b4..8c7930b5a65f 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -29,15 +29,10 @@ config DT_IDLE_STATES bool menu "ARM CPU Idle Drivers" -depends on ARM +depends on ARM || ARM64 source "drivers/cpuidle/Kconfig.arm" endmenu -menu "ARM64 CPU Idle Drivers" -depends on ARM64 -source "drivers/cpuidle/Kconfig.arm64" -endmenu - menu "MIPS CPU Idle Drivers" depends on MIPS source "drivers/cpuidle/Kconfig.mips" diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 8e07c9419153..21340e0be73e 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -1,10 +1,20 @@ # # ARM CPU Idle drivers # +config ARM_CPUIDLE + bool "Generic ARM/ARM64 CPU idle Driver" + select DT_IDLE_STATES + help + Select this to enable generic cpuidle driver for ARM. + It provides a generic idle driver whose idle states are configured + at run-time through DT nodes. The CPUidle suspend backend is + initialized by calling the CPU operations init idle hook + provided by architecture code. + config ARM_BIG_LITTLE_CPUIDLE bool "Support for ARM big.LITTLE processors" depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS - depends on MCPM + depends on MCPM && !ARM64 select ARM_CPU_SUSPEND select CPU_IDLE_MULTIPLE_DRIVERS select DT_IDLE_STATES @@ -16,51 +26,51 @@ config ARM_BIG_LITTLE_CPUIDLE config ARM_CLPS711X_CPUIDLE bool "CPU Idle Driver for CLPS711X processors" - depends on ARCH_CLPS711X || COMPILE_TEST + depends on ARCH_CLPS711X && !ARM64 || COMPILE_TEST help Select this to enable cpuidle on Cirrus Logic CLPS711X SOCs. config ARM_HIGHBANK_CPUIDLE bool "CPU Idle Driver for Calxeda processors" - depends on ARM_PSCI + depends on ARM_PSCI && !ARM64 select ARM_CPU_SUSPEND help Select this to enable cpuidle on Calxeda processors. config ARM_KIRKWOOD_CPUIDLE bool "CPU Idle Driver for Marvell Kirkwood SoCs" - depends on MACH_KIRKWOOD + depends on MACH_KIRKWOOD && !ARM64 help This adds the CPU Idle driver for Marvell Kirkwood SoCs. config ARM_ZYNQ_CPUIDLE bool "CPU Idle Driver for Xilinx Zynq processors" - depends on ARCH_ZYNQ + depends on ARCH_ZYNQ && !ARM64 help Select this to enable cpuidle on Xilinx Zynq processors. config ARM_U8500_CPUIDLE bool "Cpu Idle Driver for the ST-E u8500 processors" - depends on ARCH_U8500 + depends on ARCH_U8500 && !ARM64 help Select this to enable cpuidle for ST-E u8500 processors config ARM_AT91_CPUIDLE bool "Cpu Idle Driver for the AT91 processors" default y - depends on ARCH_AT91 + depends on ARCH_AT91 && !ARM64 help Select this to enable cpuidle for AT91 processors config ARM_EXYNOS_CPUIDLE bool "Cpu Idle Driver for the Exynos processors" - depends on ARCH_EXYNOS + depends on ARCH_EXYNOS && !ARM64 select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP help Select this to enable cpuidle for Exynos processors config ARM_MVEBU_V7_CPUIDLE bool "CPU Idle Driver for mvebu v7 family processors" - depends on ARCH_MVEBU + depends on ARCH_MVEBU && !ARM64 help Select this to enable cpuidle on Armada 370, 38x and XP processors. diff --git a/drivers/cpuidle/Kconfig.arm64 b/drivers/cpuidle/Kconfig.arm64 deleted file mode 100644 index 6effb3656735..000000000000 --- a/drivers/cpuidle/Kconfig.arm64 +++ /dev/null @@ -1,13 +0,0 @@ -# -# ARM64 CPU Idle drivers -# - -config ARM64_CPUIDLE - bool "Generic ARM64 CPU idle Driver" - select DT_IDLE_STATES - help - Select this to enable generic cpuidle driver for ARM64. - It provides a generic idle driver whose idle states are configured - at run-time through DT nodes. The CPUidle suspend backend is - initialized by calling the CPU operations init idle hook - provided by architecture code. diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 4d177b916f75..3ba81b1dffad 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -17,16 +17,13 @@ obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o +obj-$(CONFIG_ARM_CPUIDLE) += cpuidle-arm.o ############################################################################### # MIPS drivers obj-$(CONFIG_MIPS_CPS_CPUIDLE) += cpuidle-cps.o ############################################################################### -# ARM64 drivers -obj-$(CONFIG_ARM64_CPUIDLE) += cpuidle-arm64.o - -############################################################################### # POWERPC drivers obj-$(CONFIG_PSERIES_CPUIDLE) += cpuidle-pseries.o obj-$(CONFIG_POWERNV_CPUIDLE) += cpuidle-powernv.o diff --git a/drivers/cpuidle/cpuidle-arm64.c b/drivers/cpuidle/cpuidle-arm.c index 39a2c62716c3..545069d5fdfb 100644 --- a/drivers/cpuidle/cpuidle-arm64.c +++ b/drivers/cpuidle/cpuidle-arm.c @@ -1,5 +1,5 @@ /* - * ARM64 generic CPU idle driver. + * ARM/ARM64 generic CPU idle driver. * * Copyright (C) 2014 ARM Ltd. * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> @@ -9,7 +9,7 @@ * published by the Free Software Foundation. */ -#define pr_fmt(fmt) "CPUidle arm64: " fmt +#define pr_fmt(fmt) "CPUidle arm: " fmt #include <linux/cpuidle.h> #include <linux/cpumask.h> @@ -17,13 +17,14 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/slab.h> #include <asm/cpuidle.h> #include "dt_idle_states.h" /* - * arm64_enter_idle_state - Programs CPU to enter the specified state + * arm_enter_idle_state - Programs CPU to enter the specified state * * dev: cpuidle device * drv: cpuidle driver @@ -32,8 +33,8 @@ * Called from the CPUidle framework to program the device to the * specified target state selected by the governor. */ -static int arm64_enter_idle_state(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int idx) +static int arm_enter_idle_state(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int idx) { int ret; @@ -49,7 +50,7 @@ static int arm64_enter_idle_state(struct cpuidle_device *dev, * call the CPU ops suspend protocol with idle index as a * parameter. */ - ret = cpu_suspend(idx); + arm_cpuidle_suspend(idx); cpu_pm_exit(); } @@ -57,8 +58,8 @@ static int arm64_enter_idle_state(struct cpuidle_device *dev, return ret ? -1 : idx; } -static struct cpuidle_driver arm64_idle_driver = { - .name = "arm64_idle", +static struct cpuidle_driver arm_idle_driver = { + .name = "arm_idle", .owner = THIS_MODULE, /* * State at index 0 is standby wfi and considered standard @@ -68,32 +69,33 @@ static struct cpuidle_driver arm64_idle_driver = { * handler for idle state index 0. */ .states[0] = { - .enter = arm64_enter_idle_state, + .enter = arm_enter_idle_state, .exit_latency = 1, .target_residency = 1, .power_usage = UINT_MAX, .name = "WFI", - .desc = "ARM64 WFI", + .desc = "ARM WFI", } }; -static const struct of_device_id arm64_idle_state_match[] __initconst = { +static const struct of_device_id arm_idle_state_match[] __initconst = { { .compatible = "arm,idle-state", - .data = arm64_enter_idle_state }, + .data = arm_enter_idle_state }, { }, }; /* - * arm64_idle_init + * arm_idle_init * - * Registers the arm64 specific cpuidle driver with the cpuidle + * Registers the arm specific cpuidle driver with the cpuidle * framework. It relies on core code to parse the idle states * and initialize them using driver data structures accordingly. */ -static int __init arm64_idle_init(void) +static int __init arm_idle_init(void) { int cpu, ret; - struct cpuidle_driver *drv = &arm64_idle_driver; + struct cpuidle_driver *drv = &arm_idle_driver; + struct cpuidle_device *dev; /* * Initialize idle states data, starting at index 1. @@ -101,22 +103,61 @@ static int __init arm64_idle_init(void) * let the driver initialization fail accordingly since there is no * reason to initialize the idle driver if only wfi is supported. */ - ret = dt_init_idle_driver(drv, arm64_idle_state_match, 1); + ret = dt_init_idle_driver(drv, arm_idle_state_match, 1); if (ret <= 0) return ret ? : -ENODEV; + ret = cpuidle_register_driver(drv); + if (ret) { + pr_err("Failed to register cpuidle driver\n"); + return ret; + } + /* * Call arch CPU operations in order to initialize * idle states suspend back-end specific data */ for_each_possible_cpu(cpu) { - ret = cpu_init_idle(cpu); + ret = arm_cpuidle_init(cpu); + + /* + * Skip the cpuidle device initialization if the reported + * failure is a HW misconfiguration/breakage (-ENXIO). + */ + if (ret == -ENXIO) + continue; + if (ret) { pr_err("CPU %d failed to init idle CPU ops\n", cpu); - return ret; + goto out_fail; + } + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + pr_err("Failed to allocate cpuidle device\n"); + goto out_fail; + } + dev->cpu = cpu; + + ret = cpuidle_register_device(dev); + if (ret) { + pr_err("Failed to register cpuidle device for CPU %d\n", + cpu); + kfree(dev); + goto out_fail; } } - return cpuidle_register(drv, NULL); + return 0; +out_fail: + while (--cpu >= 0) { + dev = per_cpu(cpuidle_devices, cpu); + cpuidle_unregister_device(dev); + kfree(dev); + } + + cpuidle_unregister_driver(drv); + + return ret; } -device_initcall(arm64_idle_init); +device_initcall(arm_idle_init); diff --git a/drivers/cpuidle/cpuidle-at91.c b/drivers/cpuidle/cpuidle-at91.c index aae7bfc1ea36..f2446c78d87c 100644 --- a/drivers/cpuidle/cpuidle-at91.c +++ b/drivers/cpuidle/cpuidle-at91.c @@ -19,7 +19,6 @@ #include <linux/cpuidle.h> #include <linux/io.h> #include <linux/export.h> -#include <asm/proc-fns.h> #include <asm/cpuidle.h> #define AT91_MAX_STATES 2 diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c index 26f5f29fdb03..0c06ea2f50bb 100644 --- a/drivers/cpuidle/cpuidle-exynos.c +++ b/drivers/cpuidle/cpuidle-exynos.c @@ -19,7 +19,6 @@ #include <linux/of.h> #include <linux/platform_data/cpuidle-exynos.h> -#include <asm/proc-fns.h> #include <asm/suspend.h> #include <asm/cpuidle.h> diff --git a/drivers/cpuidle/cpuidle-kirkwood.c b/drivers/cpuidle/cpuidle-kirkwood.c index cea0a6c4b1db..d23d8f468c12 100644 --- a/drivers/cpuidle/cpuidle-kirkwood.c +++ b/drivers/cpuidle/cpuidle-kirkwood.c @@ -21,7 +21,6 @@ #include <linux/cpuidle.h> #include <linux/io.h> #include <linux/export.h> -#include <asm/proc-fns.h> #include <asm/cpuidle.h> #define KIRKWOOD_MAX_STATES 2 diff --git a/drivers/cpuidle/cpuidle-ux500.c b/drivers/cpuidle/cpuidle-ux500.c index 66f81e410f0d..8bf895c0017d 100644 --- a/drivers/cpuidle/cpuidle-ux500.c +++ b/drivers/cpuidle/cpuidle-ux500.c @@ -19,7 +19,6 @@ #include <linux/platform_device.h> #include <asm/cpuidle.h> -#include <asm/proc-fns.h> static atomic_t master = ATOMIC_INIT(0); static DEFINE_SPINLOCK(master_lock); diff --git a/drivers/cpuidle/cpuidle-zynq.c b/drivers/cpuidle/cpuidle-zynq.c index 002b8c9f98f5..543292b1d38e 100644 --- a/drivers/cpuidle/cpuidle-zynq.c +++ b/drivers/cpuidle/cpuidle-zynq.c @@ -28,7 +28,6 @@ #include <linux/init.h> #include <linux/cpuidle.h> #include <linux/platform_device.h> -#include <asm/proc-fns.h> #include <asm/cpuidle.h> #define ZYNQ_MAX_STATES 2 diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index 512cb8e2805e..ceedafbd23e0 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -903,6 +903,11 @@ static const struct cppi_glue_infos *get_glue_info(struct device *dev) return of_id->data; } +#define CPPI41_DMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ + BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \ + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)) + static int cppi41_dma_probe(struct platform_device *pdev) { struct cppi41_dd *cdd; @@ -926,6 +931,10 @@ static int cppi41_dma_probe(struct platform_device *pdev) cdd->ddev.device_issue_pending = cppi41_dma_issue_pending; cdd->ddev.device_prep_slave_sg = cppi41_dma_prep_slave_sg; cdd->ddev.device_terminate_all = cppi41_stop_chan; + cdd->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + cdd->ddev.src_addr_widths = CPPI41_DMA_BUSWIDTHS; + cdd->ddev.dst_addr_widths = CPPI41_DMA_BUSWIDTHS; + cdd->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; cdd->ddev.dev = dev; INIT_LIST_HEAD(&cdd->ddev.channels); cpp41_dma_info.dma_cap = cdd->ddev.cap_mask; diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index f15712f2fec6..ac336a961dea 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -859,9 +859,6 @@ int dma_async_device_register(struct dma_device *device) BUG_ON(!device->device_issue_pending); BUG_ON(!device->dev); - WARN(dma_has_cap(DMA_SLAVE, device->cap_mask) && !device->directions, - "this driver doesn't support generic slave capabilities reporting\n"); - /* note: this only matters in the * CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=n case */ diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 550a5eafbd38..ab892be26dc2 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -17,6 +17,8 @@ enum of_gpio_flags; +struct acpi_device; + /** * struct acpi_gpio_info - ACPI GPIO specific information * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index c270f5f9a8f9..538d6910b550 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -166,7 +166,7 @@ static int dw_i2c_probe(struct platform_device *pdev) /* fast mode by default because of legacy reasons */ clk_freq = 400000; - if (ACPI_COMPANION(&pdev->dev)) { + if (has_acpi_companion(&pdev->dev)) { dw_i2c_acpi_configure(pdev); } else if (pdev->dev.of_node) { of_property_read_u32(pdev->dev.of_node, @@ -286,7 +286,7 @@ static int dw_i2c_remove(struct platform_device *pdev) pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); - if (ACPI_COMPANION(&pdev->dev)) + if (has_acpi_companion(&pdev->dev)) dw_i2c_acpi_unconfigure(pdev); return 0; diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index edf274cabe81..c87c31387e2d 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -133,7 +133,7 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, return AE_OK; memset(&info, 0, sizeof(info)); - info.acpi_node.companion = adev; + info.fwnode = acpi_fwnode_handle(adev); info.irq = -1; INIT_LIST_HEAD(&resource_list); @@ -971,7 +971,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) client->dev.bus = &i2c_bus_type; client->dev.type = &i2c_client_type; client->dev.of_node = info->of_node; - ACPI_COMPANION_SET(&client->dev, info->acpi_node.companion); + client->dev.fwnode = info->fwnode; i2c_dev_set_name(adap, client); status = device_register(&client->dev); diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c index e5f3db831373..f5f2b62471da 100644 --- a/drivers/ide/ide-pnp.c +++ b/drivers/ide/ide-pnp.c @@ -96,17 +96,5 @@ static struct pnp_driver idepnp_driver = { .remove = idepnp_remove, }; -static int __init pnpide_init(void) -{ - return pnp_register_driver(&idepnp_driver); -} - -static void __exit pnpide_exit(void) -{ - pnp_unregister_driver(&idepnp_driver); -} - -module_init(pnpide_init); -module_exit(pnpide_exit); - +module_pnp_driver(idepnp_driver); MODULE_LICENSE("GPL"); diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index b0e58522780d..1fb52f4e5870 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -218,18 +218,10 @@ static struct cpuidle_state byt_cstates[] = { .enter = &intel_idle, .enter_freeze = intel_idle_freeze, }, { - .name = "C1E-BYT", - .desc = "MWAIT 0x01", - .flags = MWAIT2flg(0x01), - .exit_latency = 15, - .target_residency = 30, - .enter = &intel_idle, - .enter_freeze = intel_idle_freeze, }, - { .name = "C6N-BYT", .desc = "MWAIT 0x58", .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, - .exit_latency = 40, + .exit_latency = 300, .target_residency = 275, .enter = &intel_idle, .enter_freeze = intel_idle_freeze, }, @@ -237,7 +229,7 @@ static struct cpuidle_state byt_cstates[] = { .name = "C6S-BYT", .desc = "MWAIT 0x52", .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, - .exit_latency = 140, + .exit_latency = 500, .target_residency = 560, .enter = &intel_idle, .enter_freeze = intel_idle_freeze, }, @@ -246,7 +238,7 @@ static struct cpuidle_state byt_cstates[] = { .desc = "MWAIT 0x60", .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 1200, - .target_residency = 1500, + .target_residency = 4000, .enter = &intel_idle, .enter_freeze = intel_idle_freeze, }, { @@ -261,6 +253,51 @@ static struct cpuidle_state byt_cstates[] = { .enter = NULL } }; +static struct cpuidle_state cht_cstates[] = { + { + .name = "C1-CHT", + .desc = "MWAIT 0x00", + .flags = MWAIT2flg(0x00), + .exit_latency = 1, + .target_residency = 1, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .name = "C6N-CHT", + .desc = "MWAIT 0x58", + .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 80, + .target_residency = 275, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .name = "C6S-CHT", + .desc = "MWAIT 0x52", + .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 200, + .target_residency = 560, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .name = "C7-CHT", + .desc = "MWAIT 0x60", + .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 1200, + .target_residency = 4000, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .name = "C7S-CHT", + .desc = "MWAIT 0x64", + .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 10000, + .target_residency = 20000, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .enter = NULL } +}; + static struct cpuidle_state ivb_cstates[] = { { .name = "C1-IVB", @@ -748,6 +785,12 @@ static const struct idle_cpu idle_cpu_byt = { .byt_auto_demotion_disable_flag = true, }; +static const struct idle_cpu idle_cpu_cht = { + .state_table = cht_cstates, + .disable_promotion_to_c1e = true, + .byt_auto_demotion_disable_flag = true, +}; + static const struct idle_cpu idle_cpu_ivb = { .state_table = ivb_cstates, .disable_promotion_to_c1e = true, @@ -776,7 +819,7 @@ static const struct idle_cpu idle_cpu_avn = { #define ICPU(model, cpu) \ { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } -static const struct x86_cpu_id intel_idle_ids[] = { +static const struct x86_cpu_id intel_idle_ids[] __initconst = { ICPU(0x1a, idle_cpu_nehalem), ICPU(0x1e, idle_cpu_nehalem), ICPU(0x1f, idle_cpu_nehalem), @@ -790,6 +833,7 @@ static const struct x86_cpu_id intel_idle_ids[] = { ICPU(0x2d, idle_cpu_snb), ICPU(0x36, idle_cpu_atom), ICPU(0x37, idle_cpu_byt), + ICPU(0x4c, idle_cpu_cht), ICPU(0x3a, idle_cpu_ivb), ICPU(0x3e, idle_cpu_ivt), ICPU(0x3c, idle_cpu_hsw), diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 2d1e05bdbb53..4fc1f8a7f98e 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -684,7 +684,7 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf if (dev_is_pci(dev)) { pdev = to_pci_dev(dev); segment = pci_domain_nr(pdev->bus); - } else if (ACPI_COMPANION(dev)) + } else if (has_acpi_companion(dev)) dev = &ACPI_COMPANION(dev)->dev; rcu_read_lock(); diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index e80f2c6c5f1a..8d77e1c4a141 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -1195,16 +1195,6 @@ static struct pnp_driver ene_driver = { .shutdown = ene_shutdown, }; -static int __init ene_init(void) -{ - return pnp_register_driver(&ene_driver); -} - -static void ene_exit(void) -{ - pnp_unregister_driver(&ene_driver); -} - module_param(sample_period, int, S_IRUGO); MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)"); @@ -1226,5 +1216,4 @@ MODULE_DESCRIPTION MODULE_AUTHOR("Maxim Levitsky"); MODULE_LICENSE("GPL"); -module_init(ene_init); -module_exit(ene_exit); +module_pnp_driver(ene_driver); diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c index b5167573240e..5c63c2ec6183 100644 --- a/drivers/media/rc/fintek-cir.c +++ b/drivers/media/rc/fintek-cir.c @@ -684,16 +684,6 @@ static struct pnp_driver fintek_driver = { .shutdown = fintek_shutdown, }; -static int __init fintek_init(void) -{ - return pnp_register_driver(&fintek_driver); -} - -static void __exit fintek_exit(void) -{ - pnp_unregister_driver(&fintek_driver); -} - module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Enable debugging output"); @@ -703,5 +693,4 @@ MODULE_DESCRIPTION(FINTEK_DESCRIPTION " driver"); MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); MODULE_LICENSE("GPL"); -module_init(fintek_init); -module_exit(fintek_exit); +module_pnp_driver(fintek_driver); diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index 56abf9120cc2..0f301903aa6f 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -1708,21 +1708,10 @@ static struct pnp_driver ite_driver = { .shutdown = ite_shutdown, }; -static int __init ite_init(void) -{ - return pnp_register_driver(&ite_driver); -} - -static void __exit ite_exit(void) -{ - pnp_unregister_driver(&ite_driver); -} - MODULE_DEVICE_TABLE(pnp, ite_ids); MODULE_DESCRIPTION("ITE Tech Inc. IT8712F/ITE8512F CIR driver"); MODULE_AUTHOR("Juan J. Garcia de Soria <skandalfo@gmail.com>"); MODULE_LICENSE("GPL"); -module_init(ite_init); -module_exit(ite_exit); +module_pnp_driver(ite_driver); diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 9c2c8635ff33..85af7a869167 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1219,16 +1219,6 @@ static struct pnp_driver nvt_driver = { .shutdown = nvt_shutdown, }; -static int __init nvt_init(void) -{ - return pnp_register_driver(&nvt_driver); -} - -static void __exit nvt_exit(void) -{ - pnp_unregister_driver(&nvt_driver); -} - module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Enable debugging output"); @@ -1238,5 +1228,4 @@ MODULE_DESCRIPTION("Nuvoton W83667HG-A & W83677HG-I CIR driver"); MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); MODULE_LICENSE("GPL"); -module_init(nvt_init); -module_exit(nvt_exit); +module_pnp_driver(nvt_driver); diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c index 38552a31304a..65fed7146e9b 100644 --- a/drivers/misc/enclosure.c +++ b/drivers/misc/enclosure.c @@ -202,16 +202,17 @@ static void enclosure_remove_links(struct enclosure_component *cdev) { char name[ENCLOSURE_NAME_SIZE]; + enclosure_link_name(cdev, name); + /* * In odd circumstances, like multipath devices, something else may * already have removed the links, so check for this condition first. */ - if (!cdev->dev->kobj.sd) - return; + if (cdev->dev->kobj.sd) + sysfs_remove_link(&cdev->dev->kobj, name); - enclosure_link_name(cdev, name); - sysfs_remove_link(&cdev->dev->kobj, name); - sysfs_remove_link(&cdev->cdev.kobj, "device"); + if (cdev->cdev.kobj.sd) + sysfs_remove_link(&cdev->cdev.kobj, "device"); } static int enclosure_add_links(struct enclosure_component *cdev) diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index 66c2f1a01963..aad0b59d41e3 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -1175,17 +1175,4 @@ MODULE_AUTHOR("Franco Venturi <fventuri@mediaone.net>"); MODULE_DESCRIPTION("General Instruments SB1000 driver"); MODULE_LICENSE("GPL"); -static int __init -sb1000_init(void) -{ - return pnp_register_driver(&sb1000_driver); -} - -static void __exit -sb1000_exit(void) -{ - pnp_unregister_driver(&sb1000_driver); -} - -module_init(sb1000_init); -module_exit(sb1000_exit); +module_pnp_driver(sb1000_driver); diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index b9429fbf1cd8..66d6d22c239c 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -624,19 +624,7 @@ static struct pnp_driver gmux_pnp_driver = { }, }; -static int __init apple_gmux_init(void) -{ - return pnp_register_driver(&gmux_pnp_driver); -} - -static void __exit apple_gmux_exit(void) -{ - pnp_unregister_driver(&gmux_pnp_driver); -} - -module_init(apple_gmux_init); -module_exit(apple_gmux_exit); - +module_pnp_driver(gmux_pnp_driver); MODULE_AUTHOR("Seth Forshee <seth.forshee@canonical.com>"); MODULE_DESCRIPTION("Apple Gmux Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index c8873b0ca551..3151fd164614 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -3,7 +3,7 @@ * Bjorn Helgaas <bjorn.helgaas@hp.com> */ -extern spinlock_t pnp_lock; +extern struct mutex pnp_lock; extern const struct attribute_group *pnp_dev_groups[]; void *pnp_alloc(long size); diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index 874c236ac1a7..31ad9fc3f701 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -5,6 +5,7 @@ */ #include <linux/module.h> +#include <linux/mutex.h> #include <linux/ctype.h> #include <linux/slab.h> #include <linux/pnp.h> @@ -244,10 +245,10 @@ int pnp_add_card(struct pnp_card *card) } pnp_interface_attach_card(card); - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); list_add_tail(&card->global_list, &pnp_cards); list_add_tail(&card->protocol_list, &card->protocol->cards); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); /* we wait until now to add devices in order to ensure the drivers * will be able to use all of the related devices on the card @@ -276,10 +277,10 @@ void pnp_remove_card(struct pnp_card *card) struct list_head *pos, *temp; device_unregister(&card->dev); - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); list_del(&card->global_list); list_del(&card->protocol_list); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); list_for_each_safe(pos, temp, &card->devices) { struct pnp_dev *dev = card_to_pnp_dev(pos); pnp_remove_card_device(dev); @@ -297,10 +298,10 @@ int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) dev->card_link = NULL; dev_set_name(&dev->dev, "%02x:%02x.%02x", dev->protocol->number, card->number, dev->number); - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); dev->card = card; list_add_tail(&dev->card_list, &card->devices); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); return 0; } @@ -310,10 +311,10 @@ int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) */ void pnp_remove_card_device(struct pnp_dev *dev) { - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); dev->card = NULL; list_del(&dev->card_list); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); __pnp_remove_device(dev); } @@ -426,9 +427,9 @@ int pnp_register_card_driver(struct pnp_card_driver *drv) if (error < 0) return error; - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); list_add_tail(&drv->global_list, &pnp_card_drivers); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); list_for_each_safe(pos, temp, &pnp_cards) { struct pnp_card *card = @@ -444,9 +445,9 @@ int pnp_register_card_driver(struct pnp_card_driver *drv) */ void pnp_unregister_card_driver(struct pnp_card_driver *drv) { - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); list_del(&drv->global_list); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); pnp_unregister_driver(&drv->link); } diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index cb6ce42f8e77..b54620e53830 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c @@ -9,6 +9,7 @@ #include <linux/list.h> #include <linux/device.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/init.h> #include <linux/string.h> #include <linux/slab.h> @@ -19,7 +20,7 @@ static LIST_HEAD(pnp_protocols); LIST_HEAD(pnp_global); -DEFINE_SPINLOCK(pnp_lock); +DEFINE_MUTEX(pnp_lock); /* * ACPI or PNPBIOS should tell us about all platform devices, so we can @@ -41,6 +42,13 @@ void *pnp_alloc(long size) return result; } +static void pnp_remove_protocol(struct pnp_protocol *protocol) +{ + mutex_lock(&pnp_lock); + list_del(&protocol->protocol_list); + mutex_unlock(&pnp_lock); +} + /** * pnp_protocol_register - adds a pnp protocol to the pnp layer * @protocol: pointer to the corresponding pnp_protocol structure @@ -49,13 +57,14 @@ void *pnp_alloc(long size) */ int pnp_register_protocol(struct pnp_protocol *protocol) { - int nodenum; struct list_head *pos; + int nodenum, ret; INIT_LIST_HEAD(&protocol->devices); INIT_LIST_HEAD(&protocol->cards); nodenum = 0; - spin_lock(&pnp_lock); + + mutex_lock(&pnp_lock); /* assign the lowest unused number */ list_for_each(pos, &pnp_protocols) { @@ -66,12 +75,18 @@ int pnp_register_protocol(struct pnp_protocol *protocol) } } - list_add_tail(&protocol->protocol_list, &pnp_protocols); - spin_unlock(&pnp_lock); - protocol->number = nodenum; dev_set_name(&protocol->dev, "pnp%d", nodenum); - return device_register(&protocol->dev); + + list_add_tail(&protocol->protocol_list, &pnp_protocols); + + mutex_unlock(&pnp_lock); + + ret = device_register(&protocol->dev); + if (ret) + pnp_remove_protocol(protocol); + + return ret; } /** @@ -80,9 +95,7 @@ int pnp_register_protocol(struct pnp_protocol *protocol) */ void pnp_unregister_protocol(struct pnp_protocol *protocol) { - spin_lock(&pnp_lock); - list_del(&protocol->protocol_list); - spin_unlock(&pnp_lock); + pnp_remove_protocol(protocol); device_unregister(&protocol->dev); } @@ -157,18 +170,36 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, return dev; } +static void pnp_delist_device(struct pnp_dev *dev) +{ + mutex_lock(&pnp_lock); + list_del(&dev->global_list); + list_del(&dev->protocol_list); + mutex_unlock(&pnp_lock); +} + int __pnp_add_device(struct pnp_dev *dev) { + int ret; + pnp_fixup_device(dev); dev->status = PNP_READY; - spin_lock(&pnp_lock); + + mutex_lock(&pnp_lock); + list_add_tail(&dev->global_list, &pnp_global); list_add_tail(&dev->protocol_list, &dev->protocol->devices); - spin_unlock(&pnp_lock); - if (dev->protocol->can_wakeup) + + mutex_unlock(&pnp_lock); + + ret = device_register(&dev->dev); + if (ret) + pnp_delist_device(dev); + else if (dev->protocol->can_wakeup) device_set_wakeup_capable(&dev->dev, dev->protocol->can_wakeup(dev)); - return device_register(&dev->dev); + + return ret; } /* @@ -203,10 +234,7 @@ int pnp_add_device(struct pnp_dev *dev) void __pnp_remove_device(struct pnp_dev *dev) { - spin_lock(&pnp_lock); - list_del(&dev->global_list); - list_del(&dev->protocol_list); - spin_unlock(&pnp_lock); + pnp_delist_device(dev); device_unregister(&dev->dev); } diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 4e57d3370368..153a493b5413 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -58,22 +58,22 @@ static const struct pnp_device_id *match_device(struct pnp_driver *drv, int pnp_device_attach(struct pnp_dev *pnp_dev) { - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); if (pnp_dev->status != PNP_READY) { - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); return -EBUSY; } pnp_dev->status = PNP_ATTACHED; - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); return 0; } void pnp_device_detach(struct pnp_dev *pnp_dev) { - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); if (pnp_dev->status == PNP_ATTACHED) pnp_dev->status = PNP_READY; - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); pnp_disable_dev(pnp_dev); } diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index d2b780aade89..5153d1d69aee 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -248,6 +248,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) if (!dev) return -ENOMEM; + ACPI_COMPANION_SET(&dev->dev, device); dev->data = device; /* .enabled means the device can decode the resources */ dev->active = device->status.enabled; @@ -290,11 +291,9 @@ static int __init pnpacpi_add_device(struct acpi_device *device) return error; } - error = acpi_bind_one(&dev->dev, device); - num++; - return error; + return 0; } static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index a7cc61837818..923a2b5a2439 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -5734,9 +5734,9 @@ free_port: hba_free: if (phba->msix_enabled) pci_disable_msix(phba->pcidev); - iscsi_host_remove(phba->shost); pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); + pci_set_drvdata(pcidev, NULL); disable_pci: pci_disable_device(pcidev); return ret; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 54d7a6cbb98a..b1a263137a23 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1311,9 +1311,11 @@ scsi_prep_state_check(struct scsi_device *sdev, struct request *req) "rejecting I/O to dead device\n"); ret = BLKPREP_KILL; break; - case SDEV_QUIESCE: case SDEV_BLOCK: case SDEV_CREATED_BLOCK: + ret = BLKPREP_DEFER; + break; + case SDEV_QUIESCE: /* * If the devices is blocked we defer normal commands. */ diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 2accb6e47beb..77d64251af40 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1181,7 +1181,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, * traditional iSCSI block I/O. */ if (iscsit_allocate_iovecs(cmd) < 0) { - return iscsit_add_reject_cmd(cmd, + return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); } immed_data = cmd->immediate_data; @@ -3468,6 +3468,7 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd, tpg_np_list) { struct iscsi_np *np = tpg_np->tpg_np; bool inaddr_any = iscsit_check_inaddr_any(np); + char *fmt_str; if (np->np_network_transport != network_transport) continue; @@ -3495,8 +3496,12 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd, } } - len = sprintf(buf, "TargetAddress=" - "%s:%hu,%hu", + if (np->np_sockaddr.ss_family == AF_INET6) + fmt_str = "TargetAddress=[%s]:%hu,%hu"; + else + fmt_str = "TargetAddress=%s:%hu,%hu"; + + len = sprintf(buf, fmt_str, inaddr_any ? conn->local_ip : np->np_ip, np->np_port, tpg->tpgt); diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 79b4ec3ca2db..7faa6aef9a4d 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -781,8 +781,8 @@ int se_dev_set_emulate_fua_write(struct se_device *dev, int flag) } if (flag && dev->transport->get_write_cache) { - pr_err("emulate_fua_write not supported for this device\n"); - return -EINVAL; + pr_warn("emulate_fua_write not supported for this device, ignoring\n"); + return 0; } if (dev->export_count) { pr_err("emulate_fua_write cannot be changed with active" diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c index d1ec5804c0bb..76c515dd802b 100644 --- a/drivers/thermal/st/st_thermal.c +++ b/drivers/thermal/st/st_thermal.c @@ -25,7 +25,7 @@ * Function to allocate regfields which are common * between syscfg and memory mapped based sensors */ -int st_thermal_alloc_regfields(struct st_thermal_sensor *sensor) +static int st_thermal_alloc_regfields(struct st_thermal_sensor *sensor) { struct device *dev = sensor->dev; struct regmap *regmap = sensor->regmap; diff --git a/drivers/thermal/st/st_thermal_memmap.c b/drivers/thermal/st/st_thermal_memmap.c index 067bfcdb91d6..fc0c9e198710 100644 --- a/drivers/thermal/st/st_thermal_memmap.c +++ b/drivers/thermal/st/st_thermal_memmap.c @@ -157,7 +157,7 @@ static const struct st_thermal_sensor_ops st_mmap_sensor_ops = { }; /* Compatible device data stih416 mpe thermal sensor */ -const struct st_thermal_compat_data st_416mpe_cdata = { +static const struct st_thermal_compat_data st_416mpe_cdata = { .reg_fields = st_mmap_thermal_regfields, .ops = &st_mmap_sensor_ops, .calibration_val = 14, @@ -166,7 +166,7 @@ const struct st_thermal_compat_data st_416mpe_cdata = { }; /* Compatible device data stih407 thermal sensor */ -const struct st_thermal_compat_data st_407_cdata = { +static const struct st_thermal_compat_data st_407_cdata = { .reg_fields = st_mmap_thermal_regfields, .ops = &st_mmap_sensor_ops, .calibration_val = 16, @@ -174,19 +174,19 @@ const struct st_thermal_compat_data st_407_cdata = { .crit_temp = 120, }; -static struct of_device_id st_mmap_thermal_of_match[] = { +static const struct of_device_id st_mmap_thermal_of_match[] = { { .compatible = "st,stih416-mpe-thermal", .data = &st_416mpe_cdata }, { .compatible = "st,stih407-thermal", .data = &st_407_cdata }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, st_mmap_thermal_of_match); -int st_mmap_probe(struct platform_device *pdev) +static int st_mmap_probe(struct platform_device *pdev) { return st_thermal_register(pdev, st_mmap_thermal_of_match); } -int st_mmap_remove(struct platform_device *pdev) +static int st_mmap_remove(struct platform_device *pdev) { return st_thermal_unregister(pdev); } diff --git a/drivers/thermal/st/st_thermal_syscfg.c b/drivers/thermal/st/st_thermal_syscfg.c index 26d36a242bb8..3df5b7890703 100644 --- a/drivers/thermal/st/st_thermal_syscfg.c +++ b/drivers/thermal/st/st_thermal_syscfg.c @@ -104,7 +104,7 @@ static const struct st_thermal_sensor_ops st_syscfg_sensor_ops = { }; /* Compatible device data for stih415 sas thermal sensor */ -const struct st_thermal_compat_data st_415sas_cdata = { +static const struct st_thermal_compat_data st_415sas_cdata = { .sys_compat = "st,stih415-front-syscfg", .reg_fields = st_415sas_regfields, .ops = &st_syscfg_sensor_ops, @@ -114,7 +114,7 @@ const struct st_thermal_compat_data st_415sas_cdata = { }; /* Compatible device data for stih415 mpe thermal sensor */ -const struct st_thermal_compat_data st_415mpe_cdata = { +static const struct st_thermal_compat_data st_415mpe_cdata = { .sys_compat = "st,stih415-system-syscfg", .reg_fields = st_415mpe_regfields, .ops = &st_syscfg_sensor_ops, @@ -124,7 +124,7 @@ const struct st_thermal_compat_data st_415mpe_cdata = { }; /* Compatible device data for stih416 sas thermal sensor */ -const struct st_thermal_compat_data st_416sas_cdata = { +static const struct st_thermal_compat_data st_416sas_cdata = { .sys_compat = "st,stih416-front-syscfg", .reg_fields = st_416sas_regfields, .ops = &st_syscfg_sensor_ops, @@ -134,7 +134,7 @@ const struct st_thermal_compat_data st_416sas_cdata = { }; /* Compatible device data for stid127 thermal sensor */ -const struct st_thermal_compat_data st_127_cdata = { +static const struct st_thermal_compat_data st_127_cdata = { .sys_compat = "st,stid127-cpu-syscfg", .reg_fields = st_127_regfields, .ops = &st_syscfg_sensor_ops, @@ -143,7 +143,7 @@ const struct st_thermal_compat_data st_127_cdata = { .crit_temp = 120, }; -static struct of_device_id st_syscfg_thermal_of_match[] = { +static const struct of_device_id st_syscfg_thermal_of_match[] = { { .compatible = "st,stih415-sas-thermal", .data = &st_415sas_cdata }, { .compatible = "st,stih415-mpe-thermal", .data = &st_415mpe_cdata }, { .compatible = "st,stih416-sas-thermal", .data = &st_416sas_cdata }, @@ -152,12 +152,12 @@ static struct of_device_id st_syscfg_thermal_of_match[] = { }; MODULE_DEVICE_TABLE(of, st_syscfg_thermal_of_match); -int st_syscfg_probe(struct platform_device *pdev) +static int st_syscfg_probe(struct platform_device *pdev) { return st_thermal_register(pdev, st_syscfg_thermal_of_match); } -int st_syscfg_remove(struct platform_device *pdev) +static int st_syscfg_remove(struct platform_device *pdev) { return st_thermal_unregister(pdev); } diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 174d3bcf8bd7..4108db7e10c1 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -458,8 +458,10 @@ static void update_temperature(struct thermal_zone_device *tz) ret = thermal_zone_get_temp(tz, &temp); if (ret) { - dev_warn(&tz->device, "failed to read out thermal zone %d\n", - tz->id); + if (ret != -EAGAIN) + dev_warn(&tz->device, + "failed to read out thermal zone (%d)\n", + ret); return; } diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index 1e6899bc9429..5815e81b5fc6 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -234,18 +234,7 @@ static struct pnp_driver fintek_8250_driver = { .id_table = fintek_dev_table, }; -static int fintek_8250_init(void) -{ - return pnp_register_driver(&fintek_8250_driver); -} -module_init(fintek_8250_init); - -static void fintek_8250_exit(void) -{ - pnp_unregister_driver(&fintek_8250_driver); -} -module_exit(fintek_8250_exit); - +module_pnp_driver(fintek_8250_driver); MODULE_DESCRIPTION("Fintek F812164 module"); MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>"); MODULE_LICENSE("GPL"); @@ -278,11 +278,11 @@ static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -static void aio_ring_remap(struct file *file, struct vm_area_struct *vma) +static int aio_ring_remap(struct file *file, struct vm_area_struct *vma) { struct mm_struct *mm = vma->vm_mm; struct kioctx_table *table; - int i; + int i, res = -EINVAL; spin_lock(&mm->ioctx_lock); rcu_read_lock(); @@ -292,13 +292,17 @@ static void aio_ring_remap(struct file *file, struct vm_area_struct *vma) ctx = table->table[i]; if (ctx && ctx->aio_ring_file == file) { - ctx->user_id = ctx->mmap_base = vma->vm_start; + if (!atomic_read(&ctx->dead)) { + ctx->user_id = ctx->mmap_base = vma->vm_start; + res = 0; + } break; } } rcu_read_unlock(); spin_unlock(&mm->ioctx_lock); + return res; } static const struct file_operations aio_ring_fops = { @@ -727,6 +731,9 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) err_cleanup: aio_nr_sub(ctx->max_reqs); err_ctx: + atomic_set(&ctx->dead, 1); + if (ctx->mmap_size) + vm_munmap(ctx->mmap_base, ctx->mmap_size); aio_free_ring(ctx); err: mutex_unlock(&ctx->ring_lock); @@ -748,11 +755,12 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx, { struct kioctx_table *table; - if (atomic_xchg(&ctx->dead, 1)) + spin_lock(&mm->ioctx_lock); + if (atomic_xchg(&ctx->dead, 1)) { + spin_unlock(&mm->ioctx_lock); return -EINVAL; + } - - spin_lock(&mm->ioctx_lock); table = rcu_dereference_raw(mm->ioctx_table); WARN_ON(ctx != table->table[ctx->id]); table->table[ctx->id] = NULL; diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 46e0d4e857c7..ba1790e52ff2 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -2394,7 +2394,6 @@ relock: /* * for completing the rest of the request. */ - *ppos += written; count -= written; written_buffered = generic_perform_write(file, from, *ppos); /* @@ -2409,7 +2408,6 @@ relock: goto out_dio; } - iocb->ki_pos = *ppos + written_buffered; /* We need to ensure that the page cache pages are written to * disk and invalidated to preserve the expected O_DIRECT * semantics. @@ -2418,6 +2416,7 @@ relock: ret = filemap_write_and_wait_range(file->f_mapping, *ppos, endbyte); if (ret == 0) { + iocb->ki_pos = *ppos + written_buffered; written += written_buffered; invalidate_mapping_pages(mapping, *ppos >> PAGE_CACHE_SHIFT, @@ -2440,10 +2439,14 @@ out_dio: /* buffered aio wouldn't have proper lock coverage today */ BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); + if (unlikely(written <= 0)) + goto no_sync; + if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || ((file->f_flags & O_DIRECT) && !direct_io)) { - ret = filemap_fdatawrite_range(file->f_mapping, *ppos, - *ppos + count - 1); + ret = filemap_fdatawrite_range(file->f_mapping, + iocb->ki_pos - written, + iocb->ki_pos - 1); if (ret < 0) written = ret; @@ -2454,10 +2457,12 @@ out_dio: } if (!ret) - ret = filemap_fdatawait_range(file->f_mapping, *ppos, - *ppos + count - 1); + ret = filemap_fdatawait_range(file->f_mapping, + iocb->ki_pos - written, + iocb->ki_pos - 1); } +no_sync: /* * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io * function pointer which is called when o_direct io completes so that diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 61e32ec1fc4d..8de4fa90e8c4 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -252,6 +252,7 @@ struct acpi_device_pnp { #define acpi_device_bid(d) ((d)->pnp.bus_id) #define acpi_device_adr(d) ((d)->pnp.bus_address) const char *acpi_device_hid(struct acpi_device *device); +#define acpi_device_uid(d) ((d)->pnp.unique_id) #define acpi_device_name(d) ((d)->pnp.device_name) #define acpi_device_class(d) ((d)->pnp.device_class) @@ -386,7 +387,8 @@ static inline bool is_acpi_node(struct fwnode_handle *fwnode) static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode) { - return fwnode ? container_of(fwnode, struct acpi_device, fwnode) : NULL; + return is_acpi_node(fwnode) ? + container_of(fwnode, struct acpi_device, fwnode) : NULL; } static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index ac78910d7416..91c09305106d 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -167,6 +167,7 @@ #define IOMMU_OF_TABLES() OF_TABLE(CONFIG_OF_IOMMU, iommu) #define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem) #define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method) +#define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method) #define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon) #define KERNEL_DTB() \ @@ -501,6 +502,7 @@ CLKSRC_OF_TABLES() \ IOMMU_OF_TABLES() \ CPU_METHOD_OF_TABLES() \ + CPUIDLE_METHOD_OF_TABLES() \ KERNEL_DTB() \ IRQCHIP_OF_MATCH_TABLE() \ EARLYCON_OF_TABLES() diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 24c7aa8b1d20..dd12127f171c 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -53,10 +53,16 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev) return adev ? adev->handle : NULL; } -#define ACPI_COMPANION(dev) ((dev)->acpi_node.companion) -#define ACPI_COMPANION_SET(dev, adev) ACPI_COMPANION(dev) = (adev) +#define ACPI_COMPANION(dev) acpi_node((dev)->fwnode) +#define ACPI_COMPANION_SET(dev, adev) set_primary_fwnode(dev, (adev) ? \ + acpi_fwnode_handle(adev) : NULL) #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) +static inline bool has_acpi_companion(struct device *dev) +{ + return is_acpi_node(dev->fwnode); +} + static inline void acpi_preset_companion(struct device *dev, struct acpi_device *parent, u64 addr) { @@ -471,6 +477,11 @@ static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev) return NULL; } +static inline bool has_acpi_companion(struct device *dev) +{ + return false; +} + static inline const char *acpi_dev_name(struct acpi_device *adev) { return NULL; diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index c294e3e25e37..a1b25e35ea5f 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -181,7 +181,9 @@ enum rq_flag_bits { __REQ_ELVPRIV, /* elevator private data attached */ __REQ_FAILED, /* set if the request failed */ __REQ_QUIET, /* don't worry about errors */ - __REQ_PREEMPT, /* set for "ide_preempt" requests */ + __REQ_PREEMPT, /* set for "ide_preempt" requests and also + for requests for which the SCSI "quiesce" + state must be ignored. */ __REQ_ALLOCED, /* request came from our alloc pool */ __REQ_COPY_USER, /* contains copies of user pages */ __REQ_FLUSH_SEQ, /* request for flush sequence */ diff --git a/include/linux/device.h b/include/linux/device.h index 0eb8ee2dc6d1..324d02add7b4 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -38,6 +38,7 @@ struct class; struct subsys_private; struct bus_type; struct device_node; +struct fwnode_handle; struct iommu_ops; struct iommu_group; @@ -650,14 +651,6 @@ struct device_dma_parameters { unsigned long segment_boundary_mask; }; -struct acpi_device; - -struct acpi_dev_node { -#ifdef CONFIG_ACPI - struct acpi_device *companion; -#endif -}; - /** * struct device - The basic device structure * @parent: The device's "parent" device, the device to which it is attached. @@ -703,7 +696,7 @@ struct acpi_dev_node { * @cma_area: Contiguous memory area for dma allocations * @archdata: For arch-specific additions. * @of_node: Associated device tree node. - * @acpi_node: Associated ACPI device node. + * @fwnode: Associated device node supplied by platform firmware. * @devt: For creating the sysfs "dev". * @id: device instance * @devres_lock: Spinlock to protect the resource of the device. @@ -779,7 +772,7 @@ struct device { struct dev_archdata archdata; struct device_node *of_node; /* associated device tree node */ - struct acpi_dev_node acpi_node; /* associated ACPI device node */ + struct fwnode_handle *fwnode; /* firmware device node */ dev_t devt; /* dev_t, creates the sysfs "dev" */ u32 id; /* device instance */ @@ -947,6 +940,9 @@ extern void unlock_device_hotplug(void); extern int lock_device_hotplug_sysfs(void); extern int device_offline(struct device *dev); extern int device_online(struct device *dev); +extern void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode); +extern void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode); + /* * Root device objects for grouping under /sys/devices */ diff --git a/include/linux/fs.h b/include/linux/fs.h index f4131e8ead74..52cc4492cb3a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1549,7 +1549,7 @@ struct file_operations { long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); - void (*mremap)(struct file *, struct vm_area_struct *); + int (*mremap)(struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h new file mode 100644 index 000000000000..0408545bce42 --- /dev/null +++ b/include/linux/fwnode.h @@ -0,0 +1,27 @@ +/* + * fwnode.h - Firmware device node object handle type definition. + * + * Copyright (C) 2015, Intel Corporation + * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + * + * 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. + */ + +#ifndef _LINUX_FWNODE_H_ +#define _LINUX_FWNODE_H_ + +enum fwnode_type { + FWNODE_INVALID = 0, + FWNODE_OF, + FWNODE_ACPI, + FWNODE_PDATA, +}; + +struct fwnode_handle { + enum fwnode_type type; + struct fwnode_handle *secondary; +}; + +#endif diff --git a/include/linux/i2c.h b/include/linux/i2c.h index f17da50402a4..6d89575361a8 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -278,7 +278,7 @@ static inline int i2c_slave_event(struct i2c_client *client, * @platform_data: stored in i2c_client.dev.platform_data * @archdata: copied into i2c_client.dev.archdata * @of_node: pointer to OpenFirmware device node - * @acpi_node: ACPI device node + * @fwnode: device node supplied by the platform firmware * @irq: stored in i2c_client.irq * * I2C doesn't actually support hardware probing, although controllers and @@ -299,7 +299,7 @@ struct i2c_board_info { void *platform_data; struct dev_archdata *archdata; struct device_node *of_node; - struct acpi_dev_node acpi_node; + struct fwnode_handle *fwnode; int irq; }; diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index ae4882ca4a64..58f1e75ba105 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -59,7 +59,7 @@ extern int platform_add_devices(struct platform_device **, int); struct platform_device_info { struct device *parent; - struct acpi_dev_node acpi_node; + struct fwnode_handle *fwnode; const char *name; int id; diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 6512e9cbc6d5..5df733b8f704 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -510,4 +510,16 @@ static inline void pnp_unregister_driver(struct pnp_driver *drv) { } #endif /* CONFIG_PNP */ +/** + * module_pnp_driver() - Helper macro for registering a PnP driver + * @__pnp_driver: pnp_driver struct + * + * Helper macro for PnP drivers which do not do anything special in module + * init/exit. This eliminates a lot of boilerplate. Each module may only + * use this macro once, and calling it replaces module_init() and module_exit() + */ +#define module_pnp_driver(__pnp_driver) \ + module_driver(__pnp_driver, pnp_register_driver, \ + pnp_unregister_driver) + #endif /* _LINUX_PNP_H */ diff --git a/include/linux/property.h b/include/linux/property.h index a6a3d98bd7e9..de8bdf417a35 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -13,6 +13,7 @@ #ifndef _LINUX_PROPERTY_H_ #define _LINUX_PROPERTY_H_ +#include <linux/fwnode.h> #include <linux/types.h> struct device; @@ -40,16 +41,6 @@ int device_property_read_string_array(struct device *dev, const char *propname, int device_property_read_string(struct device *dev, const char *propname, const char **val); -enum fwnode_type { - FWNODE_INVALID = 0, - FWNODE_OF, - FWNODE_ACPI, -}; - -struct fwnode_handle { - enum fwnode_type type; -}; - bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname); int fwnode_property_read_u8_array(struct fwnode_handle *fwnode, const char *propname, u8 *val, @@ -140,4 +131,37 @@ static inline int fwnode_property_read_u64(struct fwnode_handle *fwnode, return fwnode_property_read_u64_array(fwnode, propname, val, 1); } +/** + * struct property_entry - "Built-in" device property representation. + * @name: Name of the property. + * @type: Type of the property. + * @nval: Number of items of type @type making up the value. + * @value: Value of the property (an array of @nval items of type @type). + */ +struct property_entry { + const char *name; + enum dev_prop_type type; + size_t nval; + union { + void *raw_data; + u8 *u8_data; + u16 *u16_data; + u32 *u32_data; + u64 *u64_data; + const char **str; + } value; +}; + +/** + * struct property_set - Collection of "built-in" device properties. + * @fwnode: Handle to be pointed to by the fwnode field of struct device. + * @properties: Array of properties terminated with a null entry. + */ +struct property_set { + struct fwnode_handle fwnode; + struct property_entry *properties; +}; + +void device_add_property_set(struct device *dev, struct property_set *pset); + #endif /* _LINUX_PROPERTY_H_ */ diff --git a/mm/mremap.c b/mm/mremap.c index 57dadc025c64..2dc44b1cb1df 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -286,8 +286,14 @@ static unsigned long move_vma(struct vm_area_struct *vma, old_len = new_len; old_addr = new_addr; new_addr = -ENOMEM; - } else if (vma->vm_file && vma->vm_file->f_op->mremap) - vma->vm_file->f_op->mremap(vma->vm_file, new_vma); + } else if (vma->vm_file && vma->vm_file->f_op->mremap) { + err = vma->vm_file->f_op->mremap(vma->vm_file, new_vma); + if (err < 0) { + move_page_tables(new_vma, new_addr, vma, old_addr, + moved_len, true); + return err; + } + } /* Conceal VM_ACCOUNT so old reservation is not undone */ if (vm_flags & VM_ACCOUNT) { diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c index a422aaa3bb0c..9ee25a63f684 100644 --- a/sound/firewire/bebob/bebob_maudio.c +++ b/sound/firewire/bebob/bebob_maudio.c @@ -96,10 +96,10 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit) struct fw_device *device = fw_parent_device(unit); int err, rcode; u64 date; - __be32 cues[3] = { - MAUDIO_BOOTLOADER_CUE1, - MAUDIO_BOOTLOADER_CUE2, - MAUDIO_BOOTLOADER_CUE3 + __le32 cues[3] = { + cpu_to_le32(MAUDIO_BOOTLOADER_CUE1), + cpu_to_le32(MAUDIO_BOOTLOADER_CUE2), + cpu_to_le32(MAUDIO_BOOTLOADER_CUE3) }; /* check date of software used to build */ diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 74382137b9f5..f9d12c0a7e5a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2912,6 +2912,8 @@ static void alc283_init(struct hda_codec *codec) if (!hp_pin) return; + + msleep(30); hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); /* Index 0x43 Direct Drive HP AMP LPM Control 1 */ @@ -3607,6 +3609,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) switch (codec->vendor_id) { case 0x10ec0255: + case 0x10ec0256: alc_process_coef_fw(codec, coef0255); break; case 0x10ec0233: @@ -3662,6 +3665,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, switch (codec->vendor_id) { case 0x10ec0255: + case 0x10ec0256: alc_write_coef_idx(codec, 0x45, 0xc489); snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); alc_process_coef_fw(codec, coef0255); @@ -3731,6 +3735,7 @@ static void alc_headset_mode_default(struct hda_codec *codec) switch (codec->vendor_id) { case 0x10ec0255: + case 0x10ec0256: alc_process_coef_fw(codec, coef0255); break; case 0x10ec0233: @@ -3785,6 +3790,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) switch (codec->vendor_id) { case 0x10ec0255: + case 0x10ec0256: alc_process_coef_fw(codec, coef0255); break; case 0x10ec0233: @@ -3839,6 +3845,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) switch (codec->vendor_id) { case 0x10ec0255: + case 0x10ec0256: alc_process_coef_fw(codec, coef0255); break; case 0x10ec0233: @@ -3884,6 +3891,7 @@ static void alc_determine_headset_type(struct hda_codec *codec) switch (codec->vendor_id) { case 0x10ec0255: + case 0x10ec0256: alc_process_coef_fw(codec, coef0255); msleep(300); val = alc_read_coef_idx(codec, 0x46); @@ -4364,6 +4372,7 @@ enum { ALC269_FIXUP_QUANTA_MUTE, ALC269_FIXUP_LIFEBOOK, ALC269_FIXUP_LIFEBOOK_EXTMIC, + ALC269_FIXUP_LIFEBOOK_HP_PIN, ALC269_FIXUP_AMIC, ALC269_FIXUP_DMIC, ALC269VB_FIXUP_AMIC, @@ -4517,6 +4526,13 @@ static const struct hda_fixup alc269_fixups[] = { { } }, }, + [ALC269_FIXUP_LIFEBOOK_HP_PIN] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x21, 0x0221102f }, /* HP out */ + { } + }, + }, [ALC269_FIXUP_AMIC] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -5010,6 +5026,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX), SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), + SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN), SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC), @@ -5217,6 +5234,16 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x17, 0x40000000}, {0x1d, 0x40700001}, {0x21, 0x02211050}), + SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + {0x12, 0x90a60140}, + {0x13, 0x40000000}, + {0x14, 0x90170110}, + {0x19, 0x411111f0}, + {0x1a, 0x411111f0}, + {0x1b, 0x411111f0}, + {0x1d, 0x40700001}, + {0x1e, 0x411111f0}, + {0x21, 0x02211020}), SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4, {0x12, 0x90a60130}, {0x13, 0x40000000}, diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 9974f201a08f..474cae82a874 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -1156,25 +1156,6 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream, ret, pcm512x->pll_out); return ret; } - - gpio = PCM512x_G1OE << (4 - 1); - ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_EN, - gpio, gpio); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable gpio %d: %d\n", - 4, ret); - return ret; - } - - gpio = PCM512x_GPIO_OUTPUT_1 + 4 - 1; - ret = regmap_update_bits(pcm512x->regmap, gpio, - PCM512x_GxSL, PCM512x_GxSL_PLLLK); - if (ret != 0) { - dev_err(codec->dev, - "Failed to output pll lock on %d: %d\n", - ret, 4); - return ret; - } } ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE, diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index dc9df007d3e3..337c317ead6f 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -192,6 +192,7 @@ static const struct rc_config { { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ { USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 */ { USB_ID(0x041e, 0x30df), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ + { USB_ID(0x041e, 0x3237), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ }; diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 753a47de8459..9a28365126f9 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1113,8 +1113,13 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) { - /* MS Lifecam HD-5000 doesn't support reading the sample rate. */ - return chip->usb_id == USB_ID(0x045E, 0x076D); + /* devices which do not support reading the sample rate. */ + switch (chip->usb_id) { + case USB_ID(0x045E, 0x076D): /* MS Lifecam HD-5000 */ + case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */ + return true; + } + return false; } /* Marantz/Denon USB DACs need a vendor cmd to switch |