diff options
Diffstat (limited to 'drivers')
122 files changed, 2748 insertions, 1005 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b23fe37f67c0..79078b8f5697 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -360,15 +360,14 @@ config ACPI_BGRT config ACPI_REDUCED_HARDWARE_ONLY bool "Hardware-reduced ACPI support only" if EXPERT def_bool n - depends on ACPI help - This config item changes the way the ACPI code is built. When this - option is selected, the kernel will use a specialized version of - ACPICA that ONLY supports the ACPI "reduced hardware" mode. The - resulting kernel will be smaller but it will also be restricted to - running in ACPI reduced hardware mode ONLY. + This config item changes the way the ACPI code is built. When this + option is selected, the kernel will use a specialized version of + ACPICA that ONLY supports the ACPI "reduced hardware" mode. The + resulting kernel will be smaller but it will also be restricted to + running in ACPI reduced hardware mode ONLY. - If you are unsure what to do, do not enable this option. + If you are unsure what to do, do not enable this option. source "drivers/acpi/apei/Kconfig" diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index c3b2fcb729f3..6d11522f0e48 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -47,6 +47,7 @@ acpi-y += int340x_thermal.o acpi-y += power.o acpi-y += event.o acpi-y += sysfs.o +acpi-y += property.o acpi-$(CONFIG_X86) += acpi_cmos_rtc.o acpi-$(CONFIG_DEBUG_FS) += debugfs.o acpi-$(CONFIG_ACPI_NUMA) += numa.o diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 93d160661f4c..d1dd0ada14b7 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -1,7 +1,7 @@ /* * ACPI support for Intel Lynxpoint LPSS. * - * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2013, 2014, Intel Corporation * Authors: Mika Westerberg <mika.westerberg@linux.intel.com> * Rafael J. Wysocki <rafael.j.wysocki@intel.com> * @@ -60,6 +60,8 @@ ACPI_MODULE_NAME("acpi_lpss"); #define LPSS_CLK_DIVIDER BIT(2) #define LPSS_LTR BIT(3) #define LPSS_SAVE_CTX BIT(4) +#define LPSS_DEV_PROXY BIT(5) +#define LPSS_PROXY_REQ BIT(6) struct lpss_private_data; @@ -70,8 +72,10 @@ struct lpss_device_desc { void (*setup)(struct lpss_private_data *pdata); }; +static struct device *proxy_device; + static struct lpss_device_desc lpss_dma_desc = { - .flags = LPSS_CLK, + .flags = LPSS_CLK | LPSS_PROXY_REQ, }; struct lpss_private_data { @@ -146,22 +150,24 @@ static struct lpss_device_desc byt_pwm_dev_desc = { }; static struct lpss_device_desc byt_uart_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX | + LPSS_DEV_PROXY, .prv_offset = 0x800, .setup = lpss_uart_setup, }; static struct lpss_device_desc byt_spi_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX | + LPSS_DEV_PROXY, .prv_offset = 0x400, }; static struct lpss_device_desc byt_sdio_dev_desc = { - .flags = LPSS_CLK, + .flags = LPSS_CLK | LPSS_DEV_PROXY, }; static struct lpss_device_desc byt_i2c_dev_desc = { - .flags = LPSS_CLK | LPSS_SAVE_CTX, + .flags = LPSS_CLK | LPSS_SAVE_CTX | LPSS_DEV_PROXY, .prv_offset = 0x800, .setup = byt_i2c_setup, }; @@ -368,6 +374,8 @@ static int acpi_lpss_create_device(struct acpi_device *adev, adev->driver_data = pdata; pdev = acpi_create_platform_device(adev); if (!IS_ERR_OR_NULL(pdev)) { + if (!proxy_device && dev_desc->flags & LPSS_DEV_PROXY) + proxy_device = &pdev->dev; return 1; } @@ -499,14 +507,15 @@ static void acpi_lpss_set_ltr(struct device *dev, s32 val) /** * acpi_lpss_save_ctx() - Save the private registers of LPSS device * @dev: LPSS device + * @pdata: pointer to the private data of the LPSS device * * Most LPSS devices have private registers which may loose their context when * the device is powered down. acpi_lpss_save_ctx() saves those registers into * prv_reg_ctx array. */ -static void acpi_lpss_save_ctx(struct device *dev) +static void acpi_lpss_save_ctx(struct device *dev, + struct lpss_private_data *pdata) { - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); unsigned int i; for (i = 0; i < LPSS_PRV_REG_COUNT; i++) { @@ -521,12 +530,13 @@ static void acpi_lpss_save_ctx(struct device *dev) /** * acpi_lpss_restore_ctx() - Restore the private registers of LPSS device * @dev: LPSS device + * @pdata: pointer to the private data of the LPSS device * * Restores the registers that were previously stored with acpi_lpss_save_ctx(). */ -static void acpi_lpss_restore_ctx(struct device *dev) +static void acpi_lpss_restore_ctx(struct device *dev, + struct lpss_private_data *pdata) { - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); unsigned int i; /* @@ -549,23 +559,31 @@ static void acpi_lpss_restore_ctx(struct device *dev) #ifdef CONFIG_PM_SLEEP static int acpi_lpss_suspend_late(struct device *dev) { - int ret = pm_generic_suspend_late(dev); + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + ret = pm_generic_suspend_late(dev); if (ret) return ret; - acpi_lpss_save_ctx(dev); + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) + acpi_lpss_save_ctx(dev, pdata); + return acpi_dev_suspend_late(dev); } static int acpi_lpss_resume_early(struct device *dev) { - int ret = acpi_dev_resume_early(dev); + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + ret = acpi_dev_resume_early(dev); if (ret) return ret; - acpi_lpss_restore_ctx(dev); + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) + acpi_lpss_restore_ctx(dev, pdata); + return pm_generic_resume_early(dev); } #endif /* CONFIG_PM_SLEEP */ @@ -573,23 +591,44 @@ static int acpi_lpss_resume_early(struct device *dev) #ifdef CONFIG_PM_RUNTIME static int acpi_lpss_runtime_suspend(struct device *dev) { - int ret = pm_generic_runtime_suspend(dev); + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + ret = pm_generic_runtime_suspend(dev); if (ret) return ret; - acpi_lpss_save_ctx(dev); - return acpi_dev_runtime_suspend(dev); + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) + acpi_lpss_save_ctx(dev, pdata); + + ret = acpi_dev_runtime_suspend(dev); + if (ret) + return ret; + + if (pdata->dev_desc->flags & LPSS_PROXY_REQ && proxy_device) + return pm_runtime_put_sync_suspend(proxy_device); + + return 0; } static int acpi_lpss_runtime_resume(struct device *dev) { - int ret = acpi_dev_runtime_resume(dev); + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + + if (pdata->dev_desc->flags & LPSS_PROXY_REQ && proxy_device) { + ret = pm_runtime_get_sync(proxy_device); + if (ret) + return ret; + } + ret = acpi_dev_runtime_resume(dev); if (ret) return ret; - acpi_lpss_restore_ctx(dev); + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) + acpi_lpss_restore_ctx(dev, pdata); + return pm_generic_runtime_resume(dev); } #endif /* CONFIG_PM_RUNTIME */ @@ -631,30 +670,27 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, return 0; pdata = acpi_driver_data(adev); - if (!pdata || !pdata->mmio_base) + if (!pdata) return 0; - if (pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) { + if (pdata->mmio_base && + pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) { dev_err(&pdev->dev, "MMIO size insufficient to access LTR\n"); return 0; } switch (action) { - case BUS_NOTIFY_BOUND_DRIVER: - if (pdata->dev_desc->flags & LPSS_SAVE_CTX) - pdev->dev.pm_domain = &acpi_lpss_pm_domain; - break; - case BUS_NOTIFY_UNBOUND_DRIVER: - if (pdata->dev_desc->flags & LPSS_SAVE_CTX) - pdev->dev.pm_domain = NULL; - break; case BUS_NOTIFY_ADD_DEVICE: + pdev->dev.pm_domain = &acpi_lpss_pm_domain; if (pdata->dev_desc->flags & LPSS_LTR) return sysfs_create_group(&pdev->dev.kobj, &lpss_attr_group); + break; case BUS_NOTIFY_DEL_DEVICE: if (pdata->dev_desc->flags & LPSS_LTR) sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group); + pdev->dev.pm_domain = NULL; + break; default: break; } diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 81db932b15ee..aa70154cf4fa 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -616,8 +616,11 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context) { struct acpi_gpe_event_info *gpe_event_info = context; + acpi_cpu_flags flags; + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); (void)acpi_ev_finish_gpe(gpe_event_info); + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); ACPI_FREE(gpe_event_info); return; diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 8ec8a89a20ab..d98ba4355819 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1180,6 +1180,10 @@ static int acpi_battery_add(struct acpi_device *device) if (!device) return -EINVAL; + + if (device->dep_unmet) + return -EPROBE_DEFER; + battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); if (!battery) return -ENOMEM; diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 447f6d679b29..163e82f536fa 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -173,4 +173,10 @@ static inline void suspend_nvs_restore(void) {} bool acpi_osi_is_win8(void); #endif +/*-------------------------------------------------------------------------- + Device properties + -------------------------------------------------------------------------- */ +void acpi_init_properties(struct acpi_device *adev); +void acpi_free_properties(struct acpi_device *adev); + #endif /* _ACPI_INTERNAL_H_ */ diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 9964f70be98d..f9eeae871593 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -436,7 +436,7 @@ static void acpi_os_drop_map_ref(struct acpi_ioremap *map) static void acpi_os_map_cleanup(struct acpi_ioremap *map) { if (!map->refcount) { - synchronize_rcu(); + synchronize_rcu_expedited(); acpi_unmap(map->phys, map->virt); kfree(map); } @@ -1188,6 +1188,12 @@ EXPORT_SYMBOL(acpi_os_execute); void acpi_os_wait_events_complete(void) { + /* + * Make sure the GPE handler or the fixed event handler is not used + * on another CPU after removal. + */ + if (acpi_irq_handler) + synchronize_hardirq(acpi_gbl_FADT.sci_interrupt); flush_workqueue(kacpid_wq); flush_workqueue(kacpi_notify_wq); } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 17f9ec501972..38472fd5d104 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -334,10 +334,10 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr) static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) { - acpi_status status = 0; + acpi_status status; u64 count; int current_count; - int i; + int i, ret = 0; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *cst; @@ -358,7 +358,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) /* There must be at least 2 elements */ if (!cst || (cst->type != ACPI_TYPE_PACKAGE) || cst->package.count < 2) { printk(KERN_ERR PREFIX "not enough elements in _CST\n"); - status = -EFAULT; + ret = -EFAULT; goto end; } @@ -367,7 +367,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) /* Validate number of power states. */ if (count < 1 || count != cst->package.count - 1) { printk(KERN_ERR PREFIX "count given by _CST is not valid\n"); - status = -EFAULT; + ret = -EFAULT; goto end; } @@ -489,12 +489,12 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) /* Validate number of power states discovered */ if (current_count < 2) - status = -EFAULT; + ret = -EFAULT; end: kfree(buffer.pointer); - return status; + return ret; } static void acpi_processor_power_verify_c3(struct acpi_processor *pr, @@ -1111,7 +1111,7 @@ static int acpi_processor_registered; int acpi_processor_power_init(struct acpi_processor *pr) { - acpi_status status = 0; + acpi_status status; int retval; struct cpuidle_device *dev; static int first_run; diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c new file mode 100644 index 000000000000..0d083736e25b --- /dev/null +++ b/drivers/acpi/property.c @@ -0,0 +1,551 @@ +/* + * ACPI device specific properties support. + * + * Copyright (C) 2014, Intel Corporation + * All rights reserved. + * + * Authors: Mika Westerberg <mika.westerberg@linux.intel.com> + * Darren Hart <dvhart@linux.intel.com> + * 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. + */ + +#include <linux/acpi.h> +#include <linux/device.h> +#include <linux/export.h> + +#include "internal.h" + +/* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */ +static const u8 prp_uuid[16] = { + 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d, + 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 +}; + +static bool acpi_property_value_ok(const union acpi_object *value) +{ + int j; + + /* + * The value must be an integer, a string, a reference, or a package + * whose every element must be an integer, a string, or a reference. + */ + switch (value->type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_LOCAL_REFERENCE: + return true; + + case ACPI_TYPE_PACKAGE: + for (j = 0; j < value->package.count; j++) + switch (value->package.elements[j].type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_LOCAL_REFERENCE: + continue; + + default: + return false; + } + + return true; + } + return false; +} + +static bool acpi_properties_format_valid(const union acpi_object *properties) +{ + int i; + + for (i = 0; i < properties->package.count; i++) { + const union acpi_object *property; + + property = &properties->package.elements[i]; + /* + * Only two elements allowed, the first one must be a string and + * the second one has to satisfy certain conditions. + */ + if (property->package.count != 2 + || property->package.elements[0].type != ACPI_TYPE_STRING + || !acpi_property_value_ok(&property->package.elements[1])) + return false; + } + return true; +} + +static void acpi_init_of_compatible(struct acpi_device *adev) +{ + const union acpi_object *of_compatible; + struct acpi_hardware_id *hwid; + bool acpi_of = false; + int ret; + + /* + * Check if the special PRP0001 ACPI ID is present and in that + * case we fill in Device Tree compatible properties for this + * device. + */ + list_for_each_entry(hwid, &adev->pnp.ids, list) { + if (!strcmp(hwid->id, "PRP0001")) { + acpi_of = true; + break; + } + } + + if (!acpi_of) + return; + + ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING, + &of_compatible); + if (ret) { + ret = acpi_dev_get_property(adev, "compatible", + ACPI_TYPE_STRING, &of_compatible); + if (ret) { + acpi_handle_warn(adev->handle, + "PRP0001 requires compatible property\n"); + return; + } + } + adev->data.of_compatible = of_compatible; +} + +void acpi_init_properties(struct acpi_device *adev) +{ + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; + const union acpi_object *desc; + acpi_status status; + int i; + + status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf, + ACPI_TYPE_PACKAGE); + if (ACPI_FAILURE(status)) + return; + + desc = buf.pointer; + if (desc->package.count % 2) + goto fail; + + /* Look for the device properties UUID. */ + for (i = 0; i < desc->package.count; i += 2) { + const union acpi_object *uuid, *properties; + + uuid = &desc->package.elements[i]; + properties = &desc->package.elements[i + 1]; + + /* + * The first element must be a UUID and the second one must be + * a package. + */ + if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16 + || properties->type != ACPI_TYPE_PACKAGE) + break; + + if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid))) + continue; + + /* + * We found the matching UUID. Now validate the format of the + * package immediately following it. + */ + if (!acpi_properties_format_valid(properties)) + break; + + adev->data.pointer = buf.pointer; + adev->data.properties = properties; + + acpi_init_of_compatible(adev); + return; + } + + fail: + dev_warn(&adev->dev, "Returned _DSD data is not valid, skipping\n"); + ACPI_FREE(buf.pointer); +} + +void acpi_free_properties(struct acpi_device *adev) +{ + ACPI_FREE((void *)adev->data.pointer); + adev->data.of_compatible = NULL; + adev->data.pointer = NULL; + adev->data.properties = NULL; +} + +/** + * acpi_dev_get_property - return an ACPI property with given name + * @adev: ACPI device to get property + * @name: Name of the property + * @type: Expected property type + * @obj: Location to store the property value (if not %NULL) + * + * Look up a property with @name and store a pointer to the resulting ACPI + * object at the location pointed to by @obj if found. + * + * Callers must not attempt to free the returned objects. These objects will be + * freed by the ACPI core automatically during the removal of @adev. + * + * Return: %0 if property with @name has been found (success), + * %-EINVAL if the arguments are invalid, + * %-ENODATA if the property doesn't exist, + * %-EPROTO if the property value type doesn't match @type. + */ +int acpi_dev_get_property(struct acpi_device *adev, const char *name, + acpi_object_type type, const union acpi_object **obj) +{ + const union acpi_object *properties; + int i; + + if (!adev || !name) + return -EINVAL; + + if (!adev->data.pointer || !adev->data.properties) + return -ENODATA; + + properties = adev->data.properties; + for (i = 0; i < properties->package.count; i++) { + const union acpi_object *propname, *propvalue; + const union acpi_object *property; + + property = &properties->package.elements[i]; + + propname = &property->package.elements[0]; + propvalue = &property->package.elements[1]; + + if (!strcmp(name, propname->string.pointer)) { + if (type != ACPI_TYPE_ANY && propvalue->type != type) + return -EPROTO; + else if (obj) + *obj = propvalue; + + return 0; + } + } + return -ENODATA; +} +EXPORT_SYMBOL_GPL(acpi_dev_get_property); + +/** + * acpi_dev_get_property_array - return an ACPI array property with given name + * @adev: ACPI device to get property + * @name: Name of the property + * @type: Expected type of array elements + * @obj: Location to store a pointer to the property value (if not NULL) + * + * Look up an array property with @name and store a pointer to the resulting + * ACPI object at the location pointed to by @obj if found. + * + * Callers must not attempt to free the returned objects. Those objects will be + * freed by the ACPI core automatically during the removal of @adev. + * + * Return: %0 if array property (package) with @name has been found (success), + * %-EINVAL if the arguments are invalid, + * %-ENODATA if the property doesn't exist, + * %-EPROTO if the property is not a package or the type of its elements + * doesn't match @type. + */ +int acpi_dev_get_property_array(struct acpi_device *adev, const char *name, + acpi_object_type type, + const union acpi_object **obj) +{ + const union acpi_object *prop; + int ret, i; + + ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop); + if (ret) + return ret; + + if (type != ACPI_TYPE_ANY) { + /* Check that all elements are of correct type. */ + for (i = 0; i < prop->package.count; i++) + if (prop->package.elements[i].type != type) + return -EPROTO; + } + if (obj) + *obj = prop; + + return 0; +} +EXPORT_SYMBOL_GPL(acpi_dev_get_property_array); + +/** + * acpi_dev_get_property_reference - returns handle to the referenced object + * @adev: ACPI device to get property + * @name: Name of the property + * @index: Index of the reference to return + * @args: Location to store the returned reference with optional arguments + * + * Find property with @name, verifify that it is a package containing at least + * one object reference and if so, store the ACPI device object pointer to the + * target object in @args->adev. If the reference includes arguments, store + * them in the @args->args[] array. + * + * If there's more than one reference in the property value package, @index is + * used to select the one to return. + * + * Return: %0 on success, negative error code on failure. + */ +int acpi_dev_get_property_reference(struct acpi_device *adev, + const char *name, size_t index, + struct acpi_reference_args *args) +{ + const union acpi_object *element, *end; + const union acpi_object *obj; + struct acpi_device *device; + int ret, idx = 0; + + ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj); + if (ret) + return ret; + + /* + * The simplest case is when the value is a single reference. Just + * return that reference then. + */ + if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) { + if (index) + return -EINVAL; + + ret = acpi_bus_get_device(obj->reference.handle, &device); + if (ret) + return ret; + + args->adev = device; + args->nargs = 0; + return 0; + } + + /* + * If it is not a single reference, then it is a package of + * references followed by number of ints as follows: + * + * Package () { REF, INT, REF, INT, INT } + * + * The index argument is then used to determine which reference + * the caller wants (along with the arguments). + */ + if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count) + return -EPROTO; + + element = obj->package.elements; + end = element + obj->package.count; + + while (element < end) { + u32 nargs, i; + + if (element->type != ACPI_TYPE_LOCAL_REFERENCE) + return -EPROTO; + + ret = acpi_bus_get_device(element->reference.handle, &device); + if (ret) + return -ENODEV; + + element++; + nargs = 0; + + /* assume following integer elements are all args */ + for (i = 0; element + i < end; i++) { + int type = element[i].type; + + if (type == ACPI_TYPE_INTEGER) + nargs++; + else if (type == ACPI_TYPE_LOCAL_REFERENCE) + break; + else + return -EPROTO; + } + + if (idx++ == index) { + args->adev = device; + args->nargs = nargs; + for (i = 0; i < nargs; i++) + args->args[i] = element[i].integer.value; + + return 0; + } + + element += nargs; + } + + return -EPROTO; +} +EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference); + +int acpi_dev_prop_get(struct acpi_device *adev, const char *propname, + void **valptr) +{ + return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY, + (const union acpi_object **)valptr); +} + +int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, + enum dev_prop_type proptype, void *val) +{ + const union acpi_object *obj; + int ret; + + if (!val) + return -EINVAL; + + if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) { + ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj); + if (ret) + return ret; + + switch (proptype) { + case DEV_PROP_U8: + if (obj->integer.value > U8_MAX) + return -EOVERFLOW; + *(u8 *)val = obj->integer.value; + break; + case DEV_PROP_U16: + if (obj->integer.value > U16_MAX) + return -EOVERFLOW; + *(u16 *)val = obj->integer.value; + break; + case DEV_PROP_U32: + if (obj->integer.value > U32_MAX) + return -EOVERFLOW; + *(u32 *)val = obj->integer.value; + break; + default: + *(u64 *)val = obj->integer.value; + break; + } + } else if (proptype == DEV_PROP_STRING) { + ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj); + if (ret) + return ret; + + *(char **)val = obj->string.pointer; + } else { + ret = -EINVAL; + } + return ret; +} + +static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val, + size_t nval) +{ + int i; + + for (i = 0; i < nval; i++) { + if (items[i].type != ACPI_TYPE_INTEGER) + return -EPROTO; + if (items[i].integer.value > U8_MAX) + return -EOVERFLOW; + + val[i] = items[i].integer.value; + } + return 0; +} + +static int acpi_copy_property_array_u16(const union acpi_object *items, + u16 *val, size_t nval) +{ + int i; + + for (i = 0; i < nval; i++) { + if (items[i].type != ACPI_TYPE_INTEGER) + return -EPROTO; + if (items[i].integer.value > U16_MAX) + return -EOVERFLOW; + + val[i] = items[i].integer.value; + } + return 0; +} + +static int acpi_copy_property_array_u32(const union acpi_object *items, + u32 *val, size_t nval) +{ + int i; + + for (i = 0; i < nval; i++) { + if (items[i].type != ACPI_TYPE_INTEGER) + return -EPROTO; + if (items[i].integer.value > U32_MAX) + return -EOVERFLOW; + + val[i] = items[i].integer.value; + } + return 0; +} + +static int acpi_copy_property_array_u64(const union acpi_object *items, + u64 *val, size_t nval) +{ + int i; + + for (i = 0; i < nval; i++) { + if (items[i].type != ACPI_TYPE_INTEGER) + return -EPROTO; + + val[i] = items[i].integer.value; + } + return 0; +} + +static int acpi_copy_property_array_string(const union acpi_object *items, + char **val, size_t nval) +{ + int i; + + for (i = 0; i < nval; i++) { + if (items[i].type != ACPI_TYPE_STRING) + return -EPROTO; + + val[i] = items[i].string.pointer; + } + return 0; +} + +int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, + enum dev_prop_type proptype, void *val, size_t nval) +{ + const union acpi_object *obj; + const union acpi_object *items; + int ret; + + if (val && nval == 1) { + ret = acpi_dev_prop_read_single(adev, propname, proptype, val); + if (!ret) + return ret; + } + + ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj); + if (ret) + return ret; + + if (!val) + return obj->package.count; + else if (nval <= 0) + return -EINVAL; + + if (nval > obj->package.count) + return -EOVERFLOW; + + items = obj->package.elements; + switch (proptype) { + case DEV_PROP_U8: + ret = acpi_copy_property_array_u8(items, (u8 *)val, nval); + break; + case DEV_PROP_U16: + ret = acpi_copy_property_array_u16(items, (u16 *)val, nval); + break; + case DEV_PROP_U32: + ret = acpi_copy_property_array_u32(items, (u32 *)val, nval); + break; + case DEV_PROP_U64: + ret = acpi_copy_property_array_u64(items, (u64 *)val, nval); + break; + case DEV_PROP_STRING: + ret = acpi_copy_property_array_string(items, (char **)val, nval); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 0476e90b2091..1b1cf558d3d3 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -36,6 +36,8 @@ bool acpi_force_hot_remove; static const char *dummy_hid = "device"; +static LIST_HEAD(acpi_dep_list); +static DEFINE_MUTEX(acpi_dep_list_lock); static LIST_HEAD(acpi_bus_id_list); static DEFINE_MUTEX(acpi_scan_lock); static LIST_HEAD(acpi_scan_handlers_list); @@ -43,6 +45,12 @@ DEFINE_MUTEX(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); static DEFINE_MUTEX(acpi_hp_context_lock); +struct acpi_dep_data { + struct list_head node; + acpi_handle master; + acpi_handle slave; +}; + struct acpi_device_bus_id{ char bus_id[15]; unsigned int instance_no; @@ -124,17 +132,56 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, if (list_empty(&acpi_dev->pnp.ids)) return 0; - len = snprintf(modalias, size, "acpi:"); - size -= len; - - 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 the device has PRP0001 we expose DT compatible modalias + * instead in form of of:NnameTCcompatible. + */ + 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; + + 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; + } } modalias[len] = '\0'; @@ -902,6 +949,51 @@ int acpi_match_device_ids(struct acpi_device *device, } 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_match_device(drv->acpi_match_table, dev); +} +EXPORT_SYMBOL_GPL(acpi_driver_match_device); + static void acpi_free_power_resources_lists(struct acpi_device *device) { int i; @@ -922,6 +1014,7 @@ static void acpi_device_release(struct device *dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); + acpi_free_properties(acpi_dev); acpi_free_pnp_ids(&acpi_dev->pnp); acpi_free_power_resources_lists(acpi_dev); kfree(acpi_dev); @@ -1304,6 +1397,26 @@ int acpi_device_add(struct acpi_device *device, return result; } +struct acpi_device *acpi_get_next_child(struct device *dev, + struct acpi_device *child) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + struct list_head *head, *next; + + if (!adev) + return NULL; + + head = &adev->children; + if (list_empty(head)) + return NULL; + + if (!child) + return list_first_entry(head, struct acpi_device, node); + + next = child->node.next; + return next == head ? NULL : list_entry(next, struct acpi_device, node); +} + /* -------------------------------------------------------------------------- Driver Management -------------------------------------------------------------------------- */ @@ -1923,9 +2036,11 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, device->device_type = type; device->handle = handle; device->parent = acpi_bus_get_parent(handle); + device->fwnode.type = FWNODE_ACPI; acpi_set_device_status(device, sta); acpi_device_get_busid(device); acpi_set_pnp_ids(handle, &device->pnp, type); + acpi_init_properties(device); acpi_bus_get_flags(device); device->flags.match_driver = false; device->flags.initialized = true; @@ -2086,6 +2201,59 @@ static void acpi_scan_init_hotplug(struct acpi_device *adev) } } +static void acpi_device_dep_initialize(struct acpi_device *adev) +{ + struct acpi_dep_data *dep; + struct acpi_handle_list dep_devices; + acpi_status status; + int i; + + if (!acpi_has_method(adev->handle, "_DEP")) + return; + + status = acpi_evaluate_reference(adev->handle, "_DEP", NULL, + &dep_devices); + if (ACPI_FAILURE(status)) { + dev_err(&adev->dev, "Failed to evaluate _DEP.\n"); + return; + } + + for (i = 0; i < dep_devices.count; i++) { + struct acpi_device_info *info; + int skip; + + status = acpi_get_object_info(dep_devices.handles[i], &info); + if (ACPI_FAILURE(status)) { + dev_err(&adev->dev, "Error reading device info\n"); + continue; + } + + /* + * Skip the dependency of Windows System Power + * Management Controller + */ + skip = info->valid & ACPI_VALID_HID && + !strcmp(info->hardware_id.string, "INT3396"); + + kfree(info); + + if (skip) + continue; + + dep = kzalloc(sizeof(struct acpi_dep_data), GFP_KERNEL); + if (!dep) + return; + + dep->master = dep_devices.handles[i]; + dep->slave = adev->handle; + adev->dep_unmet++; + + mutex_lock(&acpi_dep_list_lock); + list_add_tail(&dep->node , &acpi_dep_list); + mutex_unlock(&acpi_dep_list_lock); + } +} + static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, void *not_used, void **return_value) { @@ -2112,6 +2280,7 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, return AE_CTRL_DEPTH; acpi_scan_init_hotplug(device); + acpi_device_dep_initialize(device); out: if (!*return_value) @@ -2232,6 +2401,29 @@ static void acpi_bus_attach(struct acpi_device *device) device->handler->hotplug.notify_online(device); } +void acpi_walk_dep_device_list(acpi_handle handle) +{ + struct acpi_dep_data *dep, *tmp; + struct acpi_device *adev; + + mutex_lock(&acpi_dep_list_lock); + list_for_each_entry_safe(dep, tmp, &acpi_dep_list, node) { + if (dep->master == handle) { + acpi_bus_get_device(dep->slave, &adev); + if (!adev) + continue; + + adev->dep_unmet--; + if (!adev->dep_unmet) + acpi_bus_attach(adev); + list_del(&dep->node); + kfree(dep); + } + } + mutex_unlock(&acpi_dep_list_lock); +} +EXPORT_SYMBOL_GPL(acpi_walk_dep_device_list); + /** * acpi_bus_scan - Add ACPI device node objects in a given namespace scope. * @handle: Root of the namespace scope to scan. diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 6d5a6cda0734..93b81523a2fe 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -190,30 +190,24 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) } } - int __init -acpi_table_parse_entries(char *id, - unsigned long table_size, - int entry_id, - acpi_tbl_entry_handler handler, - unsigned int max_entries) +acpi_parse_entries(char *id, unsigned long table_size, + acpi_tbl_entry_handler handler, + struct acpi_table_header *table_header, + int entry_id, unsigned int max_entries) { - struct acpi_table_header *table_header = NULL; struct acpi_subtable_header *entry; - unsigned int count = 0; + int count = 0; unsigned long table_end; - acpi_size tbl_size; if (acpi_disabled) return -ENODEV; - if (!handler) + if (!id || !handler) return -EINVAL; - if (strncmp(id, ACPI_SIG_MADT, 4) == 0) - acpi_get_table_with_size(id, acpi_apic_instance, &table_header, &tbl_size); - else - acpi_get_table_with_size(id, 0, &table_header, &tbl_size); + if (!table_size) + return -EINVAL; if (!table_header) { pr_warn("%4.4s not present\n", id); @@ -230,9 +224,12 @@ acpi_table_parse_entries(char *id, while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < table_end) { if (entry->type == entry_id - && (!max_entries || count++ < max_entries)) + && (!max_entries || count < max_entries)) { if (handler(entry, table_end)) - goto err; + return -EINVAL; + + count++; + } /* * If entry->length is 0, break from this loop to avoid @@ -240,22 +237,53 @@ acpi_table_parse_entries(char *id, */ if (entry->length == 0) { pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, entry_id); - goto err; + return -EINVAL; } entry = (struct acpi_subtable_header *) ((unsigned long)entry + entry->length); } + if (max_entries && count > max_entries) { pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n", id, entry_id, count - max_entries, count); } - early_acpi_os_unmap_memory((char *)table_header, tbl_size); return count; -err: +} + +int __init +acpi_table_parse_entries(char *id, + unsigned long table_size, + int entry_id, + acpi_tbl_entry_handler handler, + unsigned int max_entries) +{ + struct acpi_table_header *table_header = NULL; + acpi_size tbl_size; + int count; + u32 instance = 0; + + if (acpi_disabled) + return -ENODEV; + + if (!id || !handler) + return -EINVAL; + + if (!strncmp(id, ACPI_SIG_MADT, 4)) + instance = acpi_apic_instance; + + acpi_get_table_with_size(id, instance, &table_header, &tbl_size); + if (!table_header) { + pr_warn("%4.4s not present\n", id); + return -ENODEV; + } + + count = acpi_parse_entries(id, table_size, handler, table_header, + entry_id, max_entries); + early_acpi_os_unmap_memory((char *)table_header, tbl_size); - return -EINVAL; + return count; } int __init diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 371ac12d25b1..dd8ff63ee2b4 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -136,8 +136,7 @@ acpi_extract_package(union acpi_object *package, break; case 'B': size_required += - sizeof(u8 *) + - (element->buffer.length * sizeof(u8)); + sizeof(u8 *) + element->buffer.length; tail_offset += sizeof(u8 *); break; default: @@ -255,7 +254,7 @@ acpi_extract_package(union acpi_object *package, memcpy(tail, element->buffer.pointer, element->buffer.length); head += sizeof(u8 *); - tail += element->buffer.length * sizeof(u8); + tail += element->buffer.length; break; default: /* Should never get here */ diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 807a88a0f394..9d75ead2a1f9 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1164,7 +1164,8 @@ static bool acpi_video_device_in_dod(struct acpi_video_device *device) return true; for (i = 0; i < video->attached_count; i++) { - if (video->attached_array[i].bind_info == device) + if ((video->attached_array[i].value.int_val & 0xfff) == + (device->device_id & 0xfff)) return true; } diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index e45f83789809..49f1e6890587 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -321,6 +321,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */ { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */ + { PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */ { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */ { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H RAID */ { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ @@ -492,6 +495,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 */ { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, + { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi }, /* Enmotus */ { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 07bc7e4dbd04..65071591b143 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -1488,7 +1488,7 @@ static int sata_fsl_probe(struct platform_device *ofdev) host_priv->csr_base = csr_base; irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); - if (irq < 0) { + if (!irq) { dev_err(&ofdev->dev, "invalid irq from platform\n"); goto error_exit_with_cleanup; } diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 7652e8dc188f..21b0bc6a9c96 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -1225,11 +1225,13 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) card->config_regs = pci_iomap(dev, 0, CONFIG_RAM_SIZE); if (!card->config_regs) { dev_warn(&dev->dev, "Failed to ioremap config registers\n"); + err = -ENOMEM; goto out_release_regions; } card->buffers = pci_iomap(dev, 1, DATA_RAM_SIZE); if (!card->buffers) { dev_warn(&dev->dev, "Failed to ioremap data buffers\n"); + err = -ENOMEM; goto out_unmap_config; } diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 6922cd6850a2..53c3fe1aeb29 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -4,7 +4,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \ driver.o class.o platform.o \ cpu.o firmware.o init.o map.o devres.o \ attribute_container.o transport_class.o \ - topology.o container.o + topology.o container.o property.o obj-$(CONFIG_DEVTMPFS) += devtmpfs.o obj-$(CONFIG_DMA_CMA) += dma-contiguous.o obj-y += power/ diff --git a/drivers/base/property.c b/drivers/base/property.c new file mode 100644 index 000000000000..c45845874d4f --- /dev/null +++ b/drivers/base/property.c @@ -0,0 +1,431 @@ +/* + * property.c - Unified device property interface. + * + * Copyright (C) 2014, Intel Corporation + * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + * Mika Westerberg <mika.westerberg@linux.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. + */ + +#include <linux/property.h> +#include <linux/export.h> +#include <linux/acpi.h> +#include <linux/of.h> + +/** + * device_property_present - check if a property of a device is present + * @dev: Device whose property is being checked + * @propname: Name of the property + * + * Check if property @propname is present in the device firmware description. + */ +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); +} +EXPORT_SYMBOL_GPL(device_property_present); + +/** + * fwnode_property_present - check if a property of a firmware node is present + * @fwnode: Firmware node whose property to check + * @propname: Name of the property + */ +bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname) +{ + if (is_of_node(fwnode)) + return of_property_read_bool(of_node(fwnode), propname); + else if (is_acpi_node(fwnode)) + return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL); + + return false; +} +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 + * @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), + * %-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, + * %-EOVERFLOW if the size of the property is not as expected. + */ +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); +} +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 + * @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), + * %-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, + * %-EOVERFLOW if the size of the property is not as expected. + */ +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); +} +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 + * @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), + * %-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, + * %-EOVERFLOW if the size of the property is not as expected. + */ +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); +} +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 + * @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), + * %-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, + * %-EOVERFLOW if the size of the property is not as expected. + */ +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); +} +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 + * @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), + * %-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, + * %-EOVERFLOW if the size of the property is not as expected. + */ +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); +} +EXPORT_SYMBOL_GPL(device_property_read_string_array); + +/** + * device_property_read_string - return a string property of a device + * @dev: Device to get the property of + * @propname: Name of the property + * @val: The value is stored here + * + * Function reads property @propname from the device firmware description and + * stores the value into @val if found. The value is checked to be a string. + * + * Return: %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 type is not a string. + */ +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); +} +EXPORT_SYMBOL_GPL(device_property_read_string); + +#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \ +({ \ + int _ret_; \ + if (is_of_node(_fwnode_)) \ + _ret_ = OF_DEV_PROP_READ_ARRAY(of_node(_fwnode_), _propname_, \ + _type_, _val_, _nval_); \ + else if (is_acpi_node(_fwnode_)) \ + _ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \ + _proptype_, _val_, _nval_); \ + else \ + _ret_ = -ENXIO; \ + _ret_; \ +}) + +/** + * 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 + * @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), + * %-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, + * %-EOVERFLOW if the size of the property is not as expected, + * %-ENXIO if no suitable firmware interface is present. + */ +int fwnode_property_read_u8_array(struct fwnode_handle *fwnode, + const char *propname, u8 *val, size_t nval) +{ + return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8, + val, nval); +} +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 + * @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), + * %-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, + * %-EOVERFLOW if the size of the property is not as expected, + * %-ENXIO if no suitable firmware interface is present. + */ +int fwnode_property_read_u16_array(struct fwnode_handle *fwnode, + const char *propname, u16 *val, size_t nval) +{ + return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16, + val, nval); +} +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 + * @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), + * %-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, + * %-EOVERFLOW if the size of the property is not as expected, + * %-ENXIO if no suitable firmware interface is present. + */ +int fwnode_property_read_u32_array(struct fwnode_handle *fwnode, + const char *propname, u32 *val, size_t nval) +{ + return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32, + val, nval); +} +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 + * @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), + * %-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, + * %-EOVERFLOW if the size of the property is not as expected, + * %-ENXIO if no suitable firmware interface is present. + */ +int fwnode_property_read_u64_array(struct fwnode_handle *fwnode, + const char *propname, u64 *val, size_t nval) +{ + return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64, + val, nval); +} +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 + * @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), + * %-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, + * %-EOVERFLOW if the size of the property is not as expected, + * %-ENXIO if no suitable firmware interface is present. + */ +int fwnode_property_read_string_array(struct fwnode_handle *fwnode, + const char *propname, const char **val, + size_t nval) +{ + if (is_of_node(fwnode)) + return of_property_read_string_array(of_node(fwnode), propname, + val, nval); + else if (is_acpi_node(fwnode)) + return acpi_dev_prop_read(acpi_node(fwnode), propname, + DEV_PROP_STRING, val, nval); + + return -ENXIO; +} +EXPORT_SYMBOL_GPL(fwnode_property_read_string_array); + +/** + * fwnode_property_read_string - return a string property of a firmware node + * @fwnode: Firmware node to get the property of + * @propname: Name of the property + * @val: The value is stored here + * + * Read property @propname from the given firmware node and store the value into + * @val if found. The value is checked to be a string. + * + * Return: %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 a string, + * %-ENXIO if no suitable firmware interface is present. + */ +int fwnode_property_read_string(struct fwnode_handle *fwnode, + const char *propname, const char **val) +{ + if (is_of_node(fwnode)) + return of_property_read_string(of_node(fwnode),propname, val); + else if (is_acpi_node(fwnode)) + return acpi_dev_prop_read(acpi_node(fwnode), propname, + DEV_PROP_STRING, val, 1); + + return -ENXIO; +} +EXPORT_SYMBOL_GPL(fwnode_property_read_string); + +/** + * device_get_next_child_node - Return the next child node handle for a device + * @dev: Device to find the next child node for. + * @child: Handle to one of the device's child nodes or a null handle. + */ +struct fwnode_handle *device_get_next_child_node(struct device *dev, + struct fwnode_handle *child) +{ + if (IS_ENABLED(CONFIG_OF) && dev->of_node) { + struct device_node *node; + + node = of_get_next_available_child(dev->of_node, of_node(child)); + if (node) + return &node->fwnode; + } else if (IS_ENABLED(CONFIG_ACPI)) { + struct acpi_device *node; + + node = acpi_get_next_child(dev, acpi_node(child)); + if (node) + return acpi_fwnode_handle(node); + } + return NULL; +} +EXPORT_SYMBOL_GPL(device_get_next_child_node); + +/** + * fwnode_handle_put - Drop reference to a device node + * @fwnode: Pointer to the device node to drop the reference to. + * + * This has to be used when terminating device_for_each_child_node() iteration + * with break or return to prevent stale device node references from being left + * behind. + */ +void fwnode_handle_put(struct fwnode_handle *fwnode) +{ + if (is_of_node(fwnode)) + of_node_put(of_node(fwnode)); +} +EXPORT_SYMBOL_GPL(fwnode_handle_put); + +/** + * device_get_child_node_count - return the number of child nodes for device + * @dev: Device to cound the child nodes for + */ +unsigned int device_get_child_node_count(struct device *dev) +{ + struct fwnode_handle *child; + unsigned int count = 0; + + device_for_each_child_node(dev, child) + count++; + + return count; +} +EXPORT_SYMBOL_GPL(device_get_child_node_count); diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c index 24b5b020753a..a23ac0c724f0 100644 --- a/drivers/clk/at91/clk-usb.c +++ b/drivers/clk/at91/clk-usb.c @@ -52,29 +52,26 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, tmp = pmc_read(pmc, AT91_PMC_USB); usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; - return parent_rate / (usbdiv + 1); + + return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1)); } static long at91sam9x5_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { unsigned long div; - unsigned long bestrate; - unsigned long tmp; + + if (!rate) + return -EINVAL; if (rate >= *parent_rate) return *parent_rate; - div = *parent_rate / rate; - if (div >= SAM9X5_USB_MAX_DIV) - return *parent_rate / (SAM9X5_USB_MAX_DIV + 1); - - bestrate = *parent_rate / div; - tmp = *parent_rate / (div + 1); - if (bestrate - rate > rate - tmp) - bestrate = tmp; + div = DIV_ROUND_CLOSEST(*parent_rate, rate); + if (div > SAM9X5_USB_MAX_DIV + 1) + div = SAM9X5_USB_MAX_DIV + 1; - return bestrate; + return DIV_ROUND_CLOSEST(*parent_rate, div); } static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index) @@ -106,9 +103,13 @@ static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, u32 tmp; struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); struct at91_pmc *pmc = usb->pmc; - unsigned long div = parent_rate / rate; + unsigned long div; + + if (!rate) + return -EINVAL; - if (parent_rate % rate || div < 1 || div >= SAM9X5_USB_MAX_DIV) + div = DIV_ROUND_CLOSEST(parent_rate, rate); + if (div > SAM9X5_USB_MAX_DIV + 1 || !div) return -EINVAL; tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_OHCIUSBDIV; @@ -253,7 +254,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, tmp_parent_rate = rate * usb->divisors[i]; tmp_parent_rate = __clk_round_rate(parent, tmp_parent_rate); - tmprate = tmp_parent_rate / usb->divisors[i]; + tmprate = DIV_ROUND_CLOSEST(tmp_parent_rate, usb->divisors[i]); if (tmprate < rate) tmpdiff = rate - tmprate; else @@ -281,10 +282,10 @@ static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, struct at91_pmc *pmc = usb->pmc; unsigned long div; - if (!rate || parent_rate % rate) + if (!rate) return -EINVAL; - div = parent_rate / rate; + div = DIV_ROUND_CLOSEST(parent_rate, rate); for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) { if (usb->divisors[i] == div) { diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 18a9de29df0e..c0a842b335c5 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -263,6 +263,14 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, if (!rate) rate = 1; + /* if read only, just return current value */ + if (divider->flags & CLK_DIVIDER_READ_ONLY) { + bestdiv = readl(divider->reg) >> divider->shift; + bestdiv &= div_mask(divider); + bestdiv = _get_div(divider, bestdiv); + return bestdiv; + } + maxdiv = _get_maxdiv(divider); if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) { @@ -361,11 +369,6 @@ const struct clk_ops clk_divider_ops = { }; EXPORT_SYMBOL_GPL(clk_divider_ops); -const struct clk_ops clk_divider_ro_ops = { - .recalc_rate = clk_divider_recalc_rate, -}; -EXPORT_SYMBOL_GPL(clk_divider_ro_ops); - static struct clk *_register_divider(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, @@ -391,10 +394,7 @@ static struct clk *_register_divider(struct device *dev, const char *name, } init.name = name; - if (clk_divider_flags & CLK_DIVIDER_READ_ONLY) - init.ops = &clk_divider_ro_ops; - else - init.ops = &clk_divider_ops; + init.ops = &clk_divider_ops; init.flags = flags | CLK_IS_BASIC; init.parent_names = (parent_name ? &parent_name: NULL); init.num_parents = (parent_name ? 1 : 0); diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c index b345cc791e5d..88b9fe13fa44 100644 --- a/drivers/clk/pxa/clk-pxa27x.c +++ b/drivers/clk/pxa/clk-pxa27x.c @@ -322,7 +322,7 @@ static unsigned long clk_pxa27x_memory_get_rate(struct clk_hw *hw, unsigned long ccsr = CCSR; osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); - a = cccr & CCCR_A_BIT; + a = cccr & (1 << CCCR_A_BIT); l = ccsr & CCSR_L_MASK; if (osc_forced || a) @@ -341,7 +341,7 @@ static u8 clk_pxa27x_memory_get_parent(struct clk_hw *hw) unsigned long ccsr = CCSR; osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); - a = cccr & CCCR_A_BIT; + a = cccr & (1 << CCCR_A_BIT); if (osc_forced) return PXA_MEM_13Mhz; if (a) diff --git a/drivers/clk/qcom/mmcc-apq8084.c b/drivers/clk/qcom/mmcc-apq8084.c index dab988ab8cf1..157139a5c1ca 100644 --- a/drivers/clk/qcom/mmcc-apq8084.c +++ b/drivers/clk/qcom/mmcc-apq8084.c @@ -3122,7 +3122,7 @@ static struct clk_regmap *mmcc_apq8084_clocks[] = { [ESC1_CLK_SRC] = &esc1_clk_src.clkr, [HDMI_CLK_SRC] = &hdmi_clk_src.clkr, [VSYNC_CLK_SRC] = &vsync_clk_src.clkr, - [RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr, + [MMSS_RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr, [RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr, [MAPLE_CLK_SRC] = &maple_clk_src.clkr, [VDP_CLK_SRC] = &vdp_clk_src.clkr, diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 1e68bff481b8..880a266f0143 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -90,9 +90,7 @@ static struct clk *rockchip_clk_register_branch(const char *name, div->width = div_width; div->lock = lock; div->table = div_table; - div_ops = (div_flags & CLK_DIVIDER_READ_ONLY) - ? &clk_divider_ro_ops - : &clk_divider_ops; + div_ops = &clk_divider_ops; } clk = clk_register_composite(NULL, name, parent_names, num_parents, diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 244722170410..380478562b7d 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -22,6 +22,7 @@ #include <linux/mm.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/pm_runtime.h> #include "../dmaengine.h" #include "internal.h" @@ -1504,6 +1505,9 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) dw->regs = chip->regs; chip->dw = dw; + pm_runtime_enable(chip->dev); + pm_runtime_get_sync(chip->dev); + dw_params = dma_read_byaddr(chip->regs, DW_PARAMS); autocfg = dw_params >> DW_PARAMS_EN & 0x1; @@ -1667,11 +1671,14 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) dev_info(chip->dev, "DesignWare DMA Controller, %d channels\n", nr_channels); + pm_runtime_put_sync_suspend(chip->dev); + return 0; err_dma_register: free_irq(chip->irq, dw); err_pdata: + pm_runtime_put_sync_suspend(chip->dev); return err; } EXPORT_SYMBOL_GPL(dw_dma_probe); @@ -1681,6 +1688,8 @@ int dw_dma_remove(struct dw_dma_chip *chip) struct dw_dma *dw = chip->dw; struct dw_dma_chan *dwc, *_dwc; + pm_runtime_get_sync(chip->dev); + dw_dma_off(dw); dma_async_device_unregister(&dw->dma); @@ -1693,6 +1702,8 @@ int dw_dma_remove(struct dw_dma_chip *chip) channel_clear_bit(dw, CH_EN, dwc->mask); } + pm_runtime_put_sync_suspend(chip->dev); + pm_runtime_disable(chip->dev); return 0; } EXPORT_SYMBOL_GPL(dw_dma_remove); diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 954b9f6b0ef8..13dbd3dfc33a 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c @@ -109,6 +109,38 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev, EXPORT_SYMBOL(__devm_gpiod_get_index); /** + * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node + * @dev: GPIO consumer + * @child: firmware node (child of @dev) + * + * GPIO descriptors returned from this function are automatically disposed on + * driver detach. + */ +struct gpio_desc *devm_get_gpiod_from_child(struct device *dev, + struct fwnode_handle *child) +{ + struct gpio_desc **dr; + struct gpio_desc *desc; + + dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *), + GFP_KERNEL); + if (!dr) + return ERR_PTR(-ENOMEM); + + desc = fwnode_get_named_gpiod(child, "gpios"); + if (IS_ERR(desc)) { + devres_free(dr); + return desc; + } + + *dr = desc; + devres_add(dev, dr); + + return desc; +} +EXPORT_SYMBOL(devm_get_gpiod_from_child); + +/** * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional() * @dev: GPIO consumer * @con_id: function within the GPIO consumer diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 41e91d70301e..99720c8bc8ed 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c @@ -29,290 +29,221 @@ #include <linux/gpio.h> -static DEFINE_SPINLOCK(gpio_lock); - -#define CGEN (0x00) -#define CGIO (0x04) -#define CGLV (0x08) - -#define RGEN (0x20) -#define RGIO (0x24) -#define RGLV (0x28) - -static unsigned short gpio_ba; - -static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned gpio_num) -{ - u8 curr_dirs; - unsigned short offset, bit; - - spin_lock(&gpio_lock); - - offset = CGIO + gpio_num / 8; - bit = gpio_num % 8; - - curr_dirs = inb(gpio_ba + offset); - - if (!(curr_dirs & (1 << bit))) - outb(curr_dirs | (1 << bit), gpio_ba + offset); +#define GEN 0x00 +#define GIO 0x04 +#define GLV 0x08 + +struct sch_gpio { + struct gpio_chip chip; + spinlock_t lock; + unsigned short iobase; + unsigned short core_base; + unsigned short resume_base; +}; - spin_unlock(&gpio_lock); - return 0; -} +#define to_sch_gpio(c) container_of(c, struct sch_gpio, chip) -static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num) +static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio, + unsigned reg) { - int res; - unsigned short offset, bit; + unsigned base = 0; - offset = CGLV + gpio_num / 8; - bit = gpio_num % 8; + if (gpio >= sch->resume_base) { + gpio -= sch->resume_base; + base += 0x20; + } - res = !!(inb(gpio_ba + offset) & (1 << bit)); - return res; + return base + reg + gpio / 8; } -static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val) +static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio) { - u8 curr_vals; - unsigned short offset, bit; - - spin_lock(&gpio_lock); - - offset = CGLV + gpio_num / 8; - bit = gpio_num % 8; - - curr_vals = inb(gpio_ba + offset); - - if (val) - outb(curr_vals | (1 << bit), gpio_ba + offset); - else - outb((curr_vals & ~(1 << bit)), gpio_ba + offset); - spin_unlock(&gpio_lock); + if (gpio >= sch->resume_base) + gpio -= sch->resume_base; + return gpio % 8; } -static int sch_gpio_core_direction_out(struct gpio_chip *gc, - unsigned gpio_num, int val) +static void sch_gpio_enable(struct sch_gpio *sch, unsigned gpio) { - u8 curr_dirs; unsigned short offset, bit; + u8 enable; - spin_lock(&gpio_lock); + spin_lock(&sch->lock); - offset = CGIO + gpio_num / 8; - bit = gpio_num % 8; - - curr_dirs = inb(gpio_ba + offset); - if (curr_dirs & (1 << bit)) - outb(curr_dirs & ~(1 << bit), gpio_ba + offset); + offset = sch_gpio_offset(sch, gpio, GEN); + bit = sch_gpio_bit(sch, gpio); - spin_unlock(&gpio_lock); + enable = inb(sch->iobase + offset); + if (!(enable & (1 << bit))) + outb(enable | (1 << bit), sch->iobase + offset); - /* - * according to the datasheet, writing to the level register has no - * effect when GPIO is programmed as input. - * Actually the the level register is read-only when configured as input. - * Thus presetting the output level before switching to output is _NOT_ possible. - * Hence we set the level after configuring the GPIO as output. - * But we cannot prevent a short low pulse if direction is set to high - * and an external pull-up is connected. - */ - sch_gpio_core_set(gc, gpio_num, val); - return 0; + spin_unlock(&sch->lock); } -static struct gpio_chip sch_gpio_core = { - .label = "sch_gpio_core", - .owner = THIS_MODULE, - .direction_input = sch_gpio_core_direction_in, - .get = sch_gpio_core_get, - .direction_output = sch_gpio_core_direction_out, - .set = sch_gpio_core_set, -}; - -static int sch_gpio_resume_direction_in(struct gpio_chip *gc, - unsigned gpio_num) +static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) { + struct sch_gpio *sch = to_sch_gpio(gc); u8 curr_dirs; unsigned short offset, bit; - spin_lock(&gpio_lock); + spin_lock(&sch->lock); - offset = RGIO + gpio_num / 8; - bit = gpio_num % 8; + offset = sch_gpio_offset(sch, gpio_num, GIO); + bit = sch_gpio_bit(sch, gpio_num); - curr_dirs = inb(gpio_ba + offset); + curr_dirs = inb(sch->iobase + offset); if (!(curr_dirs & (1 << bit))) - outb(curr_dirs | (1 << bit), gpio_ba + offset); + outb(curr_dirs | (1 << bit), sch->iobase + offset); - spin_unlock(&gpio_lock); + spin_unlock(&sch->lock); return 0; } -static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num) +static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num) { + struct sch_gpio *sch = to_sch_gpio(gc); + int res; unsigned short offset, bit; - offset = RGLV + gpio_num / 8; - bit = gpio_num % 8; + offset = sch_gpio_offset(sch, gpio_num, GLV); + bit = sch_gpio_bit(sch, gpio_num); + + res = !!(inb(sch->iobase + offset) & (1 << bit)); - return !!(inb(gpio_ba + offset) & (1 << bit)); + return res; } -static void sch_gpio_resume_set(struct gpio_chip *gc, - unsigned gpio_num, int val) +static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val) { + struct sch_gpio *sch = to_sch_gpio(gc); u8 curr_vals; unsigned short offset, bit; - spin_lock(&gpio_lock); + spin_lock(&sch->lock); - offset = RGLV + gpio_num / 8; - bit = gpio_num % 8; + offset = sch_gpio_offset(sch, gpio_num, GLV); + bit = sch_gpio_bit(sch, gpio_num); - curr_vals = inb(gpio_ba + offset); + curr_vals = inb(sch->iobase + offset); if (val) - outb(curr_vals | (1 << bit), gpio_ba + offset); + outb(curr_vals | (1 << bit), sch->iobase + offset); else - outb((curr_vals & ~(1 << bit)), gpio_ba + offset); + outb((curr_vals & ~(1 << bit)), sch->iobase + offset); - spin_unlock(&gpio_lock); + spin_unlock(&sch->lock); } -static int sch_gpio_resume_direction_out(struct gpio_chip *gc, - unsigned gpio_num, int val) +static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num, + int val) { + struct sch_gpio *sch = to_sch_gpio(gc); u8 curr_dirs; unsigned short offset, bit; - offset = RGIO + gpio_num / 8; - bit = gpio_num % 8; + spin_lock(&sch->lock); - spin_lock(&gpio_lock); + offset = sch_gpio_offset(sch, gpio_num, GIO); + bit = sch_gpio_bit(sch, gpio_num); - curr_dirs = inb(gpio_ba + offset); + curr_dirs = inb(sch->iobase + offset); if (curr_dirs & (1 << bit)) - outb(curr_dirs & ~(1 << bit), gpio_ba + offset); + outb(curr_dirs & ~(1 << bit), sch->iobase + offset); - spin_unlock(&gpio_lock); + spin_unlock(&sch->lock); /* - * according to the datasheet, writing to the level register has no - * effect when GPIO is programmed as input. - * Actually the the level register is read-only when configured as input. - * Thus presetting the output level before switching to output is _NOT_ possible. - * Hence we set the level after configuring the GPIO as output. - * But we cannot prevent a short low pulse if direction is set to high - * and an external pull-up is connected. - */ - sch_gpio_resume_set(gc, gpio_num, val); + * according to the datasheet, writing to the level register has no + * effect when GPIO is programmed as input. + * Actually the the level register is read-only when configured as input. + * Thus presetting the output level before switching to output is _NOT_ possible. + * Hence we set the level after configuring the GPIO as output. + * But we cannot prevent a short low pulse if direction is set to high + * and an external pull-up is connected. + */ + sch_gpio_set(gc, gpio_num, val); return 0; } -static struct gpio_chip sch_gpio_resume = { - .label = "sch_gpio_resume", +static struct gpio_chip sch_gpio_chip = { + .label = "sch_gpio", .owner = THIS_MODULE, - .direction_input = sch_gpio_resume_direction_in, - .get = sch_gpio_resume_get, - .direction_output = sch_gpio_resume_direction_out, - .set = sch_gpio_resume_set, + .direction_input = sch_gpio_direction_in, + .get = sch_gpio_get, + .direction_output = sch_gpio_direction_out, + .set = sch_gpio_set, }; static int sch_gpio_probe(struct platform_device *pdev) { + struct sch_gpio *sch; struct resource *res; - int err, id; - id = pdev->id; - if (!id) - return -ENODEV; + sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL); + if (!sch) + return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!res) return -EBUSY; - if (!request_region(res->start, resource_size(res), pdev->name)) + if (!devm_request_region(&pdev->dev, res->start, resource_size(res), + pdev->name)) return -EBUSY; - gpio_ba = res->start; + spin_lock_init(&sch->lock); + sch->iobase = res->start; + sch->chip = sch_gpio_chip; + sch->chip.label = dev_name(&pdev->dev); + sch->chip.dev = &pdev->dev; - switch (id) { + switch (pdev->id) { case PCI_DEVICE_ID_INTEL_SCH_LPC: - sch_gpio_core.base = 0; - sch_gpio_core.ngpio = 10; - sch_gpio_resume.base = 10; - sch_gpio_resume.ngpio = 4; + sch->core_base = 0; + sch->resume_base = 10; + sch->chip.ngpio = 14; + /* * GPIO[6:0] enabled by default * GPIO7 is configured by the CMC as SLPIOVR * Enable GPIO[9:8] core powered gpios explicitly */ - outb(0x3, gpio_ba + CGEN + 1); + sch_gpio_enable(sch, 8); + sch_gpio_enable(sch, 9); /* * SUS_GPIO[2:0] enabled by default * Enable SUS_GPIO3 resume powered gpio explicitly */ - outb(0x8, gpio_ba + RGEN); + sch_gpio_enable(sch, 13); break; case PCI_DEVICE_ID_INTEL_ITC_LPC: - sch_gpio_core.base = 0; - sch_gpio_core.ngpio = 5; - sch_gpio_resume.base = 5; - sch_gpio_resume.ngpio = 9; + sch->core_base = 0; + sch->resume_base = 5; + sch->chip.ngpio = 14; break; case PCI_DEVICE_ID_INTEL_CENTERTON_ILB: - sch_gpio_core.base = 0; - sch_gpio_core.ngpio = 21; - sch_gpio_resume.base = 21; - sch_gpio_resume.ngpio = 9; + sch->core_base = 0; + sch->resume_base = 21; + sch->chip.ngpio = 30; break; default: - err = -ENODEV; - goto err_sch_gpio_core; + return -ENODEV; } - sch_gpio_core.dev = &pdev->dev; - sch_gpio_resume.dev = &pdev->dev; - - err = gpiochip_add(&sch_gpio_core); - if (err < 0) - goto err_sch_gpio_core; + platform_set_drvdata(pdev, sch); - err = gpiochip_add(&sch_gpio_resume); - if (err < 0) - goto err_sch_gpio_resume; - - return 0; - -err_sch_gpio_resume: - gpiochip_remove(&sch_gpio_core); - -err_sch_gpio_core: - release_region(res->start, resource_size(res)); - gpio_ba = 0; - - return err; + return gpiochip_add(&sch->chip); } static int sch_gpio_remove(struct platform_device *pdev) { - struct resource *res; - if (gpio_ba) { - - gpiochip_remove(&sch_gpio_core); - gpiochip_remove(&sch_gpio_resume); - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - - release_region(res->start, resource_size(res)); - gpio_ba = 0; - } + struct sch_gpio *sch = platform_get_drvdata(pdev); + gpiochip_remove(&sch->chip); return 0; } diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 05c6275da224..ba98bb59a58f 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -287,9 +287,45 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) } } +int acpi_dev_add_driver_gpios(struct acpi_device *adev, + const struct acpi_gpio_mapping *gpios) +{ + if (adev && gpios) { + adev->driver_gpios = gpios; + return 0; + } + return -EINVAL; +} +EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios); + +static bool acpi_get_driver_gpio_data(struct acpi_device *adev, + const char *name, int index, + struct acpi_reference_args *args) +{ + const struct acpi_gpio_mapping *gm; + + if (!adev->driver_gpios) + return false; + + for (gm = adev->driver_gpios; gm->name; gm++) + if (!strcmp(name, gm->name) && gm->data && index < gm->size) { + const struct acpi_gpio_params *par = gm->data + index; + + args->adev = adev; + args->args[0] = par->crs_entry_index; + args->args[1] = par->line_index; + args->args[2] = par->active_low; + args->nargs = 3; + return true; + } + + return false; +} + struct acpi_gpio_lookup { struct acpi_gpio_info info; int index; + int pin_index; struct gpio_desc *desc; int n; }; @@ -303,13 +339,24 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) if (lookup->n++ == lookup->index && !lookup->desc) { const struct acpi_resource_gpio *agpio = &ares->data.gpio; + int pin_index = lookup->pin_index; + + if (pin_index >= agpio->pin_table_length) + return 1; lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr, - agpio->pin_table[0]); + agpio->pin_table[pin_index]); lookup->info.gpioint = agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT; - lookup->info.active_low = - agpio->polarity == ACPI_ACTIVE_LOW; + + /* + * ActiveLow is only specified for GpioInt resource. If + * GpioIo is used then the only way to set the flag is + * to use _DSD "gpios" property. + */ + if (lookup->info.gpioint) + lookup->info.active_low = + agpio->polarity == ACPI_ACTIVE_LOW; } return 1; @@ -317,40 +364,79 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) /** * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources - * @dev: pointer to a device to get GPIO from + * @adev: pointer to a ACPI device to get GPIO from + * @propname: Property name of the GPIO (optional) * @index: index of GpioIo/GpioInt resource (starting from %0) * @info: info pointer to fill in (optional) * - * Function goes through ACPI resources for @dev and based on @index looks + * Function goes through ACPI resources for @adev and based on @index looks * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor, * and returns it. @index matches GpioIo/GpioInt resources only so if there * are total %3 GPIO resources, the index goes from %0 to %2. * + * If @propname is specified the GPIO is looked using device property. In + * that case @index is used to select the GPIO entry in the property value + * (in case of multiple). + * * If the GPIO cannot be translated or there is an error an ERR_PTR is * returned. * * Note: if the GPIO resource has multiple entries in the pin list, this * function only returns the first. */ -struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, +struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, + const char *propname, int index, struct acpi_gpio_info *info) { struct acpi_gpio_lookup lookup; struct list_head resource_list; - struct acpi_device *adev; - acpi_handle handle; + bool active_low = false; int ret; - if (!dev) - return ERR_PTR(-EINVAL); - - handle = ACPI_HANDLE(dev); - if (!handle || acpi_bus_get_device(handle, &adev)) + if (!adev) return ERR_PTR(-ENODEV); memset(&lookup, 0, sizeof(lookup)); lookup.index = index; + if (propname) { + struct acpi_reference_args args; + + dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname); + + memset(&args, 0, sizeof(args)); + ret = acpi_dev_get_property_reference(adev, propname, + index, &args); + if (ret) { + bool found = acpi_get_driver_gpio_data(adev, propname, + index, &args); + if (!found) + return ERR_PTR(ret); + } + + /* + * The property was found and resolved so need to + * lookup the GPIO based on returned args instead. + */ + adev = args.adev; + if (args.nargs >= 2) { + lookup.index = args.args[0]; + lookup.pin_index = args.args[1]; + /* + * 3rd argument, if present is used to + * specify active_low. + */ + if (args.nargs >= 3) + active_low = !!args.args[2]; + } + + dev_dbg(&adev->dev, "GPIO: _DSD returned %s %zd %llu %llu %llu\n", + dev_name(&adev->dev), args.nargs, + args.args[0], args.args[1], args.args[2]); + } else { + dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index); + } + INIT_LIST_HEAD(&resource_list); ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio, &lookup); @@ -359,8 +445,11 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, acpi_dev_free_resource_list(&resource_list); - if (lookup.desc && info) + if (lookup.desc && info) { *info = lookup.info; + if (active_low) + info->active_low = active_low; + } return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e8e98ca25ec7..58659dbe702a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1505,14 +1505,36 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpio_lookup_flags *flags) { + static const char * const suffixes[] = { "gpios", "gpio" }; + struct acpi_device *adev = ACPI_COMPANION(dev); struct acpi_gpio_info info; struct gpio_desc *desc; + char propname[32]; + int i; - desc = acpi_get_gpiod_by_index(dev, idx, &info); - if (IS_ERR(desc)) - return desc; + /* Try first from _DSD */ + for (i = 0; i < ARRAY_SIZE(suffixes); i++) { + if (con_id && strcmp(con_id, "gpios")) { + snprintf(propname, sizeof(propname), "%s-%s", + con_id, suffixes[i]); + } else { + snprintf(propname, sizeof(propname), "%s", + suffixes[i]); + } + + desc = acpi_get_gpiod_by_index(adev, propname, idx, &info); + if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER)) + break; + } - if (info.gpioint && info.active_low) + /* Then from plain _CRS GPIOs */ + if (IS_ERR(desc)) { + desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info); + if (IS_ERR(desc)) + return desc; + } + + if (info.active_low) *flags |= GPIO_ACTIVE_LOW; return desc; @@ -1713,6 +1735,61 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, EXPORT_SYMBOL_GPL(__gpiod_get_index); /** + * fwnode_get_named_gpiod - obtain a GPIO from firmware node + * @fwnode: handle of the firmware node + * @propname: name of the firmware property representing the GPIO + * + * This function can be used for drivers that get their configuration + * from firmware. + * + * Function properly finds the corresponding GPIO using whatever is the + * underlying firmware interface and then makes sure that the GPIO + * descriptor is requested before it is returned to the caller. + * + * In case of error an ERR_PTR() is returned. + */ +struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, + const char *propname) +{ + struct gpio_desc *desc = ERR_PTR(-ENODEV); + bool active_low = false; + int ret; + + if (!fwnode) + return ERR_PTR(-EINVAL); + + if (is_of_node(fwnode)) { + enum of_gpio_flags flags; + + desc = of_get_named_gpiod_flags(of_node(fwnode), propname, 0, + &flags); + if (!IS_ERR(desc)) + active_low = flags & OF_GPIO_ACTIVE_LOW; + } else if (is_acpi_node(fwnode)) { + struct acpi_gpio_info info; + + desc = acpi_get_gpiod_by_index(acpi_node(fwnode), propname, 0, + &info); + if (!IS_ERR(desc)) + active_low = info.active_low; + } + + if (IS_ERR(desc)) + return desc; + + ret = gpiod_request(desc, NULL); + if (ret) + return ERR_PTR(ret); + + /* Only value flag can be set from both DT and ACPI is active_low */ + if (active_low) + set_bit(FLAG_ACTIVE_LOW, &desc->flags); + + return desc; +} +EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod); + +/** * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO * function * @dev: GPIO consumer, can be NULL for system-global GPIOs diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 9db2b6a71c5d..e3a52113a541 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -34,7 +34,8 @@ void acpi_gpiochip_remove(struct gpio_chip *chip); void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); -struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, +struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, + const char *propname, int index, struct acpi_gpio_info *info); #else static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } @@ -47,8 +48,8 @@ static inline void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { } static inline struct gpio_desc * -acpi_get_gpiod_by_index(struct device *dev, int index, - struct acpi_gpio_info *info) +acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname, + int index, struct acpi_gpio_info *info) { return ERR_PTR(-ENOSYS); } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f0a1a56406eb..9cb5c95d5898 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4325,7 +4325,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) ironlake_fdi_disable(crtc); ironlake_disable_pch_transcoder(dev_priv, pipe); - intel_set_pch_fifo_underrun_reporting(dev, pipe, true); if (HAS_PCH_CPT(dev)) { /* disable TRANS_DP_CTL */ @@ -4389,7 +4388,6 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) if (intel_crtc->config.has_pch_encoder) { lpt_disable_pch_transcoder(dev_priv); - intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true); intel_ddi_fdi_disable(crtc); } @@ -9408,6 +9406,10 @@ static bool page_flip_finished(struct intel_crtc *crtc) struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + if (i915_reset_in_progress(&dev_priv->gpu_error) || + crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter)) + return true; + /* * The relevant registers doen't exist on pre-ctg. * As the flip done interrupt doesn't trigger for mmio diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5ad45bfff3fe..4bcd91757321 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4450,6 +4450,7 @@ static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) * vdd might still be enabled do to the delayed vdd off. * Make sure vdd is actually turned off here. */ + cancel_delayed_work_sync(&intel_dp->panel_vdd_work); pps_lock(intel_dp); edp_panel_vdd_off_sync(intel_dp); pps_unlock(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index a6bd1422e38f..c0bbf2172446 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -899,6 +899,17 @@ void intel_lvds_init(struct drm_device *dev) int pipe; u8 pin; + /* + * Unlock registers and just leave them unlocked. Do this before + * checking quirk lists to avoid bogus WARNINGs. + */ + if (HAS_PCH_SPLIT(dev)) { + I915_WRITE(PCH_PP_CONTROL, + I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); + } else { + I915_WRITE(PP_CONTROL, + I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); + } if (!intel_lvds_supported(dev)) return; @@ -1097,17 +1108,6 @@ out: lvds_encoder->a3_power = I915_READ(lvds_encoder->reg) & LVDS_A3_POWER_MASK; - /* - * Unlock registers and just - * leave them unlocked - */ - if (HAS_PCH_SPLIT(dev)) { - I915_WRITE(PCH_PP_CONTROL, - I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); - } else { - I915_WRITE(PP_CONTROL, - I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); - } lvds_connector->lid_notifier.notifier_call = intel_lid_notify; if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) { DRM_DEBUG_KMS("lid notifier registration failed\n"); diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c index cd05677ad4b7..72a40f95d048 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c @@ -218,7 +218,6 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass; device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; - device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass; device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass; break; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index 5ae6a43893b5..1931057f9962 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -551,8 +551,8 @@ nv04_fifo_intr(struct nouveau_subdev *subdev) } if (status & 0x40000000) { - nouveau_fifo_uevent(&priv->base); nv_wr32(priv, 0x002100, 0x40000000); + nouveau_fifo_uevent(&priv->base); status &= ~0x40000000; } } diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index 1fe1f8fbda0c..074d434c3077 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -740,6 +740,8 @@ nvc0_fifo_intr_engine_unit(struct nvc0_fifo_priv *priv, int engn) u32 inte = nv_rd32(priv, 0x002628); u32 unkn; + nv_wr32(priv, 0x0025a8 + (engn * 0x04), intr); + for (unkn = 0; unkn < 8; unkn++) { u32 ints = (intr >> (unkn * 0x04)) & inte; if (ints & 0x1) { @@ -751,8 +753,6 @@ nvc0_fifo_intr_engine_unit(struct nvc0_fifo_priv *priv, int engn) nv_mask(priv, 0x002628, ints, 0); } } - - nv_wr32(priv, 0x0025a8 + (engn * 0x04), intr); } static void diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index d2f0fd39c145..f8734eb74eaa 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -952,8 +952,8 @@ nve0_fifo_intr(struct nouveau_subdev *subdev) } if (stat & 0x80000000) { - nve0_fifo_intr_engine(priv); nv_wr32(priv, 0x002100, 0x80000000); + nve0_fifo_intr_engine(priv); stat &= ~0x80000000; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 57238076049f..62b97c4eef8d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -629,7 +629,6 @@ int nouveau_pmops_suspend(struct device *dev) pci_save_state(pdev); pci_disable_device(pdev); - pci_ignore_hotplug(pdev); pci_set_power_state(pdev, PCI_D3hot); return 0; } @@ -933,6 +932,7 @@ static int nouveau_pmops_runtime_suspend(struct device *dev) ret = nouveau_do_suspend(drm_dev, true); pci_save_state(pdev); pci_disable_device(pdev); + pci_ignore_hotplug(pdev); pci_set_power_state(pdev, PCI_D3cold); drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 515cd9aebb99..f32a434724e3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -52,20 +52,24 @@ nouveau_fctx(struct nouveau_fence *fence) return container_of(fence->base.lock, struct nouveau_fence_chan, lock); } -static void +static int nouveau_fence_signal(struct nouveau_fence *fence) { + int drop = 0; + fence_signal_locked(&fence->base); list_del(&fence->head); + rcu_assign_pointer(fence->channel, NULL); if (test_bit(FENCE_FLAG_USER_BITS, &fence->base.flags)) { struct nouveau_fence_chan *fctx = nouveau_fctx(fence); if (!--fctx->notify_ref) - nvif_notify_put(&fctx->notify); + drop = 1; } fence_put(&fence->base); + return drop; } static struct nouveau_fence * @@ -88,16 +92,23 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx) { struct nouveau_fence *fence; - nvif_notify_fini(&fctx->notify); - spin_lock_irq(&fctx->lock); while (!list_empty(&fctx->pending)) { fence = list_entry(fctx->pending.next, typeof(*fence), head); - nouveau_fence_signal(fence); - fence->channel = NULL; + if (nouveau_fence_signal(fence)) + nvif_notify_put(&fctx->notify); } spin_unlock_irq(&fctx->lock); + + nvif_notify_fini(&fctx->notify); + fctx->dead = 1; + + /* + * Ensure that all accesses to fence->channel complete before freeing + * the channel. + */ + synchronize_rcu(); } static void @@ -112,21 +123,23 @@ nouveau_fence_context_free(struct nouveau_fence_chan *fctx) kref_put(&fctx->fence_ref, nouveau_fence_context_put); } -static void +static int nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx) { struct nouveau_fence *fence; - + int drop = 0; u32 seq = fctx->read(chan); while (!list_empty(&fctx->pending)) { fence = list_entry(fctx->pending.next, typeof(*fence), head); if ((int)(seq - fence->base.seqno) < 0) - return; + break; - nouveau_fence_signal(fence); + drop |= nouveau_fence_signal(fence); } + + return drop; } static int @@ -135,18 +148,21 @@ nouveau_fence_wait_uevent_handler(struct nvif_notify *notify) struct nouveau_fence_chan *fctx = container_of(notify, typeof(*fctx), notify); unsigned long flags; + int ret = NVIF_NOTIFY_KEEP; spin_lock_irqsave(&fctx->lock, flags); if (!list_empty(&fctx->pending)) { struct nouveau_fence *fence; + struct nouveau_channel *chan; fence = list_entry(fctx->pending.next, typeof(*fence), head); - nouveau_fence_update(fence->channel, fctx); + chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); + if (nouveau_fence_update(fence->channel, fctx)) + ret = NVIF_NOTIFY_DROP; } spin_unlock_irqrestore(&fctx->lock, flags); - /* Always return keep here. NVIF refcount is handled with nouveau_fence_update */ - return NVIF_NOTIFY_KEEP; + return ret; } void @@ -262,7 +278,10 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) if (!ret) { fence_get(&fence->base); spin_lock_irq(&fctx->lock); - nouveau_fence_update(chan, fctx); + + if (nouveau_fence_update(chan, fctx)) + nvif_notify_put(&fctx->notify); + list_add_tail(&fence->head, &fctx->pending); spin_unlock_irq(&fctx->lock); } @@ -276,13 +295,16 @@ nouveau_fence_done(struct nouveau_fence *fence) if (fence->base.ops == &nouveau_fence_ops_legacy || fence->base.ops == &nouveau_fence_ops_uevent) { struct nouveau_fence_chan *fctx = nouveau_fctx(fence); + struct nouveau_channel *chan; unsigned long flags; if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags)) return true; spin_lock_irqsave(&fctx->lock, flags); - nouveau_fence_update(fence->channel, fctx); + chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); + if (chan && nouveau_fence_update(chan, fctx)) + nvif_notify_put(&fctx->notify); spin_unlock_irqrestore(&fctx->lock, flags); } return fence_is_signaled(&fence->base); @@ -387,12 +409,18 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e if (fence && (!exclusive || !fobj || !fobj->shared_count)) { struct nouveau_channel *prev = NULL; + bool must_wait = true; f = nouveau_local_fence(fence, chan->drm); - if (f) - prev = f->channel; + if (f) { + rcu_read_lock(); + prev = rcu_dereference(f->channel); + if (prev && (prev == chan || fctx->sync(f, prev, chan) == 0)) + must_wait = false; + rcu_read_unlock(); + } - if (!prev || (prev != chan && (ret = fctx->sync(f, prev, chan)))) + if (must_wait) ret = fence_wait(fence, intr); return ret; @@ -403,19 +431,22 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e for (i = 0; i < fobj->shared_count && !ret; ++i) { struct nouveau_channel *prev = NULL; + bool must_wait = true; fence = rcu_dereference_protected(fobj->shared[i], reservation_object_held(resv)); f = nouveau_local_fence(fence, chan->drm); - if (f) - prev = f->channel; + if (f) { + rcu_read_lock(); + prev = rcu_dereference(f->channel); + if (prev && (prev == chan || fctx->sync(f, prev, chan) == 0)) + must_wait = false; + rcu_read_unlock(); + } - if (!prev || (prev != chan && (ret = fctx->sync(f, prev, chan)))) + if (must_wait) ret = fence_wait(fence, intr); - - if (ret) - break; } return ret; @@ -463,7 +494,7 @@ static const char *nouveau_fence_get_timeline_name(struct fence *f) struct nouveau_fence *fence = from_fence(f); struct nouveau_fence_chan *fctx = nouveau_fctx(fence); - return fence->channel ? fctx->name : "dead channel"; + return !fctx->dead ? fctx->name : "dead channel"; } /* @@ -476,9 +507,16 @@ static bool nouveau_fence_is_signaled(struct fence *f) { struct nouveau_fence *fence = from_fence(f); struct nouveau_fence_chan *fctx = nouveau_fctx(fence); - struct nouveau_channel *chan = fence->channel; + struct nouveau_channel *chan; + bool ret = false; + + rcu_read_lock(); + chan = rcu_dereference(fence->channel); + if (chan) + ret = (int)(fctx->read(chan) - fence->base.seqno) >= 0; + rcu_read_unlock(); - return (int)(fctx->read(chan) - fence->base.seqno) >= 0; + return ret; } static bool nouveau_fence_no_signaling(struct fence *f) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index 943b0b17b1fc..96e461c6f68f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -14,7 +14,7 @@ struct nouveau_fence { bool sysmem; - struct nouveau_channel *channel; + struct nouveau_channel __rcu *channel; unsigned long timeout; }; @@ -47,7 +47,7 @@ struct nouveau_fence_chan { char name[32]; struct nvif_notify notify; - int notify_ref; + int notify_ref, dead; }; struct nouveau_fence_priv { diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 300c4b3d4669..26baa9c05f6c 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -322,6 +322,12 @@ static void radeon_connector_get_edid(struct drm_connector *connector) } if (!radeon_connector->edid) { + /* don't fetch the edid from the vbios if ddc fails and runpm is + * enabled so we report disconnected. + */ + if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0)) + return; + if (rdev->is_atom_bios) { /* some laptops provide a hardcoded edid in rom for LCDs */ if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) || @@ -826,6 +832,8 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector, static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector, bool force) { + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct drm_encoder *encoder = radeon_best_single_encoder(connector); enum drm_connector_status ret = connector_status_disconnected; @@ -842,7 +850,11 @@ radeon_lvds_detect(struct drm_connector *connector, bool force) /* check if panel is valid */ if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240) ret = connector_status_connected; - + /* don't fetch the edid from the vbios if ddc fails and runpm is + * enabled so we report disconnected. + */ + if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0)) + ret = connector_status_disconnected; } /* check for edid as well */ @@ -1589,6 +1601,11 @@ radeon_dp_detect(struct drm_connector *connector, bool force) /* check if panel is valid */ if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240) ret = connector_status_connected; + /* don't fetch the edid from the vbios if ddc fails and runpm is + * enabled so we report disconnected. + */ + if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0)) + ret = connector_status_disconnected; } /* eDP is always DP */ radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT; diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index a3e7aed7e680..6f377de099f9 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -251,22 +251,19 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority static int radeon_cs_sync_rings(struct radeon_cs_parser *p) { - int i, r = 0; + struct radeon_cs_reloc *reloc; + int r; - for (i = 0; i < p->nrelocs; i++) { + list_for_each_entry(reloc, &p->validated, tv.head) { struct reservation_object *resv; - if (!p->relocs[i].robj) - continue; - - resv = p->relocs[i].robj->tbo.resv; + resv = reloc->robj->tbo.resv; r = radeon_semaphore_sync_resv(p->rdev, p->ib.semaphore, resv, - p->relocs[i].tv.shared); - + reloc->tv.shared); if (r) - break; + return r; } - return r; + return 0; } /* XXX: note that this is called from the legacy UMS CS ioctl as well */ diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 7784911d78ef..00fc59762e0d 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -185,6 +185,16 @@ static bool radeon_msi_ok(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_AGP) return false; + /* + * Older chips have a HW limitation, they can only generate 40 bits + * of address for "64-bit" MSIs which breaks on some platforms, notably + * IBM POWER servers, so we limit them + */ + if (rdev->family < CHIP_BONAIRE) { + dev_info(rdev->dev, "radeon: MSI limited to 32-bit\n"); + rdev->pdev->no_64bit_msi = 1; + } + /* force MSI on */ if (radeon_msi == 1) return true; diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 8309b11e674d..03586763ee86 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -795,6 +795,8 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, /* Get associated drm_crtc: */ drmcrtc = &rdev->mode_info.crtcs[crtc]->base; + if (!drmcrtc) + return -EINVAL; /* Helper routine in DRM core does all the work: */ return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 99a960a4f302..4c0d786d5c7a 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -213,6 +213,13 @@ int radeon_bo_create(struct radeon_device *rdev, if (!(rdev->flags & RADEON_IS_PCIE)) bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC); +#ifdef CONFIG_X86_32 + /* XXX: Write-combined CPU mappings of GTT seem broken on 32-bit + * See https://bugs.freedesktop.org/show_bug.cgi?id=84627 + */ + bo->flags &= ~RADEON_GEM_GTT_WC; +#endif + radeon_ttm_placement_from_domain(bo, domain); /* Kernel allocation are uninterruptible */ down_read(&rdev->pm.mclk_lock); diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c index 6aac695b1688..9b55e673b67c 100644 --- a/drivers/hwmon/g762.c +++ b/drivers/hwmon/g762.c @@ -1084,10 +1084,8 @@ static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id) if (ret) goto clock_dis; - data->hwmon_dev = devm_hwmon_device_register_with_groups(dev, - client->name, - data, - g762_groups); + data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name, + data, g762_groups); if (IS_ERR(data->hwmon_dev)) { ret = PTR_ERR(data->hwmon_dev); goto clock_dis; diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 63f3f03ecc9b..c604f4c3ac0d 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -111,6 +111,8 @@ #define CDNS_I2C_DIVA_MAX 4 #define CDNS_I2C_DIVB_MAX 64 +#define CDNS_I2C_TIMEOUT_MAX 0xFF + #define cdns_i2c_readreg(offset) readl_relaxed(id->membase + offset) #define cdns_i2c_writereg(val, offset) writel_relaxed(val, id->membase + offset) @@ -852,6 +854,15 @@ static int cdns_i2c_probe(struct platform_device *pdev) goto err_clk_dis; } + /* + * Cadence I2C controller has a bug wherein it generates + * invalid read transaction after HW timeout in master receiver mode. + * HW timeout is not used by this driver and the interrupt is disabled. + * But the feature itself cannot be disabled. Hence maximum value + * is written to this register to reduce the chances of error. + */ + cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET); + dev_info(&pdev->dev, "%u kHz mmio %08lx irq %d\n", id->i2c_clk / 1000, (unsigned long)r_mem->start, id->irq); diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index d15b7c9b9219..01f0cd87a4a5 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -407,11 +407,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) if (dev->cmd_err & DAVINCI_I2C_STR_NACK) { if (msg->flags & I2C_M_IGNORE_NAK) return msg->len; - if (stop) { - w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); - w |= DAVINCI_I2C_MDR_STP; - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); - } + w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); + w |= DAVINCI_I2C_MDR_STP; + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); return -EREMOTEIO; } return -EIO; diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index edca99dbba23..23628b7bfb8d 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -359,7 +359,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev) } /* Configure Tx/Rx FIFO threshold levels */ - dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL); + dw_writel(dev, dev->tx_fifo_depth / 2, DW_IC_TX_TL); dw_writel(dev, 0, DW_IC_RX_TL); /* configure the i2c master */ diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 26942c159de1..277a2288d4a8 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -922,14 +922,12 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) if (stat & OMAP_I2C_STAT_NACK) { err |= OMAP_I2C_STAT_NACK; omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK); - break; } if (stat & OMAP_I2C_STAT_AL) { dev_err(dev->dev, "Arbitration lost\n"); err |= OMAP_I2C_STAT_AL; omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL); - break; } /* @@ -954,11 +952,13 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) if (dev->fifo_size) num_bytes = dev->buf_len; - omap_i2c_receive_data(dev, num_bytes, true); - - if (dev->errata & I2C_OMAP_ERRATA_I207) + if (dev->errata & I2C_OMAP_ERRATA_I207) { i2c_omap_errata_i207(dev, stat); + num_bytes = (omap_i2c_read_reg(dev, + OMAP_I2C_BUFSTAT_REG) >> 8) & 0x3F; + } + omap_i2c_receive_data(dev, num_bytes, true); omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); continue; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index f43b4e11647a..68aeb8eedae0 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -403,6 +403,7 @@ static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) return -ENOMEM; } + acpi_walk_dep_device_list(handle); return 0; } diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c index 22c096ce39ad..513bd6d14293 100644 --- a/drivers/iio/accel/bmc150-accel.c +++ b/drivers/iio/accel/bmc150-accel.c @@ -44,6 +44,9 @@ #define BMC150_ACCEL_REG_INT_STATUS_2 0x0B #define BMC150_ACCEL_ANY_MOTION_MASK 0x07 +#define BMC150_ACCEL_ANY_MOTION_BIT_X BIT(0) +#define BMC150_ACCEL_ANY_MOTION_BIT_Y BIT(1) +#define BMC150_ACCEL_ANY_MOTION_BIT_Z BIT(2) #define BMC150_ACCEL_ANY_MOTION_BIT_SIGN BIT(3) #define BMC150_ACCEL_REG_PMU_LPW 0x11 @@ -92,9 +95,9 @@ #define BMC150_ACCEL_SLOPE_THRES_MASK 0xFF /* Slope duration in terms of number of samples */ -#define BMC150_ACCEL_DEF_SLOPE_DURATION 2 +#define BMC150_ACCEL_DEF_SLOPE_DURATION 1 /* in terms of multiples of g's/LSB, based on range */ -#define BMC150_ACCEL_DEF_SLOPE_THRESHOLD 5 +#define BMC150_ACCEL_DEF_SLOPE_THRESHOLD 1 #define BMC150_ACCEL_REG_XOUT_L 0x02 @@ -536,6 +539,9 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on) if (ret < 0) { dev_err(&data->client->dev, "Failed: bmc150_accel_set_power_state for %d\n", on); + if (on) + pm_runtime_put_noidle(&data->client->dev); + return ret; } @@ -811,6 +817,7 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev, ret = bmc150_accel_setup_any_motion_interrupt(data, state); if (ret < 0) { + bmc150_accel_set_power_state(data, false); mutex_unlock(&data->mutex); return ret; } @@ -846,7 +853,7 @@ static const struct attribute_group bmc150_accel_attrs_group = { static const struct iio_event_spec bmc150_accel_event = { .type = IIO_EV_TYPE_ROC, - .dir = IIO_EV_DIR_RISING | IIO_EV_DIR_FALLING, + .dir = IIO_EV_DIR_EITHER, .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_PERIOD) @@ -1054,6 +1061,7 @@ static int bmc150_accel_data_rdy_trigger_set_state(struct iio_trigger *trig, else ret = bmc150_accel_setup_new_data_interrupt(data, state); if (ret < 0) { + bmc150_accel_set_power_state(data, false); mutex_unlock(&data->mutex); return ret; } @@ -1092,12 +1100,26 @@ static irqreturn_t bmc150_accel_event_handler(int irq, void *private) else dir = IIO_EV_DIR_RISING; - if (ret & BMC150_ACCEL_ANY_MOTION_MASK) + if (ret & BMC150_ACCEL_ANY_MOTION_BIT_X) + iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_X, + IIO_EV_TYPE_ROC, + dir), + data->timestamp); + if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Y) iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, - IIO_MOD_X_OR_Y_OR_Z, + IIO_MOD_Y, IIO_EV_TYPE_ROC, - IIO_EV_DIR_EITHER), + dir), + data->timestamp); + if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Z) + iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Z, + IIO_EV_TYPE_ROC, + dir), data->timestamp); ack_intr_status: if (!data->dready_trigger_on) @@ -1354,10 +1376,14 @@ static int bmc150_accel_runtime_suspend(struct device *dev) { struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct bmc150_accel_data *data = iio_priv(indio_dev); + int ret; dev_dbg(&data->client->dev, __func__); + ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0); + if (ret < 0) + return -EAGAIN; - return bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0); + return 0; } static int bmc150_accel_runtime_resume(struct device *dev) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index a23e58c4ed99..320aa72c0349 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -269,6 +269,8 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index) return ret; } + ret &= ~(KXCJK1013_REG_CTRL1_BIT_GSEL0 | + KXCJK1013_REG_CTRL1_BIT_GSEL1); ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3); ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4); diff --git a/drivers/iio/adc/men_z188_adc.c b/drivers/iio/adc/men_z188_adc.c index b58d6302521f..d095efe1ba14 100644 --- a/drivers/iio/adc/men_z188_adc.c +++ b/drivers/iio/adc/men_z188_adc.c @@ -152,6 +152,7 @@ static void men_z188_remove(struct mcb_device *dev) static const struct mcb_device_id men_z188_ids[] = { { .device = 0xbc }, + { } }; MODULE_DEVICE_TABLE(mcb, men_z188_ids); diff --git a/drivers/iio/gyro/bmg160.c b/drivers/iio/gyro/bmg160.c index 1f967e0d688e..d2fa526740ca 100644 --- a/drivers/iio/gyro/bmg160.c +++ b/drivers/iio/gyro/bmg160.c @@ -67,6 +67,9 @@ #define BMG160_REG_INT_EN_0 0x15 #define BMG160_DATA_ENABLE_INT BIT(7) +#define BMG160_REG_INT_EN_1 0x16 +#define BMG160_INT1_BIT_OD BIT(1) + #define BMG160_REG_XOUT_L 0x02 #define BMG160_AXIS_TO_REG(axis) (BMG160_REG_XOUT_L + (axis * 2)) @@ -82,6 +85,9 @@ #define BMG160_REG_INT_STATUS_2 0x0B #define BMG160_ANY_MOTION_MASK 0x07 +#define BMG160_ANY_MOTION_BIT_X BIT(0) +#define BMG160_ANY_MOTION_BIT_Y BIT(1) +#define BMG160_ANY_MOTION_BIT_Z BIT(2) #define BMG160_REG_TEMP 0x08 #define BMG160_TEMP_CENTER_VAL 23 @@ -222,6 +228,19 @@ static int bmg160_chip_init(struct bmg160_data *data) data->slope_thres = ret; /* Set default interrupt mode */ + ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_EN_1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_int_en_1\n"); + return ret; + } + ret &= ~BMG160_INT1_BIT_OD; + ret = i2c_smbus_write_byte_data(data->client, + BMG160_REG_INT_EN_1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_int_en_1\n"); + return ret; + } + ret = i2c_smbus_write_byte_data(data->client, BMG160_REG_INT_RST_LATCH, BMG160_INT_MODE_LATCH_INT | @@ -250,6 +269,9 @@ static int bmg160_set_power_state(struct bmg160_data *data, bool on) if (ret < 0) { dev_err(&data->client->dev, "Failed: bmg160_set_power_state for %d\n", on); + if (on) + pm_runtime_put_noidle(&data->client->dev); + return ret; } #endif @@ -705,6 +727,7 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev, ret = bmg160_setup_any_motion_interrupt(data, state); if (ret < 0) { + bmg160_set_power_state(data, false); mutex_unlock(&data->mutex); return ret; } @@ -743,7 +766,7 @@ static const struct attribute_group bmg160_attrs_group = { static const struct iio_event_spec bmg160_event = { .type = IIO_EV_TYPE_ROC, - .dir = IIO_EV_DIR_RISING | IIO_EV_DIR_FALLING, + .dir = IIO_EV_DIR_EITHER, .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE) }; @@ -871,6 +894,7 @@ static int bmg160_data_rdy_trigger_set_state(struct iio_trigger *trig, else ret = bmg160_setup_new_data_interrupt(data, state); if (ret < 0) { + bmg160_set_power_state(data, false); mutex_unlock(&data->mutex); return ret; } @@ -908,10 +932,24 @@ static irqreturn_t bmg160_event_handler(int irq, void *private) else dir = IIO_EV_DIR_FALLING; - if (ret & BMG160_ANY_MOTION_MASK) + if (ret & BMG160_ANY_MOTION_BIT_X) iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, 0, - IIO_MOD_X_OR_Y_OR_Z, + IIO_MOD_X, + IIO_EV_TYPE_ROC, + dir), + data->timestamp); + if (ret & BMG160_ANY_MOTION_BIT_Y) + iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, + 0, + IIO_MOD_Y, + IIO_EV_TYPE_ROC, + dir), + data->timestamp); + if (ret & BMG160_ANY_MOTION_BIT_Z) + iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, + 0, + IIO_MOD_Z, IIO_EV_TYPE_ROC, dir), data->timestamp); @@ -1169,8 +1207,15 @@ static int bmg160_runtime_suspend(struct device *dev) { struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct bmg160_data *data = iio_priv(indio_dev); + int ret; + + ret = bmg160_set_mode(data, BMG160_MODE_SUSPEND); + if (ret < 0) { + dev_err(&data->client->dev, "set mode failed\n"); + return -EAGAIN; + } - return bmg160_set_mode(data, BMG160_MODE_SUSPEND); + return 0; } static int bmg160_runtime_resume(struct device *dev) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index bc203485716d..8afa28e4570e 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -421,7 +421,7 @@ static int evdev_open(struct inode *inode, struct file *file) err_free_client: evdev_detach_client(evdev, client); - kfree(client); + kvfree(client); return error; } diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 2ed7905a068f..fc55f0d15b70 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -1179,9 +1179,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id } ep_irq_in = &intf->cur_altsetting->endpoint[1].desc; - usb_fill_bulk_urb(xpad->bulk_out, udev, - usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress), - xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad); + if (usb_endpoint_is_bulk_out(ep_irq_in)) { + usb_fill_bulk_urb(xpad->bulk_out, udev, + usb_sndbulkpipe(udev, + ep_irq_in->bEndpointAddress), + xpad->bdata, XPAD_PKT_LEN, + xpad_bulk_out, xpad); + } else { + usb_fill_int_urb(xpad->bulk_out, udev, + usb_sndintpipe(udev, + ep_irq_in->bEndpointAddress), + xpad->bdata, XPAD_PKT_LEN, + xpad_bulk_out, xpad, 0); + } /* * Submit the int URB immediately rather than waiting for open diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 432d36395f35..c9c1c8ca7267 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -23,10 +23,9 @@ #include <linux/ioport.h> #include <linux/platform_device.h> #include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/gpio_keys.h> -#include <linux/of.h> -#include <linux/of_platform.h> -#include <linux/of_gpio.h> +#include <linux/property.h> #define DRV_NAME "gpio-keys-polled" @@ -51,15 +50,14 @@ static void gpio_keys_polled_check_state(struct input_dev *input, int state; if (bdata->can_sleep) - state = !!gpio_get_value_cansleep(button->gpio); + state = !!gpiod_get_value_cansleep(button->gpiod); else - state = !!gpio_get_value(button->gpio); + state = !!gpiod_get_value(button->gpiod); if (state != bdata->last_state) { unsigned int type = button->type ?: EV_KEY; - input_event(input, type, button->code, - !!(state ^ button->active_low)); + input_event(input, type, button->code, state); input_sync(input); bdata->count = 0; bdata->last_state = state; @@ -102,21 +100,15 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev) pdata->disable(bdev->dev); } -#ifdef CONFIG_OF static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev) { - struct device_node *node, *pp; struct gpio_keys_platform_data *pdata; struct gpio_keys_button *button; + struct fwnode_handle *child; int error; int nbuttons; - int i; - - node = dev->of_node; - if (!node) - return NULL; - nbuttons = of_get_child_count(node); + nbuttons = device_get_child_node_count(dev); if (nbuttons == 0) return NULL; @@ -126,52 +118,44 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct return ERR_PTR(-ENOMEM); pdata->buttons = (struct gpio_keys_button *)(pdata + 1); - pdata->nbuttons = nbuttons; - pdata->rep = !!of_get_property(node, "autorepeat", NULL); - of_property_read_u32(node, "poll-interval", &pdata->poll_interval); + pdata->rep = device_property_present(dev, "autorepeat"); + device_property_read_u32(dev, "poll-interval", &pdata->poll_interval); - i = 0; - for_each_child_of_node(node, pp) { - int gpio; - enum of_gpio_flags flags; + device_for_each_child_node(dev, child) { + struct gpio_desc *desc; - if (!of_find_property(pp, "gpios", NULL)) { - pdata->nbuttons--; - dev_warn(dev, "Found button without gpios\n"); - continue; - } - - gpio = of_get_gpio_flags(pp, 0, &flags); - if (gpio < 0) { - error = gpio; + desc = devm_get_gpiod_from_child(dev, child); + if (IS_ERR(desc)) { + error = PTR_ERR(desc); if (error != -EPROBE_DEFER) dev_err(dev, "Failed to get gpio flags, error: %d\n", error); + fwnode_handle_put(child); return ERR_PTR(error); } - button = &pdata->buttons[i++]; - - button->gpio = gpio; - button->active_low = flags & OF_GPIO_ACTIVE_LOW; + button = &pdata->buttons[pdata->nbuttons++]; + button->gpiod = desc; - if (of_property_read_u32(pp, "linux,code", &button->code)) { - dev_err(dev, "Button without keycode: 0x%x\n", - button->gpio); + if (fwnode_property_read_u32(child, "linux,code", &button->code)) { + dev_err(dev, "Button without keycode: %d\n", + pdata->nbuttons - 1); + fwnode_handle_put(child); return ERR_PTR(-EINVAL); } - button->desc = of_get_property(pp, "label", NULL); + fwnode_property_read_string(child, "label", &button->desc); - if (of_property_read_u32(pp, "linux,input-type", &button->type)) + if (fwnode_property_read_u32(child, "linux,input-type", + &button->type)) button->type = EV_KEY; - button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); + button->wakeup = fwnode_property_present(child, "gpio-key,wakeup"); - if (of_property_read_u32(pp, "debounce-interval", - &button->debounce_interval)) + if (fwnode_property_read_u32(child, "debounce-interval", + &button->debounce_interval)) button->debounce_interval = 5; } @@ -187,15 +171,6 @@ static const struct of_device_id gpio_keys_polled_of_match[] = { }; MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match); -#else - -static inline struct gpio_keys_platform_data * -gpio_keys_polled_get_devtree_pdata(struct device *dev) -{ - return NULL; -} -#endif - static int gpio_keys_polled_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -259,7 +234,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_keys_button_data *bdata = &bdev->data[i]; - unsigned int gpio = button->gpio; unsigned int type = button->type ?: EV_KEY; if (button->wakeup) { @@ -267,15 +241,31 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) return -EINVAL; } - error = devm_gpio_request_one(&pdev->dev, gpio, GPIOF_IN, - button->desc ? : DRV_NAME); - if (error) { - dev_err(dev, "unable to claim gpio %u, err=%d\n", - gpio, error); - return error; + /* + * Legacy GPIO number so request the GPIO here and + * convert it to descriptor. + */ + if (!button->gpiod && gpio_is_valid(button->gpio)) { + unsigned flags = 0; + + if (button->active_low) + flags |= GPIOF_ACTIVE_LOW; + + error = devm_gpio_request_one(&pdev->dev, button->gpio, + flags, button->desc ? : DRV_NAME); + if (error) { + dev_err(dev, "unable to claim gpio %u, err=%d\n", + button->gpio, error); + return error; + } + + button->gpiod = gpio_to_desc(button->gpio); } - bdata->can_sleep = gpio_cansleep(gpio); + if (IS_ERR(button->gpiod)) + return PTR_ERR(button->gpiod); + + bdata->can_sleep = gpiod_cansleep(button->gpiod); bdata->last_state = -1; bdata->threshold = DIV_ROUND_UP(button->debounce_interval, pdata->poll_interval); @@ -308,7 +298,7 @@ static struct platform_driver gpio_keys_polled_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, - .of_match_table = of_match_ptr(gpio_keys_polled_of_match), + .of_match_table = gpio_keys_polled_of_match, }, }; module_platform_driver(gpio_keys_polled_driver); diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 3fcb6b3cb0bd..f2b978026407 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -428,14 +428,6 @@ static void elantech_report_trackpoint(struct psmouse *psmouse, int x, y; u32 t; - if (dev_WARN_ONCE(&psmouse->ps2dev.serio->dev, - !tp_dev, - psmouse_fmt("Unexpected trackpoint message\n"))) { - if (etd->debug == 1) - elantech_packet_dump(psmouse); - return; - } - t = get_unaligned_le32(&packet[0]); switch (t & ~7U) { @@ -793,7 +785,7 @@ static int elantech_packet_check_v4(struct psmouse *psmouse) unsigned char packet_type = packet[3] & 0x03; bool sanity_check; - if ((packet[3] & 0x0f) == 0x06) + if (etd->tp_dev && (packet[3] & 0x0f) == 0x06) return PACKET_TRACKPOINT; /* diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 2a7a9174c702..f9472920d986 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -143,6 +143,10 @@ static const struct min_max_quirk min_max_pnpid_table[] = { (const char * const []){"LEN2001", NULL}, 1024, 5022, 2508, 4832 }, + { + (const char * const []){"LEN2006", NULL}, + 1264, 5675, 1171, 4688 + }, { } }; diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c index 6ae3cdee0681..cc4f9d80122e 100644 --- a/drivers/irqchip/irq-atmel-aic-common.c +++ b/drivers/irqchip/irq-atmel-aic-common.c @@ -217,8 +217,9 @@ struct irq_domain *__init aic_common_of_init(struct device_node *node, } ret = irq_alloc_domain_generic_chips(domain, 32, 1, name, - handle_level_irq, 0, 0, - IRQCHIP_SKIP_SET_WAKE); + handle_fasteoi_irq, + IRQ_NOREQUEST | IRQ_NOPROBE | + IRQ_NOAUTOEN, 0, 0); if (ret) goto err_domain_remove; @@ -230,7 +231,6 @@ struct irq_domain *__init aic_common_of_init(struct device_node *node, gc->unused = 0; gc->wake_enabled = ~0; gc->chip_types[0].type = IRQ_TYPE_SENSE_MASK; - gc->chip_types[0].handler = handle_fasteoi_irq; gc->chip_types[0].chip.irq_eoi = irq_gc_eoi; gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake; gc->chip_types[0].chip.irq_shutdown = aic_common_shutdown; diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c index b9f4fb808e49..5fb38a2ac226 100644 --- a/drivers/irqchip/irq-bcm7120-l2.c +++ b/drivers/irqchip/irq-bcm7120-l2.c @@ -101,9 +101,9 @@ static int bcm7120_l2_intc_init_one(struct device_node *dn, int parent_irq; parent_irq = irq_of_parse_and_map(dn, irq); - if (parent_irq < 0) { + if (!parent_irq) { pr_err("failed to map interrupt %d\n", irq); - return parent_irq; + return -EINVAL; } data->irq_map_mask |= be32_to_cpup(map_mask + irq); diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c index c15c840987d2..14691a4cb84c 100644 --- a/drivers/irqchip/irq-brcmstb-l2.c +++ b/drivers/irqchip/irq-brcmstb-l2.c @@ -135,9 +135,9 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np, __raw_writel(0xffffffff, data->base + CPU_CLEAR); data->parent_irq = irq_of_parse_and_map(np, 0); - if (data->parent_irq < 0) { + if (!data->parent_irq) { pr_err("failed to find parent interrupt\n"); - ret = data->parent_irq; + ret = -EINVAL; goto out_unmap; } diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index b4518c8751c8..868e6fc17cba 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -12,25 +12,23 @@ */ #include <linux/err.h> #include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/kernel.h> #include <linux/leds.h> #include <linux/module.h> -#include <linux/of.h> -#include <linux/of_gpio.h> -#include <linux/of_platform.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/slab.h> #include <linux/workqueue.h> struct gpio_led_data { struct led_classdev cdev; - unsigned gpio; + struct gpio_desc *gpiod; struct work_struct work; u8 new_level; u8 can_sleep; - u8 active_low; u8 blinking; - int (*platform_gpio_blink_set)(unsigned gpio, int state, + int (*platform_gpio_blink_set)(struct gpio_desc *desc, int state, unsigned long *delay_on, unsigned long *delay_off); }; @@ -40,12 +38,11 @@ static void gpio_led_work(struct work_struct *work) container_of(work, struct gpio_led_data, work); if (led_dat->blinking) { - led_dat->platform_gpio_blink_set(led_dat->gpio, - led_dat->new_level, - NULL, NULL); + led_dat->platform_gpio_blink_set(led_dat->gpiod, + led_dat->new_level, NULL, NULL); led_dat->blinking = 0; } else - gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level); + gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level); } static void gpio_led_set(struct led_classdev *led_cdev, @@ -60,9 +57,6 @@ static void gpio_led_set(struct led_classdev *led_cdev, else level = 1; - if (led_dat->active_low) - level = !level; - /* Setting GPIOs with I2C/etc requires a task context, and we don't * seem to have a reliable way to know if we're already in one; so * let's just assume the worst. @@ -72,11 +66,11 @@ static void gpio_led_set(struct led_classdev *led_cdev, schedule_work(&led_dat->work); } else { if (led_dat->blinking) { - led_dat->platform_gpio_blink_set(led_dat->gpio, level, + led_dat->platform_gpio_blink_set(led_dat->gpiod, level, NULL, NULL); led_dat->blinking = 0; } else - gpio_set_value(led_dat->gpio, level); + gpiod_set_value(led_dat->gpiod, level); } } @@ -87,34 +81,49 @@ static int gpio_blink_set(struct led_classdev *led_cdev, container_of(led_cdev, struct gpio_led_data, cdev); led_dat->blinking = 1; - return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK, + return led_dat->platform_gpio_blink_set(led_dat->gpiod, GPIO_LED_BLINK, delay_on, delay_off); } static int create_gpio_led(const struct gpio_led *template, struct gpio_led_data *led_dat, struct device *parent, - int (*blink_set)(unsigned, int, unsigned long *, unsigned long *)) + int (*blink_set)(struct gpio_desc *, int, unsigned long *, + unsigned long *)) { int ret, state; - led_dat->gpio = -1; + led_dat->gpiod = template->gpiod; + if (!led_dat->gpiod) { + /* + * This is the legacy code path for platform code that + * still uses GPIO numbers. Ultimately we would like to get + * rid of this block completely. + */ + unsigned long flags = 0; + + /* skip leds that aren't available */ + if (!gpio_is_valid(template->gpio)) { + dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n", + template->gpio, template->name); + return 0; + } - /* skip leds that aren't available */ - if (!gpio_is_valid(template->gpio)) { - dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n", - template->gpio, template->name); - return 0; - } + if (template->active_low) + flags |= GPIOF_ACTIVE_LOW; - ret = devm_gpio_request(parent, template->gpio, template->name); - if (ret < 0) - return ret; + ret = devm_gpio_request_one(parent, template->gpio, flags, + template->name); + if (ret < 0) + return ret; + + led_dat->gpiod = gpio_to_desc(template->gpio); + if (IS_ERR(led_dat->gpiod)) + return PTR_ERR(led_dat->gpiod); + } led_dat->cdev.name = template->name; led_dat->cdev.default_trigger = template->default_trigger; - led_dat->gpio = template->gpio; - led_dat->can_sleep = gpio_cansleep(template->gpio); - led_dat->active_low = template->active_low; + led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod); led_dat->blinking = 0; if (blink_set) { led_dat->platform_gpio_blink_set = blink_set; @@ -122,30 +131,24 @@ static int create_gpio_led(const struct gpio_led *template, } led_dat->cdev.brightness_set = gpio_led_set; if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) - state = !!gpio_get_value_cansleep(led_dat->gpio) ^ led_dat->active_low; + state = !!gpiod_get_value_cansleep(led_dat->gpiod); else state = (template->default_state == LEDS_GPIO_DEFSTATE_ON); led_dat->cdev.brightness = state ? LED_FULL : LED_OFF; if (!template->retain_state_suspended) led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; - ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state); + ret = gpiod_direction_output(led_dat->gpiod, state); if (ret < 0) return ret; INIT_WORK(&led_dat->work, gpio_led_work); - ret = led_classdev_register(parent, &led_dat->cdev); - if (ret < 0) - return ret; - - return 0; + return led_classdev_register(parent, &led_dat->cdev); } static void delete_gpio_led(struct gpio_led_data *led) { - if (!gpio_is_valid(led->gpio)) - return; led_classdev_unregister(&led->cdev); cancel_work_sync(&led->work); } @@ -161,40 +164,47 @@ static inline int sizeof_gpio_leds_priv(int num_leds) (sizeof(struct gpio_led_data) * num_leds); } -/* Code to create from OpenFirmware platform devices */ -#ifdef CONFIG_OF_GPIO -static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev) +static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node, *child; + struct device *dev = &pdev->dev; + struct fwnode_handle *child; struct gpio_leds_priv *priv; int count, ret; + struct device_node *np; - /* count LEDs in this device, so we know how much to allocate */ - count = of_get_available_child_count(np); + count = device_get_child_node_count(dev); if (!count) return ERR_PTR(-ENODEV); - for_each_available_child_of_node(np, child) - if (of_get_gpio(child, 0) == -EPROBE_DEFER) - return ERR_PTR(-EPROBE_DEFER); - - priv = devm_kzalloc(&pdev->dev, sizeof_gpio_leds_priv(count), - GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof_gpio_leds_priv(count), GFP_KERNEL); if (!priv) return ERR_PTR(-ENOMEM); - for_each_available_child_of_node(np, child) { + device_for_each_child_node(dev, child) { struct gpio_led led = {}; - enum of_gpio_flags flags; - const char *state; - - led.gpio = of_get_gpio_flags(child, 0, &flags); - led.active_low = flags & OF_GPIO_ACTIVE_LOW; - led.name = of_get_property(child, "label", NULL) ? : child->name; - led.default_trigger = - of_get_property(child, "linux,default-trigger", NULL); - state = of_get_property(child, "default-state", NULL); - if (state) { + const char *state = NULL; + + led.gpiod = devm_get_gpiod_from_child(dev, child); + if (IS_ERR(led.gpiod)) { + fwnode_handle_put(child); + goto err; + } + + np = of_node(child); + + if (fwnode_property_present(child, "label")) { + fwnode_property_read_string(child, "label", &led.name); + } else { + if (IS_ENABLED(CONFIG_OF) && !led.name && np) + led.name = np->name; + if (!led.name) + return ERR_PTR(-EINVAL); + } + fwnode_property_read_string(child, "linux,default-trigger", + &led.default_trigger); + + if (!fwnode_property_read_string(child, "linux,default_state", + &state)) { if (!strcmp(state, "keep")) led.default_state = LEDS_GPIO_DEFSTATE_KEEP; else if (!strcmp(state, "on")) @@ -203,13 +213,13 @@ static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev) led.default_state = LEDS_GPIO_DEFSTATE_OFF; } - if (of_get_property(child, "retain-state-suspended", NULL)) + if (fwnode_property_present(child, "retain-state-suspended")) led.retain_state_suspended = 1; ret = create_gpio_led(&led, &priv->leds[priv->num_leds++], - &pdev->dev, NULL); + dev, NULL); if (ret < 0) { - of_node_put(child); + fwnode_handle_put(child); goto err; } } @@ -228,12 +238,6 @@ static const struct of_device_id of_gpio_leds_match[] = { }; MODULE_DEVICE_TABLE(of, of_gpio_leds_match); -#else /* CONFIG_OF_GPIO */ -static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev) -{ - return ERR_PTR(-ENODEV); -} -#endif /* CONFIG_OF_GPIO */ static int gpio_led_probe(struct platform_device *pdev) { @@ -261,7 +265,7 @@ static int gpio_led_probe(struct platform_device *pdev) } } } else { - priv = gpio_leds_create_of(pdev); + priv = gpio_leds_create(pdev); if (IS_ERR(priv)) return PTR_ERR(priv); } @@ -288,7 +292,7 @@ static struct platform_driver gpio_led_driver = { .driver = { .name = "leds-gpio", .owner = THIS_MODULE, - .of_match_table = of_match_ptr(of_gpio_leds_match), + .of_match_table = of_gpio_leds_match, }, }; diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 932ed9be9ff3..b10aaeda2bb4 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2190,7 +2190,7 @@ static int smiapp_set_selection(struct v4l2_subdev *subdev, ret = smiapp_set_compose(subdev, fh, sel); break; default: - BUG(); + ret = -EINVAL; } mutex_unlock(&sensor->mutex); diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c index 331eddac7222..3bd386c371f7 100644 --- a/drivers/media/pci/cx23885/cx23885-core.c +++ b/drivers/media/pci/cx23885/cx23885-core.c @@ -1078,7 +1078,7 @@ static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist, for (line = 0; line < lines; line++) { while (offset && offset >= sg_dma_len(sg)) { offset -= sg_dma_len(sg); - sg++; + sg = sg_next(sg); } if (lpi && line > 0 && !(line % lpi)) @@ -1101,14 +1101,14 @@ static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist, *(rp++) = cpu_to_le32(0); /* bits 63-32 */ todo -= (sg_dma_len(sg)-offset); offset = 0; - sg++; + sg = sg_next(sg); while (todo > sg_dma_len(sg)) { *(rp++) = cpu_to_le32(RISC_WRITE| sg_dma_len(sg)); *(rp++) = cpu_to_le32(sg_dma_address(sg)); *(rp++) = cpu_to_le32(0); /* bits 63-32 */ todo -= sg_dma_len(sg); - sg++; + sg = sg_next(sg); } *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo); *(rp++) = cpu_to_le32(sg_dma_address(sg)); diff --git a/drivers/media/pci/solo6x10/solo6x10-core.c b/drivers/media/pci/solo6x10/solo6x10-core.c index 172583d736fe..8cbe6b49f4c2 100644 --- a/drivers/media/pci/solo6x10/solo6x10-core.c +++ b/drivers/media/pci/solo6x10/solo6x10-core.c @@ -105,11 +105,8 @@ static irqreturn_t solo_isr(int irq, void *data) if (!status) return IRQ_NONE; - if (status & ~solo_dev->irq_mask) { - solo_reg_write(solo_dev, SOLO_IRQ_STAT, - status & ~solo_dev->irq_mask); - status &= solo_dev->irq_mask; - } + /* Acknowledge all interrupts immediately */ + solo_reg_write(solo_dev, SOLO_IRQ_STAT, status); if (status & SOLO_IRQ_PCI_ERR) solo_p2m_error_isr(solo_dev); @@ -132,9 +129,6 @@ static irqreturn_t solo_isr(int irq, void *data) if (status & SOLO_IRQ_G723) solo_g723_isr(solo_dev); - /* Clear all interrupts handled */ - solo_reg_write(solo_dev, SOLO_IRQ_STAT, status); - return IRQ_HANDLED; } diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c index f1f098e22f7e..d16bc67af732 100644 --- a/drivers/media/rc/ir-rc6-decoder.c +++ b/drivers/media/rc/ir-rc6-decoder.c @@ -259,8 +259,8 @@ again: case 32: if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) { protocol = RC_TYPE_RC6_MCE; - scancode &= ~RC6_6A_MCE_TOGGLE_MASK; toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); + scancode &= ~RC6_6A_MCE_TOGGLE_MASK; } else { protocol = RC_BIT_RC6_6A_32; toggle = 0; diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index ccc00099b261..1c0dbf428a3a 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -632,7 +632,7 @@ static void s2255_fillbuff(struct s2255_vc *vc, break; case V4L2_PIX_FMT_JPEG: case V4L2_PIX_FMT_MJPEG: - buf->vb.v4l2_buf.length = jpgsize; + vb2_set_plane_payload(&buf->vb, 0, jpgsize); memcpy(vbuf, tmpbuf, jpgsize); break; case V4L2_PIX_FMT_YUV422P: diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index 634f72929e12..0a1af93ec638 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -18,7 +18,7 @@ #include <linux/spi/spi.h> #include <linux/spi/eeprom.h> -#include <linux/of.h> +#include <linux/property.h> /* * NOTE: this is an *EEPROM* driver. The vagaries of product naming @@ -301,35 +301,33 @@ static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf, /*-------------------------------------------------------------------------*/ -static int at25_np_to_chip(struct device *dev, - struct device_node *np, - struct spi_eeprom *chip) +static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip) { u32 val; memset(chip, 0, sizeof(*chip)); - strncpy(chip->name, np->name, sizeof(chip->name)); + strncpy(chip->name, "at25", sizeof(chip->name)); - if (of_property_read_u32(np, "size", &val) == 0 || - of_property_read_u32(np, "at25,byte-len", &val) == 0) { + if (device_property_read_u32(dev, "size", &val) == 0 || + device_property_read_u32(dev, "at25,byte-len", &val) == 0) { chip->byte_len = val; } else { dev_err(dev, "Error: missing \"size\" property\n"); return -ENODEV; } - if (of_property_read_u32(np, "pagesize", &val) == 0 || - of_property_read_u32(np, "at25,page-size", &val) == 0) { + if (device_property_read_u32(dev, "pagesize", &val) == 0 || + device_property_read_u32(dev, "at25,page-size", &val) == 0) { chip->page_size = (u16)val; } else { dev_err(dev, "Error: missing \"pagesize\" property\n"); return -ENODEV; } - if (of_property_read_u32(np, "at25,addr-mode", &val) == 0) { + if (device_property_read_u32(dev, "at25,addr-mode", &val) == 0) { chip->flags = (u16)val; } else { - if (of_property_read_u32(np, "address-width", &val)) { + if (device_property_read_u32(dev, "address-width", &val)) { dev_err(dev, "Error: missing \"address-width\" property\n"); return -ENODEV; @@ -350,7 +348,7 @@ static int at25_np_to_chip(struct device *dev, val); return -ENODEV; } - if (of_find_property(np, "read-only", NULL)) + if (device_property_present(dev, "read-only")) chip->flags |= EE_READONLY; } return 0; @@ -360,21 +358,15 @@ static int at25_probe(struct spi_device *spi) { struct at25_data *at25 = NULL; struct spi_eeprom chip; - struct device_node *np = spi->dev.of_node; int err; int sr; int addrlen; /* Chip description */ if (!spi->dev.platform_data) { - if (np) { - err = at25_np_to_chip(&spi->dev, np, &chip); - if (err) - return err; - } else { - dev_err(&spi->dev, "Error: no chip description\n"); - return -ENODEV; - } + err = at25_fw_to_chip(&spi->dev, &chip); + if (err) + return err; } else chip = *(struct spi_eeprom *)spi->dev.platform_data; diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index c13d83e15ace..45f09a66e6c9 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -225,7 +225,12 @@ static int bond_changelink(struct net_device *bond_dev, bond_option_arp_ip_targets_clear(bond); nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) { - __be32 target = nla_get_be32(attr); + __be32 target; + + if (nla_len(attr) < sizeof(target)) + return -EINVAL; + + target = nla_get_be32(attr); bond_opt_initval(&newval, (__force u64)target); err = __bond_opt_set(bond, BOND_OPT_ARP_TARGETS, diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index b9625968daac..4f4c2a7888e5 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -377,6 +377,29 @@ static irqreturn_t bcm_sf2_switch_1_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv) +{ + unsigned int timeout = 1000; + u32 reg; + + reg = core_readl(priv, CORE_WATCHDOG_CTRL); + reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET; + core_writel(priv, reg, CORE_WATCHDOG_CTRL); + + do { + reg = core_readl(priv, CORE_WATCHDOG_CTRL); + if (!(reg & SOFTWARE_RESET)) + break; + + usleep_range(1000, 2000); + } while (timeout-- > 0); + + if (timeout == 0) + return -ETIMEDOUT; + + return 0; +} + static int bcm_sf2_sw_setup(struct dsa_switch *ds) { const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME; @@ -404,11 +427,18 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) *base = of_iomap(dn, i); if (*base == NULL) { pr_err("unable to find register: %s\n", reg_names[i]); - return -ENODEV; + ret = -ENOMEM; + goto out_unmap; } base++; } + ret = bcm_sf2_sw_rst(priv); + if (ret) { + pr_err("unable to software reset switch: %d\n", ret); + goto out_unmap; + } + /* Disable all interrupts and request them */ intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET); intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR); @@ -484,7 +514,8 @@ out_free_irq0: out_unmap: base = &priv->core; for (i = 0; i < BCM_SF2_REGS_NUM; i++) { - iounmap(*base); + if (*base) + iounmap(*base); base++; } return ret; @@ -733,29 +764,6 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds) return 0; } -static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv) -{ - unsigned int timeout = 1000; - u32 reg; - - reg = core_readl(priv, CORE_WATCHDOG_CTRL); - reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET; - core_writel(priv, reg, CORE_WATCHDOG_CTRL); - - do { - reg = core_readl(priv, CORE_WATCHDOG_CTRL); - if (!(reg & SOFTWARE_RESET)) - break; - - usleep_range(1000, 2000); - } while (timeout-- > 0); - - if (timeout == 0) - return -ETIMEDOUT; - - return 0; -} - static int bcm_sf2_sw_resume(struct dsa_switch *ds) { struct bcm_sf2_priv *priv = ds_to_priv(ds); diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index dbb41c1923e6..77f8f836cbbe 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -8563,7 +8563,8 @@ static int tg3_init_rings(struct tg3 *tp) if (tnapi->rx_rcb) memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); - if (tg3_rx_prodring_alloc(tp, &tnapi->prodring)) { + if (tnapi->prodring.rx_std && + tg3_rx_prodring_alloc(tp, &tnapi->prodring)) { tg3_free_rings(tp); return -ENOMEM; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 8520d5529df8..279873cb6e3a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -2442,9 +2442,13 @@ static unsigned int from_fw_linkcaps(unsigned int type, unsigned int caps) SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full | SUPPORTED_10000baseKX4_Full; else if (type == FW_PORT_TYPE_FIBER_XFI || - type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP) + type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP) { v |= SUPPORTED_FIBRE; - else if (type == FW_PORT_TYPE_BP40_BA) + if (caps & FW_PORT_CAP_SPEED_1G) + v |= SUPPORTED_1000baseT_Full; + if (caps & FW_PORT_CAP_SPEED_10G) + v |= SUPPORTED_10000baseT_Full; + } else if (type == FW_PORT_TYPE_BP40_BA) v |= SUPPORTED_40000baseSR4_Full; if (caps & FW_PORT_CAP_ANEG) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 3e8475cae4f9..597c463e384d 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4309,11 +4309,16 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh) return -EOPNOTSUPP; br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); + if (!br_spec) + return -EINVAL; nla_for_each_nested(attr, br_spec, rem) { if (nla_type(attr) != IFLA_BRIDGE_MODE) continue; + if (nla_len(attr) < sizeof(mode)) + return -EINVAL; + mode = nla_get_u16(attr); if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB) return -EINVAL; diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index a2d72a87cbde..487cd9c4ac0d 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -1012,7 +1012,8 @@ static void igb_free_q_vector(struct igb_adapter *adapter, int v_idx) /* igb_get_stats64() might access the rings on this vector, * we must wait a grace period before freeing it. */ - kfree_rcu(q_vector, rcu); + if (q_vector) + kfree_rcu(q_vector, rcu); } /** @@ -1792,8 +1793,10 @@ void igb_down(struct igb_adapter *adapter) adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; for (i = 0; i < adapter->num_q_vectors; i++) { - napi_synchronize(&(adapter->q_vector[i]->napi)); - napi_disable(&(adapter->q_vector[i]->napi)); + if (adapter->q_vector[i]) { + napi_synchronize(&adapter->q_vector[i]->napi); + napi_disable(&adapter->q_vector[i]->napi); + } } @@ -3717,7 +3720,8 @@ static void igb_free_all_tx_resources(struct igb_adapter *adapter) int i; for (i = 0; i < adapter->num_tx_queues; i++) - igb_free_tx_resources(adapter->tx_ring[i]); + if (adapter->tx_ring[i]) + igb_free_tx_resources(adapter->tx_ring[i]); } void igb_unmap_and_free_tx_resource(struct igb_ring *ring, @@ -3782,7 +3786,8 @@ static void igb_clean_all_tx_rings(struct igb_adapter *adapter) int i; for (i = 0; i < adapter->num_tx_queues; i++) - igb_clean_tx_ring(adapter->tx_ring[i]); + if (adapter->tx_ring[i]) + igb_clean_tx_ring(adapter->tx_ring[i]); } /** @@ -3819,7 +3824,8 @@ static void igb_free_all_rx_resources(struct igb_adapter *adapter) int i; for (i = 0; i < adapter->num_rx_queues; i++) - igb_free_rx_resources(adapter->rx_ring[i]); + if (adapter->rx_ring[i]) + igb_free_rx_resources(adapter->rx_ring[i]); } /** @@ -3874,7 +3880,8 @@ static void igb_clean_all_rx_rings(struct igb_adapter *adapter) int i; for (i = 0; i < adapter->num_rx_queues; i++) - igb_clean_rx_ring(adapter->rx_ring[i]); + if (adapter->rx_ring[i]) + igb_clean_rx_ring(adapter->rx_ring[i]); } /** @@ -7404,6 +7411,8 @@ static int igb_resume(struct device *dev) pci_restore_state(pdev); pci_save_state(pdev); + if (!pci_device_is_present(pdev)) + return -ENODEV; err = pci_enable_device_mem(pdev); if (err) { dev_err(&pdev->dev, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index d2df4e3d1032..cc51554c9e99 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3936,8 +3936,8 @@ void ixgbe_set_rx_mode(struct net_device *netdev) * if SR-IOV and VMDQ are disabled - otherwise ensure * that hardware VLAN filters remain enabled. */ - if (!(adapter->flags & (IXGBE_FLAG_VMDQ_ENABLED | - IXGBE_FLAG_SRIOV_ENABLED))) + if (adapter->flags & (IXGBE_FLAG_VMDQ_ENABLED | + IXGBE_FLAG_SRIOV_ENABLED)) vlnctrl |= (IXGBE_VLNCTRL_VFE | IXGBE_VLNCTRL_CFIEN); } else { if (netdev->flags & IFF_ALLMULTI) { @@ -7669,6 +7669,8 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev, return -EOPNOTSUPP; br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); + if (!br_spec) + return -EINVAL; nla_for_each_nested(attr, br_spec, rem) { __u16 mode; @@ -7677,6 +7679,9 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev, if (nla_type(attr) != IFLA_BRIDGE_MODE) continue; + if (nla_len(attr) < sizeof(mode)) + return -EINVAL; + mode = nla_get_u16(attr); if (mode == BRIDGE_MODE_VEPA) { reg = 0; @@ -7979,6 +7984,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int i, err, pci_using_dac, expected_gts; unsigned int indices = MAX_TX_QUEUES; u8 part_str[IXGBE_PBANUM_LENGTH]; + bool disable_dev = false; #ifdef IXGBE_FCOE u16 device_caps; #endif @@ -8369,13 +8375,14 @@ err_sw_init: iounmap(adapter->io_addr); kfree(adapter->mac_table); err_ioremap: + disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state); free_netdev(netdev); err_alloc_etherdev: pci_release_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM)); err_pci_reg: err_dma: - if (!adapter || !test_and_set_bit(__IXGBE_DISABLED, &adapter->state)) + if (!adapter || disable_dev) pci_disable_device(pdev); return err; } @@ -8393,6 +8400,7 @@ static void ixgbe_remove(struct pci_dev *pdev) { struct ixgbe_adapter *adapter = pci_get_drvdata(pdev); struct net_device *netdev = adapter->netdev; + bool disable_dev; ixgbe_dbg_adapter_exit(adapter); @@ -8442,11 +8450,12 @@ static void ixgbe_remove(struct pci_dev *pdev) e_dev_info("complete\n"); kfree(adapter->mac_table); + disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state); free_netdev(netdev); pci_disable_pcie_error_reporting(pdev); - if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state)) + if (disable_dev) pci_disable_device(pdev); } diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 5d2498dcf536..cd5cf6d957c7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -1546,7 +1546,7 @@ static int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, switch (op) { case RES_OP_RESERVE: - count = get_param_l(&in_param); + count = get_param_l(&in_param) & 0xffffff; align = get_param_h(&in_param); err = mlx4_grant_resource(dev, slave, RES_QP, count, 0); if (err) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 60e9c2cd051e..b5db6b3f939f 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -917,21 +917,13 @@ static int sh_eth_reset(struct net_device *ndev) return ret; } -#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) static void sh_eth_set_receive_align(struct sk_buff *skb) { - int reserve; + uintptr_t reserve = (uintptr_t)skb->data & (SH_ETH_RX_ALIGN - 1); - reserve = SH4_SKB_RX_ALIGN - ((u32)skb->data & (SH4_SKB_RX_ALIGN - 1)); if (reserve) - skb_reserve(skb, reserve); + skb_reserve(skb, SH_ETH_RX_ALIGN - reserve); } -#else -static void sh_eth_set_receive_align(struct sk_buff *skb) -{ - skb_reserve(skb, SH2_SH3_SKB_RX_ALIGN); -} -#endif /* CPU <-> EDMAC endian convert */ @@ -1119,6 +1111,7 @@ static void sh_eth_ring_format(struct net_device *ndev) struct sh_eth_txdesc *txdesc = NULL; int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring; int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring; + int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1; mdp->cur_rx = 0; mdp->cur_tx = 0; @@ -1131,21 +1124,21 @@ static void sh_eth_ring_format(struct net_device *ndev) for (i = 0; i < mdp->num_rx_ring; i++) { /* skb */ mdp->rx_skbuff[i] = NULL; - skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz); + skb = netdev_alloc_skb(ndev, skbuff_size); mdp->rx_skbuff[i] = skb; if (skb == NULL) break; - dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz, - DMA_FROM_DEVICE); sh_eth_set_receive_align(skb); /* RX descriptor */ rxdesc = &mdp->rx_ring[i]; + /* The size of the buffer is a multiple of 16 bytes. */ + rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); + dma_map_single(&ndev->dev, skb->data, rxdesc->buffer_length, + DMA_FROM_DEVICE); rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4)); rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP); - /* The size of the buffer is 16 byte boundary. */ - rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); /* Rx descriptor address set */ if (i == 0) { sh_eth_write(ndev, mdp->rx_desc_dma, RDLAR); @@ -1397,6 +1390,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) struct sk_buff *skb; u16 pkt_len = 0; u32 desc_status; + int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1; rxdesc = &mdp->rx_ring[entry]; while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) { @@ -1448,7 +1442,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) if (mdp->cd->rpadir) skb_reserve(skb, NET_IP_ALIGN); dma_sync_single_for_cpu(&ndev->dev, rxdesc->addr, - mdp->rx_buf_sz, + ALIGN(mdp->rx_buf_sz, 16), DMA_FROM_DEVICE); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, ndev); @@ -1468,13 +1462,13 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); if (mdp->rx_skbuff[entry] == NULL) { - skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz); + skb = netdev_alloc_skb(ndev, skbuff_size); mdp->rx_skbuff[entry] = skb; if (skb == NULL) break; /* Better luck next round. */ - dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz, - DMA_FROM_DEVICE); sh_eth_set_receive_align(skb); + dma_map_single(&ndev->dev, skb->data, + rxdesc->buffer_length, DMA_FROM_DEVICE); skb_checksum_none_assert(skb); rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4)); @@ -2042,6 +2036,8 @@ static int sh_eth_open(struct net_device *ndev) if (ret) goto out_free_irq; + mdp->is_opened = 1; + return ret; out_free_irq: @@ -2131,6 +2127,36 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_OK; } +static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + + if (sh_eth_is_rz_fast_ether(mdp)) + return &ndev->stats; + + if (!mdp->is_opened) + return &ndev->stats; + + ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR); + sh_eth_write(ndev, 0, TROCR); /* (write clear) */ + ndev->stats.collisions += sh_eth_read(ndev, CDCR); + sh_eth_write(ndev, 0, CDCR); /* (write clear) */ + ndev->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR); + sh_eth_write(ndev, 0, LCCR); /* (write clear) */ + + if (sh_eth_is_gether(mdp)) { + ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR); + sh_eth_write(ndev, 0, CERCR); /* (write clear) */ + ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR); + sh_eth_write(ndev, 0, CEECR); /* (write clear) */ + } else { + ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR); + sh_eth_write(ndev, 0, CNDCR); /* (write clear) */ + } + + return &ndev->stats; +} + /* device close function */ static int sh_eth_close(struct net_device *ndev) { @@ -2145,6 +2171,7 @@ static int sh_eth_close(struct net_device *ndev) sh_eth_write(ndev, 0, EDTRR); sh_eth_write(ndev, 0, EDRRR); + sh_eth_get_stats(ndev); /* PHY Disconnect */ if (mdp->phydev) { phy_stop(mdp->phydev); @@ -2163,36 +2190,9 @@ static int sh_eth_close(struct net_device *ndev) pm_runtime_put_sync(&mdp->pdev->dev); - return 0; -} - -static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev) -{ - struct sh_eth_private *mdp = netdev_priv(ndev); - - if (sh_eth_is_rz_fast_ether(mdp)) - return &ndev->stats; + mdp->is_opened = 0; - pm_runtime_get_sync(&mdp->pdev->dev); - - ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR); - sh_eth_write(ndev, 0, TROCR); /* (write clear) */ - ndev->stats.collisions += sh_eth_read(ndev, CDCR); - sh_eth_write(ndev, 0, CDCR); /* (write clear) */ - ndev->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR); - sh_eth_write(ndev, 0, LCCR); /* (write clear) */ - if (sh_eth_is_gether(mdp)) { - ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR); - sh_eth_write(ndev, 0, CERCR); /* (write clear) */ - ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR); - sh_eth_write(ndev, 0, CEECR); /* (write clear) */ - } else { - ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR); - sh_eth_write(ndev, 0, CNDCR); /* (write clear) */ - } - pm_runtime_put_sync(&mdp->pdev->dev); - - return &ndev->stats; + return 0; } /* ioctl to device function */ diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index b37c427144ee..22301bf9c21d 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -162,9 +162,9 @@ enum { /* Driver's parameters */ #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) -#define SH4_SKB_RX_ALIGN 32 +#define SH_ETH_RX_ALIGN 32 #else -#define SH2_SH3_SKB_RX_ALIGN 2 +#define SH_ETH_RX_ALIGN 2 #endif /* Register's bits @@ -522,6 +522,7 @@ struct sh_eth_private { unsigned no_ether_link:1; unsigned ether_link_active_low:1; + unsigned is_opened:1; }; static inline void sh_eth_soft_swap(char *src, int len) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index db56fa7ce8f9..58a1a0a423d4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -177,12 +177,6 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, */ plat->maxmtu = JUMBO_LEN; - /* Set default value for multicast hash bins */ - plat->multicast_filter_bins = HASH_TABLE_SIZE; - - /* Set default value for unicast filter entries */ - plat->unicast_filter_entries = 1; - /* * Currently only the properties needed on SPEAr600 * are provided. All other properties should be added @@ -270,16 +264,23 @@ static int stmmac_pltfr_probe(struct platform_device *pdev) return PTR_ERR(addr); plat_dat = dev_get_platdata(&pdev->dev); - if (pdev->dev.of_node) { - if (!plat_dat) - plat_dat = devm_kzalloc(&pdev->dev, + + if (!plat_dat) + plat_dat = devm_kzalloc(&pdev->dev, sizeof(struct plat_stmmacenet_data), GFP_KERNEL); - if (!plat_dat) { - pr_err("%s: ERROR: no memory", __func__); - return -ENOMEM; - } + if (!plat_dat) { + pr_err("%s: ERROR: no memory", __func__); + return -ENOMEM; + } + + /* Set default value for multicast hash bins */ + plat_dat->multicast_filter_bins = HASH_TABLE_SIZE; + /* Set default value for unicast filter entries */ + plat_dat->unicast_filter_entries = 1; + + if (pdev->dev.of_node) { ret = stmmac_probe_config_dt(pdev, plat_dat, &mac); if (ret) { pr_err("%s: main dt probe failed", __func__); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index e1e335c339e3..be4649a49c5e 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2306,9 +2306,9 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6, if (ipv6) { udp_conf.family = AF_INET6; udp_conf.use_udp6_tx_checksums = - !!(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); + !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); udp_conf.use_udp6_rx_checksums = - !!(flags & VXLAN_F_UDP_ZERO_CSUM6_RX); + !(flags & VXLAN_F_UDP_ZERO_CSUM6_RX); } else { udp_conf.family = AF_INET; udp_conf.local_ip.s_addr = INADDR_ANY; diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index 4f6e66892acc..b894a84e8393 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h @@ -155,6 +155,7 @@ enum iwl_ucode_tlv_api { * @IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT: supports Quiet Period requests * @IWL_UCODE_TLV_CAPA_DQA_SUPPORT: supports dynamic queue allocation (DQA), * which also implies support for the scheduler configuration command + * @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command */ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0), @@ -163,6 +164,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT = BIT(10), IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT = BIT(11), IWL_UCODE_TLV_CAPA_DQA_SUPPORT = BIT(12), + IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT = BIT(18), }; /* The default calibrate table size if not specified by firmware file */ diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index b62405865b25..b6d2683da3a9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -2448,9 +2448,15 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, switch (vif->type) { case NL80211_IFTYPE_STATION: - /* Use aux roc framework (HS20) */ - ret = iwl_mvm_send_aux_roc_cmd(mvm, channel, - vif, duration); + if (mvm->fw->ucode_capa.capa[0] & + IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT) { + /* Use aux roc framework (HS20) */ + ret = iwl_mvm_send_aux_roc_cmd(mvm, channel, + vif, duration); + goto out_unlock; + } + IWL_ERR(mvm, "hotspot not supported\n"); + ret = -EINVAL; goto out_unlock; case NL80211_IFTYPE_P2P_DEVICE: /* handle below */ diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 61f5d36eca6a..846a2e6e34d8 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -2249,6 +2249,16 @@ int rtl_pci_probe(struct pci_dev *pdev, /*like read eeprom and so on */ rtlpriv->cfg->ops->read_eeprom_info(hw); + if (rtlpriv->cfg->ops->init_sw_vars(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n"); + err = -ENODEV; + goto fail3; + } + rtlpriv->cfg->ops->init_sw_leds(hw); + + /*aspm */ + rtl_pci_init_aspm(hw); + /* Init mac80211 sw */ err = rtl_init_core(hw); if (err) { @@ -2264,16 +2274,6 @@ int rtl_pci_probe(struct pci_dev *pdev, goto fail3; } - if (rtlpriv->cfg->ops->init_sw_vars(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n"); - err = -ENODEV; - goto fail3; - } - rtlpriv->cfg->ops->init_sw_leds(hw); - - /*aspm */ - rtl_pci_init_aspm(hw); - err = ieee80211_register_hw(hw); if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c index 310d3163dc5b..8ec8200002c7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c @@ -3672,8 +3672,9 @@ static void rtl8821ae_update_hal_rate_mask(struct ieee80211_hw *hw, mac->opmode == NL80211_IFTYPE_ADHOC) macid = sta->aid + 1; if (wirelessmode == WIRELESS_MODE_N_5G || - wirelessmode == WIRELESS_MODE_AC_5G) - ratr_bitmap = sta->supp_rates[NL80211_BAND_5GHZ]; + wirelessmode == WIRELESS_MODE_AC_5G || + wirelessmode == WIRELESS_MODE_A) + ratr_bitmap = sta->supp_rates[NL80211_BAND_5GHZ] << 4; else ratr_bitmap = sta->supp_rates[NL80211_BAND_2GHZ]; diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 4e56a27f9689..fab0d4b42f58 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -39,7 +39,7 @@ struct backend_info { static int connect_rings(struct backend_info *be, struct xenvif_queue *queue); static void connect(struct backend_info *be); static int read_xenbus_vif_flags(struct backend_info *be); -static void backend_create_xenvif(struct backend_info *be); +static int backend_create_xenvif(struct backend_info *be); static void unregister_hotplug_status_watch(struct backend_info *be); static void set_backend_state(struct backend_info *be, enum xenbus_state state); @@ -352,7 +352,9 @@ static int netback_probe(struct xenbus_device *dev, be->state = XenbusStateInitWait; /* This kicks hotplug scripts, so do it immediately. */ - backend_create_xenvif(be); + err = backend_create_xenvif(be); + if (err) + goto fail; return 0; @@ -397,19 +399,19 @@ static int netback_uevent(struct xenbus_device *xdev, } -static void backend_create_xenvif(struct backend_info *be) +static int backend_create_xenvif(struct backend_info *be) { int err; long handle; struct xenbus_device *dev = be->dev; if (be->vif != NULL) - return; + return 0; err = xenbus_scanf(XBT_NIL, dev->nodename, "handle", "%li", &handle); if (err != 1) { xenbus_dev_fatal(dev, err, "reading handle"); - return; + return (err < 0) ? err : -EINVAL; } be->vif = xenvif_alloc(&dev->dev, dev->otherend_id, handle); @@ -417,10 +419,11 @@ static void backend_create_xenvif(struct backend_info *be) err = PTR_ERR(be->vif); be->vif = NULL; xenbus_dev_fatal(dev, err, "creating interface"); - return; + return err; } kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE); + return 0; } static void backend_disconnect(struct backend_info *be) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index cca871346a0f..ece8d1804d13 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -496,9 +496,6 @@ static void xennet_make_frags(struct sk_buff *skb, struct netfront_queue *queue, len = skb_frag_size(frag); offset = frag->page_offset; - /* Data must not cross a page boundary. */ - BUG_ON(len + offset > PAGE_SIZE<<compound_order(page)); - /* Skip unused frames from start of page */ page += offset >> PAGE_SHIFT; offset &= ~PAGE_MASK; @@ -506,8 +503,6 @@ static void xennet_make_frags(struct sk_buff *skb, struct netfront_queue *queue, while (len > 0) { unsigned long bytes; - BUG_ON(offset >= PAGE_SIZE); - bytes = PAGE_SIZE - offset; if (bytes > len) bytes = len; diff --git a/drivers/of/base.c b/drivers/of/base.c index 3823edf2d012..4c2ccde42427 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1250,6 +1250,39 @@ int of_property_read_u64(const struct device_node *np, const char *propname, EXPORT_SYMBOL_GPL(of_property_read_u64); /** + * of_property_read_u64_array - Find and read an array of 64 bit integers + * from a property. + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @out_values: pointer to return value, modified only if return value is 0. + * @sz: number of array elements to read + * + * Search for a property in a device node and read 64-bit value(s) from + * it. Returns 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + * The out_values is modified only if a valid u64 value can be decoded. + */ +int of_property_read_u64_array(const struct device_node *np, + const char *propname, u64 *out_values, + size_t sz) +{ + const __be32 *val = of_find_property_value_of_size(np, propname, + (sz * sizeof(*out_values))); + + if (IS_ERR(val)) + return PTR_ERR(val); + + while (sz--) { + *out_values++ = of_read_number(val, 2); + val += 2; + } + return 0; +} + +/** * of_property_read_string - Find and read a string from a property * @np: device node from which the property value is to be read. * @propname: name of the property to be searched. diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 30e97bcc4f88..d134710de96d 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -964,8 +964,6 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, bool nomap) { - if (memblock_is_region_reserved(base, size)) - return -EBUSY; if (nomap) return memblock_remove(base, size); return memblock_reserve(base, size); diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 3d43874319be..19bb19c7db4a 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -276,6 +276,7 @@ struct tegra_pcie { struct resource all; struct resource io; + struct resource pio; struct resource mem; struct resource prefetch; struct resource busn; @@ -658,7 +659,6 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) { struct tegra_pcie *pcie = sys_to_pcie(sys); int err; - phys_addr_t io_start; err = devm_request_resource(pcie->dev, &pcie->all, &pcie->mem); if (err < 0) @@ -668,14 +668,12 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) if (err) return err; - io_start = pci_pio_to_address(pcie->io.start); - pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); pci_add_resource_offset(&sys->resources, &pcie->prefetch, sys->mem_offset); pci_add_resource(&sys->resources, &pcie->busn); - pci_ioremap_io(nr * SZ_64K, io_start); + pci_ioremap_io(pcie->pio.start, pcie->io.start); return 1; } @@ -786,7 +784,6 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg) static void tegra_pcie_setup_translations(struct tegra_pcie *pcie) { u32 fpci_bar, size, axi_address; - phys_addr_t io_start = pci_pio_to_address(pcie->io.start); /* Bar 0: type 1 extended configuration space */ fpci_bar = 0xfe100000; @@ -799,7 +796,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie) /* Bar 1: downstream IO bar */ fpci_bar = 0xfdfc0000; size = resource_size(&pcie->io); - axi_address = io_start; + axi_address = pcie->io.start; afi_writel(pcie, axi_address, AFI_AXI_BAR1_START); afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ); afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1); @@ -1690,8 +1687,23 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) switch (res.flags & IORESOURCE_TYPE_BITS) { case IORESOURCE_IO: - memcpy(&pcie->io, &res, sizeof(res)); - pcie->io.name = np->full_name; + memcpy(&pcie->pio, &res, sizeof(res)); + pcie->pio.name = np->full_name; + + /* + * The Tegra PCIe host bridge uses this to program the + * mapping of the I/O space to the physical address, + * so we override the .start and .end fields here that + * of_pci_range_to_resource() converted to I/O space. + * We also set the IORESOURCE_MEM type to clarify that + * the resource is in the physical memory space. + */ + pcie->io.start = range.cpu_addr; + pcie->io.end = range.cpu_addr + range.size - 1; + pcie->io.flags = IORESOURCE_MEM; + pcie->io.name = "I/O"; + + memcpy(&res, &pcie->io, sizeof(res)); break; case IORESOURCE_MEM: diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 9fab30af0e75..084587d7cd13 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -590,6 +590,20 @@ static struct msi_desc *msi_setup_entry(struct pci_dev *dev) return entry; } +static int msi_verify_entries(struct pci_dev *dev) +{ + struct msi_desc *entry; + + list_for_each_entry(entry, &dev->msi_list, list) { + if (!dev->no_64bit_msi || !entry->msg.address_hi) + continue; + dev_err(&dev->dev, "Device has broken 64-bit MSI but arch" + " tried to assign one above 4G\n"); + return -EIO; + } + return 0; +} + /** * msi_capability_init - configure device's MSI capability structure * @dev: pointer to the pci_dev data structure of MSI device function @@ -627,6 +641,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) return ret; } + ret = msi_verify_entries(dev); + if (ret) { + msi_mask_irq(entry, mask, ~mask); + free_msi_irqs(dev); + return ret; + } + ret = populate_msi_sysfs(dev); if (ret) { msi_mask_irq(entry, mask, ~mask); @@ -739,6 +760,11 @@ static int msix_capability_init(struct pci_dev *dev, if (ret) goto out_avail; + /* Check if all MSI entries honor device restrictions */ + ret = msi_verify_entries(dev); + if (ret) + goto out_free; + /* * Some devices require MSI-X to be enabled before we can touch the * MSI-X registers. We need to mask all the vectors to prevent diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 79e5c94107a9..72533c58c1f3 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -412,6 +412,7 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, struct fc_frame_header *fh; struct fcoe_rcv_info *fr; struct fcoe_percpu_s *bg; + struct sk_buff *tmp_skb; unsigned short oxid; interface = container_of(ptype, struct bnx2fc_interface, @@ -424,6 +425,12 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, goto err; } + tmp_skb = skb_share_check(skb, GFP_ATOMIC); + if (!tmp_skb) + goto err; + + skb = tmp_skb; + if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) { printk(KERN_ERR PFX "bnx2fc_rcv: Wrong FC type frame\n"); goto err; diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 49014a143c6a..c1d04d4d3c6c 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -202,6 +202,7 @@ static struct { {"IOMEGA", "Io20S *F", NULL, BLIST_KEY}, {"INSITE", "Floptical F*8I", NULL, BLIST_KEY}, {"INSITE", "I325VM", NULL, BLIST_KEY}, + {"Intel", "Multi-Flex", NULL, BLIST_NO_RSOC}, {"iRiver", "iFP Mass Driver", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36}, {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN}, {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index 8adf067ff019..1c3467b82566 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -102,7 +102,6 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) clkfreq = devm_kzalloc(dev, sz * sizeof(*clkfreq), GFP_KERNEL); if (!clkfreq) { - dev_err(dev, "%s: no memory\n", "freq-table-hz"); ret = -ENOMEM; goto out; } @@ -112,19 +111,19 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) if (ret && (ret != -EINVAL)) { dev_err(dev, "%s: error reading array %d\n", "freq-table-hz", ret); - goto free_clkfreq; + return ret; } for (i = 0; i < sz; i += 2) { ret = of_property_read_string_index(np, "clock-names", i/2, (const char **)&name); if (ret) - goto free_clkfreq; + goto out; clki = devm_kzalloc(dev, sizeof(*clki), GFP_KERNEL); if (!clki) { ret = -ENOMEM; - goto free_clkfreq; + goto out; } clki->min_freq = clkfreq[i]; @@ -134,8 +133,6 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) clki->min_freq, clki->max_freq, clki->name); list_add_tail(&clki->list, &hba->clk_list_head); } -free_clkfreq: - kfree(clkfreq); out: return ret; } @@ -162,10 +159,8 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name, } vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL); - if (!vreg) { - dev_err(dev, "No memory for %s regulator\n", name); - goto out; - } + if (!vreg) + return -ENOMEM; vreg->name = kstrdup(name, GFP_KERNEL); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 497c38a4a866..605ca60e8a10 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -744,6 +744,8 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba) if (!ufshcd_is_clkgating_allowed(hba)) return; device_remove_file(hba->dev, &hba->clk_gating.delay_attr); + cancel_work_sync(&hba->clk_gating.ungate_work); + cancel_delayed_work_sync(&hba->clk_gating.gate_work); } /* Must be called with host lock acquired */ @@ -2246,6 +2248,22 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba) return ret; } + /** + * ufshcd_init_pwr_info - setting the POR (power on reset) + * values in hba power info + * @hba: per-adapter instance + */ +static void ufshcd_init_pwr_info(struct ufs_hba *hba) +{ + hba->pwr_info.gear_rx = UFS_PWM_G1; + hba->pwr_info.gear_tx = UFS_PWM_G1; + hba->pwr_info.lane_rx = 1; + hba->pwr_info.lane_tx = 1; + hba->pwr_info.pwr_rx = SLOWAUTO_MODE; + hba->pwr_info.pwr_tx = SLOWAUTO_MODE; + hba->pwr_info.hs_rate = 0; +} + /** * ufshcd_get_max_pwr_mode - reads the max power mode negotiated with device * @hba: per-adapter instance @@ -2844,8 +2862,13 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev) hba = shost_priv(sdev->host); scsi_deactivate_tcq(sdev, hba->nutrs); /* Drop the reference as it won't be needed anymore */ - if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN) + if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN) { + unsigned long flags; + + spin_lock_irqsave(hba->host->host_lock, flags); hba->sdev_ufs_device = NULL; + spin_unlock_irqrestore(hba->host->host_lock, flags); + } } /** @@ -4062,6 +4085,8 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba) static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) { int ret = 0; + struct scsi_device *sdev_rpmb; + struct scsi_device *sdev_boot; hba->sdev_ufs_device = __scsi_add_device(hba->host, 0, 0, ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_UFS_DEVICE_WLUN), NULL); @@ -4070,26 +4095,27 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) hba->sdev_ufs_device = NULL; goto out; } + scsi_device_put(hba->sdev_ufs_device); - hba->sdev_boot = __scsi_add_device(hba->host, 0, 0, + sdev_boot = __scsi_add_device(hba->host, 0, 0, ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); - if (IS_ERR(hba->sdev_boot)) { - ret = PTR_ERR(hba->sdev_boot); - hba->sdev_boot = NULL; + if (IS_ERR(sdev_boot)) { + ret = PTR_ERR(sdev_boot); goto remove_sdev_ufs_device; } + scsi_device_put(sdev_boot); - hba->sdev_rpmb = __scsi_add_device(hba->host, 0, 0, + sdev_rpmb = __scsi_add_device(hba->host, 0, 0, ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL); - if (IS_ERR(hba->sdev_rpmb)) { - ret = PTR_ERR(hba->sdev_rpmb); - hba->sdev_rpmb = NULL; + if (IS_ERR(sdev_rpmb)) { + ret = PTR_ERR(sdev_rpmb); goto remove_sdev_boot; } + scsi_device_put(sdev_rpmb); goto out; remove_sdev_boot: - scsi_remove_device(hba->sdev_boot); + scsi_remove_device(sdev_boot); remove_sdev_ufs_device: scsi_remove_device(hba->sdev_ufs_device); out: @@ -4097,30 +4123,6 @@ out: } /** - * ufshcd_scsi_remove_wlus - Removes the W-LUs which were added by - * ufshcd_scsi_add_wlus() - * @hba: per-adapter instance - * - */ -static void ufshcd_scsi_remove_wlus(struct ufs_hba *hba) -{ - if (hba->sdev_ufs_device) { - scsi_remove_device(hba->sdev_ufs_device); - hba->sdev_ufs_device = NULL; - } - - if (hba->sdev_boot) { - scsi_remove_device(hba->sdev_boot); - hba->sdev_boot = NULL; - } - - if (hba->sdev_rpmb) { - scsi_remove_device(hba->sdev_rpmb); - hba->sdev_rpmb = NULL; - } -} - -/** * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance * @@ -4134,6 +4136,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) if (ret) goto out; + ufshcd_init_pwr_info(hba); + /* UniPro link is active now */ ufshcd_set_link_active(hba); @@ -4264,12 +4268,18 @@ static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg, static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba, struct ufs_vreg *vreg) { + if (!vreg) + return 0; + return ufshcd_config_vreg_load(hba->dev, vreg, UFS_VREG_LPM_LOAD_UA); } static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba, struct ufs_vreg *vreg) { + if (!vreg) + return 0; + return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA); } @@ -4471,7 +4481,7 @@ out: if (!IS_ERR_OR_NULL(clki->clk) && clki->enabled) clk_disable_unprepare(clki->clk); } - } else if (!ret && on) { + } else if (on) { spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_gating.state = CLKS_ON; spin_unlock_irqrestore(hba->host->host_lock, flags); @@ -4675,11 +4685,25 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, { unsigned char cmd[6] = { START_STOP }; struct scsi_sense_hdr sshdr; - struct scsi_device *sdp = hba->sdev_ufs_device; + struct scsi_device *sdp; + unsigned long flags; int ret; - if (!sdp || !scsi_device_online(sdp)) - return -ENODEV; + spin_lock_irqsave(hba->host->host_lock, flags); + sdp = hba->sdev_ufs_device; + if (sdp) { + ret = scsi_device_get(sdp); + if (!ret && !scsi_device_online(sdp)) { + ret = -ENODEV; + scsi_device_put(sdp); + } + } else { + ret = -ENODEV; + } + spin_unlock_irqrestore(hba->host->host_lock, flags); + + if (ret) + return ret; /* * If scsi commands fail, the scsi mid-layer schedules scsi error- @@ -4718,6 +4742,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, if (!ret) hba->curr_dev_pwr_mode = pwr_mode; out: + scsi_device_put(sdp); hba->host->eh_noresume = 0; return ret; } @@ -5087,7 +5112,7 @@ int ufshcd_system_suspend(struct ufs_hba *hba) int ret = 0; if (!hba || !hba->is_powered) - goto out; + return 0; if (pm_runtime_suspended(hba->dev)) { if (hba->rpm_lvl == hba->spm_lvl) @@ -5231,7 +5256,6 @@ EXPORT_SYMBOL(ufshcd_shutdown); void ufshcd_remove(struct ufs_hba *hba) { scsi_remove_host(hba->host); - ufshcd_scsi_remove_wlus(hba); /* disable interrupts */ ufshcd_disable_intr(hba, hba->intr_mask); ufshcd_hba_stop(hba); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 58ecdff5065c..4a574aa45855 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -392,8 +392,6 @@ struct ufs_hba { * "UFS device" W-LU. */ struct scsi_device *sdev_ufs_device; - struct scsi_device *sdev_rpmb; - struct scsi_device *sdev_boot; enum ufs_dev_pwr_mode curr_dev_pwr_mode; enum uic_link_state uic_link_state; diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 72e12bad14b9..d0d5542efc06 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -376,9 +376,6 @@ static void pump_transfers(unsigned long data) chip = dws->cur_chip; spi = message->spi; - if (unlikely(!chip->clk_div)) - chip->clk_div = dws->max_freq / chip->speed_hz; - if (message->state == ERROR_STATE) { message->status = -EIO; goto early_exit; @@ -419,7 +416,7 @@ static void pump_transfers(unsigned long data) if (transfer->speed_hz) { speed = chip->speed_hz; - if (transfer->speed_hz != speed) { + if ((transfer->speed_hz != speed) || (!chip->clk_div)) { speed = transfer->speed_hz; /* clk_div doesn't support odd number */ @@ -581,7 +578,6 @@ static int dw_spi_setup(struct spi_device *spi) dev_err(&spi->dev, "No max speed HZ parameter\n"); return -EINVAL; } - chip->speed_hz = spi->max_speed_hz; chip->tmode = 0; /* Tx & Rx */ /* Default SPI mode is SCPOL = 0, SCPH = 0 */ diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 39e2c0a55a28..f63de781c729 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -562,9 +562,9 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) sspi->word_width = DIV_ROUND_UP(bits_per_word, 8); txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) | - sspi->word_width; + (sspi->word_width >> 1); rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) | - sspi->word_width; + (sspi->word_width >> 1); if (!(spi->mode & SPI_CS_HIGH)) regval |= SIRFSOC_SPI_CS_IDLE_STAT; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index ebcb33df2eb2..50f20f243981 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -615,13 +615,13 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, sg_free_table(sgt); return -ENOMEM; } - sg_buf = page_address(vm_page) + - ((size_t)buf & ~PAGE_MASK); + sg_set_page(&sgt->sgl[i], vm_page, + min, offset_in_page(buf)); } else { sg_buf = buf; + sg_set_buf(&sgt->sgl[i], sg_buf, min); } - sg_set_buf(&sgt->sgl[i], sg_buf, min); buf += min; len -= min; diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index 9935e66935af..eddef9cd2e16 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -275,11 +275,11 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, if (check_fwstate(pmlmepriv, _FW_LINKED) == true) rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1); - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); + ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); if (ph2c == NULL) return _FAIL; - psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_KERNEL); + psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC); if (psurveyPara == NULL) { kfree(ph2c); return _FAIL; @@ -405,7 +405,7 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) else RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid)); - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); + pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); if (pcmd == NULL) { res = _FAIL; RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n")); @@ -755,13 +755,13 @@ u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter) u8 res = _SUCCESS; - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); + ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); if (ph2c == NULL) { res = _FAIL; goto exit; } - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL); + pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC); if (pdrvextra_cmd_parm == NULL) { kfree(ph2c); res = _FAIL; @@ -967,13 +967,13 @@ u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue) u8 res = _SUCCESS; if (enqueue) { - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); + ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); if (ph2c == NULL) { res = _FAIL; goto exit; } - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL); + pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC); if (pdrvextra_cmd_parm == NULL) { kfree(ph2c); res = _FAIL; @@ -1010,13 +1010,13 @@ u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time) u8 res = _SUCCESS; - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); + ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); if (ph2c == NULL) { res = _FAIL; goto exit; } - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL); + pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC); if (pdrvextra_cmd_parm == NULL) { kfree(ph2c); res = _FAIL; @@ -1088,13 +1088,13 @@ u8 rtw_ps_cmd(struct adapter *padapter) u8 res = _SUCCESS; - ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); + ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); if (ppscmd == NULL) { res = _FAIL; goto exit; } - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL); + pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC); if (pdrvextra_cmd_parm == NULL) { kfree(ppscmd); res = _FAIL; diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 5ba5099ec20d..70b1bc3e0e63 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -4241,12 +4241,12 @@ void report_survey_event(struct adapter *padapter, pcmdpriv = &padapter->cmdpriv; - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); + pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); if (pcmd_obj == NULL) return; cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = kzalloc(cmdsz, GFP_KERNEL); + pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); if (pevtcmd == NULL) { kfree(pcmd_obj); return; @@ -4339,12 +4339,12 @@ void report_join_res(struct adapter *padapter, int res) struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); + pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); if (pcmd_obj == NULL) return; cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = kzalloc(cmdsz, GFP_KERNEL); + pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); if (pevtcmd == NULL) { kfree(pcmd_obj); return; @@ -4854,11 +4854,11 @@ void survey_timer_hdl(void *function_context) pmlmeext->scan_abort = false;/* reset */ } - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); + ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); if (ph2c == NULL) goto exit_survey_timer_hdl; - psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_KERNEL); + psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC); if (psurveyPara == NULL) { kfree(ph2c); goto exit_survey_timer_hdl; diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 33ccbbbd8ed6..d300369977fa 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -935,7 +935,7 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) return true; } - bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_KERNEL); + bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC); subtype = GetFrameSubType(pframe) >> 4; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 407a318b09db..2f87150a21b7 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -47,6 +47,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = { {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */ {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */ {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */ + {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */ {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ {} /* Terminating entry */ }; diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 1ab0018271c5..ad09e51ffae4 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -50,15 +50,14 @@ struct cpufreq_cooling_device { unsigned int cpufreq_state; unsigned int cpufreq_val; struct cpumask allowed_cpus; + struct list_head node; }; static DEFINE_IDR(cpufreq_idr); static DEFINE_MUTEX(cooling_cpufreq_lock); static unsigned int cpufreq_dev_count; -/* notify_table passes value to the CPUFREQ_ADJUST callback function. */ -#define NOTIFY_INVALID NULL -static struct cpufreq_cooling_device *notify_device; +static LIST_HEAD(cpufreq_dev_list); /** * get_idr - function to get a unique id. @@ -287,15 +286,12 @@ static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device, cpufreq_device->cpufreq_state = cooling_state; cpufreq_device->cpufreq_val = clip_freq; - notify_device = cpufreq_device; for_each_cpu(cpuid, mask) { if (is_cpufreq_valid(cpuid)) cpufreq_update_policy(cpuid); } - notify_device = NOTIFY_INVALID; - return 0; } @@ -316,21 +312,28 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb, { struct cpufreq_policy *policy = data; unsigned long max_freq = 0; + struct cpufreq_cooling_device *cpufreq_dev; - if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID) + if (event != CPUFREQ_ADJUST) return 0; - if (cpumask_test_cpu(policy->cpu, ¬ify_device->allowed_cpus)) - max_freq = notify_device->cpufreq_val; - else - return 0; + mutex_lock(&cooling_cpufreq_lock); + list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) { + if (!cpumask_test_cpu(policy->cpu, + &cpufreq_dev->allowed_cpus)) + continue; + + if (!cpufreq_dev->cpufreq_val) + cpufreq_dev->cpufreq_val = get_cpu_frequency( + cpumask_any(&cpufreq_dev->allowed_cpus), + cpufreq_dev->cpufreq_state); - /* Never exceed user_policy.max */ - if (max_freq > policy->user_policy.max) - max_freq = policy->user_policy.max; + max_freq = cpufreq_dev->cpufreq_val; - if (policy->max != max_freq) - cpufreq_verify_within_limits(policy, 0, max_freq); + if (policy->max != max_freq) + cpufreq_verify_within_limits(policy, 0, max_freq); + } + mutex_unlock(&cooling_cpufreq_lock); return 0; } @@ -486,6 +489,7 @@ __cpufreq_cooling_register(struct device_node *np, cpufreq_register_notifier(&thermal_cpufreq_notifier_block, CPUFREQ_POLICY_NOTIFIER); cpufreq_dev_count++; + list_add(&cpufreq_dev->node, &cpufreq_dev_list); mutex_unlock(&cooling_cpufreq_lock); @@ -549,6 +553,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) cpufreq_dev = cdev->devdata; mutex_lock(&cooling_cpufreq_lock); + list_del(&cpufreq_dev->node); cpufreq_dev_count--; /* Unregister the notifier for the last cpufreq cooling device */ diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c index 3f5ad25ddca8..b6be572704a4 100644 --- a/drivers/thermal/samsung/exynos_thermal_common.c +++ b/drivers/thermal/samsung/exynos_thermal_common.c @@ -417,13 +417,10 @@ void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf) th_zone = sensor_conf->pzone_data; - if (th_zone->therm_dev) - thermal_zone_device_unregister(th_zone->therm_dev); + thermal_zone_device_unregister(th_zone->therm_dev); - for (i = 0; i < th_zone->cool_dev_size; i++) { - if (th_zone->cool_dev[i]) - cpufreq_cooling_unregister(th_zone->cool_dev[i]); - } + for (i = 0; i < th_zone->cool_dev_size; ++i) + cpufreq_cooling_unregister(th_zone->cool_dev[i]); dev_info(sensor_conf->dev, "Exynos: Kernel Thermal management unregistered\n"); diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c index 90163b384660..d1ec5804c0bb 100644 --- a/drivers/thermal/st/st_thermal.c +++ b/drivers/thermal/st/st_thermal.c @@ -275,6 +275,7 @@ int st_thermal_unregister(struct platform_device *pdev) } EXPORT_SYMBOL_GPL(st_thermal_unregister); +#ifdef CONFIG_PM_SLEEP static int st_thermal_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -305,6 +306,8 @@ static int st_thermal_resume(struct device *dev) return 0; } +#endif + SIMPLE_DEV_PM_OPS(st_thermal_pm_ops, st_thermal_suspend, st_thermal_resume); EXPORT_SYMBOL_GPL(st_thermal_pm_ops); diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 56982da4a9e9..bf355050eab6 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -240,32 +240,6 @@ static int of_platform_serial_remove(struct platform_device *ofdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int of_serial_suspend(struct device *dev) -{ - struct of_serial_info *info = dev_get_drvdata(dev); - - serial8250_suspend_port(info->line); - if (info->clk) - clk_disable_unprepare(info->clk); - - return 0; -} - -static int of_serial_resume(struct device *dev) -{ - struct of_serial_info *info = dev_get_drvdata(dev); - - if (info->clk) - clk_prepare_enable(info->clk); - - serial8250_resume_port(info->line); - - return 0; -} -#endif -static SIMPLE_DEV_PM_OPS(of_serial_pm_ops, of_serial_suspend, of_serial_resume); - /* * A few common types, add more as needed. */ @@ -297,7 +271,6 @@ static struct platform_driver of_platform_serial_driver = { .name = "of_serial", .owner = THIS_MODULE, .of_match_table = of_platform_serial_table, - .pm = &of_serial_pm_ops, }, .probe = of_platform_serial_probe, .remove = of_platform_serial_remove, diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 39b4081b632d..96fafed92b76 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -44,6 +44,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Creative SB Audigy 2 NX */ { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Microsoft Wireless Laser Mouse 6000 Receiver */ + { USB_DEVICE(0x045e, 0x00e1), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Microsoft LifeCam-VX700 v2.0 */ { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 711b23019d54..df38e7ef4976 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -791,6 +791,10 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, trb = dwc->ep0_trb; + r = next_request(&ep0->request_list); + if (!r) + return; + status = DWC3_TRB_SIZE_TRBSTS(trb->size); if (status == DWC3_TRBSTS_SETUP_PENDING) { dwc3_trace(trace_dwc3_ep0, "Setup Pending received"); @@ -801,10 +805,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, return; } - r = next_request(&ep0->request_list); - if (!r) - return; - ur = &r->request; length = trb->size & DWC3_TRB_SIZE_MASK; diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 696160d48ae8..388cfd83b6b6 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -22,7 +22,6 @@ #include <linux/slab.h> -#include <linux/device.h> #include <asm/unaligned.h> #include "xhci.h" @@ -1149,9 +1148,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) * including the USB 3.0 roothub, but only if CONFIG_PM_RUNTIME * is enabled, so also enable remote wake here. */ - if (hcd->self.root_hub->do_remote_wakeup - && device_may_wakeup(hcd->self.controller)) { - + if (hcd->self.root_hub->do_remote_wakeup) { if (t1 & PORT_CONNECT) { t2 |= PORT_WKOC_E | PORT_WKDISC_E; t2 &= ~PORT_WKCONN_E; diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 9a69b1f1b300..142b601f9563 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -281,7 +281,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) if (xhci->quirks & XHCI_COMP_MODE_QUIRK) pdev->no_d3cold = true; - return xhci_suspend(xhci); + return xhci_suspend(xhci, do_wakeup); } static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 3d78b0cd674b..646300cbe5f7 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -204,7 +204,15 @@ static int xhci_plat_suspend(struct device *dev) struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); - return xhci_suspend(xhci); + /* + * xhci_suspend() needs `do_wakeup` to know whether host is allowed + * to do wakeup during suspend. Since xhci_plat_suspend is currently + * only designed for system suspend, device_may_wakeup() is enough + * to dertermine whether host is allowed to do wakeup. Need to + * reconsider this when xhci_plat_suspend enlarges its scope, e.g., + * also applies to runtime suspend. + */ + return xhci_suspend(xhci, device_may_wakeup(dev)); } static int xhci_plat_resume(struct device *dev) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index bc6fcbc16f61..06433aec81d7 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1067,9 +1067,8 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id, false); xhci_ring_cmd_db(xhci); } else { - /* Clear our internal halted state and restart the ring(s) */ + /* Clear our internal halted state */ xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_HALTED; - ring_doorbell_for_active_rings(xhci, slot_id, ep_index); } } @@ -1823,22 +1822,13 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, ep->stopped_td = td; return 0; } else { - if (trb_comp_code == COMP_STALL) { - /* The transfer is completed from the driver's - * perspective, but we need to issue a set dequeue - * command for this stalled endpoint to move the dequeue - * pointer past the TD. We can't do that here because - * the halt condition must be cleared first. Let the - * USB class driver clear the stall later. - */ - ep->stopped_td = td; - ep->stopped_stream = ep_ring->stream_id; - } else if (xhci_requires_manual_halt_cleanup(xhci, - ep_ctx, trb_comp_code)) { - /* Other types of errors halt the endpoint, but the - * class driver doesn't call usb_reset_endpoint() unless - * the error is -EPIPE. Clear the halted status in the - * xHCI hardware manually. + if (trb_comp_code == COMP_STALL || + xhci_requires_manual_halt_cleanup(xhci, ep_ctx, + trb_comp_code)) { + /* Issue a reset endpoint command to clear the host side + * halt, followed by a set dequeue command to move the + * dequeue pointer past the TD. + * The class driver clears the device side halt later. */ xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index, ep_ring->stream_id, @@ -1958,9 +1948,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, else td->urb->actual_length = 0; - xhci_cleanup_halted_endpoint(xhci, - slot_id, ep_index, 0, td, event_trb); - return finish_td(xhci, td, event_trb, event, ep, status, true); + return finish_td(xhci, td, event_trb, event, ep, status, false); } /* * Did we transfer any data, despite the errors that might have @@ -2519,17 +2507,8 @@ cleanup: if (ret) { urb = td->urb; urb_priv = urb->hcpriv; - /* Leave the TD around for the reset endpoint function - * to use(but only if it's not a control endpoint, - * since we already queued the Set TR dequeue pointer - * command for stalled control endpoints). - */ - if (usb_endpoint_xfer_control(&urb->ep->desc) || - (trb_comp_code != COMP_STALL && - trb_comp_code != COMP_BABBLE)) - xhci_urb_free_priv(xhci, urb_priv); - else - kfree(urb_priv); + + xhci_urb_free_priv(xhci, urb_priv); usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb); if ((urb->actual_length != urb->transfer_buffer_length && diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 2a5d45b4cb15..033b46c470bd 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -35,6 +35,8 @@ #define DRIVER_AUTHOR "Sarah Sharp" #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver" +#define PORT_WAKE_BITS (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E) + /* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */ static int link_quirk; module_param(link_quirk, int, S_IRUGO | S_IWUSR); @@ -851,13 +853,47 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci) xhci_set_cmd_ring_deq(xhci); } +static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci) +{ + int port_index; + __le32 __iomem **port_array; + unsigned long flags; + u32 t1, t2; + + spin_lock_irqsave(&xhci->lock, flags); + + /* disble usb3 ports Wake bits*/ + port_index = xhci->num_usb3_ports; + port_array = xhci->usb3_ports; + while (port_index--) { + t1 = readl(port_array[port_index]); + t1 = xhci_port_state_to_neutral(t1); + t2 = t1 & ~PORT_WAKE_BITS; + if (t1 != t2) + writel(t2, port_array[port_index]); + } + + /* disble usb2 ports Wake bits*/ + port_index = xhci->num_usb2_ports; + port_array = xhci->usb2_ports; + while (port_index--) { + t1 = readl(port_array[port_index]); + t1 = xhci_port_state_to_neutral(t1); + t2 = t1 & ~PORT_WAKE_BITS; + if (t1 != t2) + writel(t2, port_array[port_index]); + } + + spin_unlock_irqrestore(&xhci->lock, flags); +} + /* * Stop HC (not bus-specific) * * This is called when the machine transition into S3/S4 mode. * */ -int xhci_suspend(struct xhci_hcd *xhci) +int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) { int rc = 0; unsigned int delay = XHCI_MAX_HALT_USEC; @@ -868,6 +904,10 @@ int xhci_suspend(struct xhci_hcd *xhci) xhci->shared_hcd->state != HC_STATE_SUSPENDED) return -EINVAL; + /* Clear root port wake on bits if wakeup not allowed. */ + if (!do_wakeup) + xhci_disable_port_wake_on_bits(xhci); + /* Don't poll the roothubs on bus suspend. */ xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); @@ -2912,68 +2952,33 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, } } -/* Deal with stalled endpoints. The core should have sent the control message - * to clear the halt condition. However, we need to make the xHCI hardware - * reset its sequence number, since a device will expect a sequence number of - * zero after the halt condition is cleared. +/* Called when clearing halted device. The core should have sent the control + * message to clear the device halt condition. The host side of the halt should + * already be cleared with a reset endpoint command issued when the STALL tx + * event was received. + * * Context: in_interrupt */ + void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) { struct xhci_hcd *xhci; - struct usb_device *udev; - unsigned int ep_index; - unsigned long flags; - int ret; - struct xhci_virt_ep *virt_ep; - struct xhci_command *command; xhci = hcd_to_xhci(hcd); - udev = (struct usb_device *) ep->hcpriv; - /* Called with a root hub endpoint (or an endpoint that wasn't added - * with xhci_add_endpoint() - */ - if (!ep->hcpriv) - return; - ep_index = xhci_get_endpoint_index(&ep->desc); - virt_ep = &xhci->devs[udev->slot_id]->eps[ep_index]; - if (!virt_ep->stopped_td) { - xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep, - "Endpoint 0x%x not halted, refusing to reset.", - ep->desc.bEndpointAddress); - return; - } - if (usb_endpoint_xfer_control(&ep->desc)) { - xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep, - "Control endpoint stall already handled."); - return; - } - command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC); - if (!command) - return; - - xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep, - "Queueing reset endpoint command"); - spin_lock_irqsave(&xhci->lock, flags); - ret = xhci_queue_reset_ep(xhci, command, udev->slot_id, ep_index); /* - * Can't change the ring dequeue pointer until it's transitioned to the - * stopped state, which is only upon a successful reset endpoint - * command. Better hope that last command worked! + * We might need to implement the config ep cmd in xhci 4.8.1 note: + * The Reset Endpoint Command may only be issued to endpoints in the + * Halted state. If software wishes reset the Data Toggle or Sequence + * Number of an endpoint that isn't in the Halted state, then software + * may issue a Configure Endpoint Command with the Drop and Add bits set + * for the target endpoint. that is in the Stopped state. */ - if (!ret) { - xhci_cleanup_stalled_ring(xhci, udev, ep_index); - kfree(virt_ep->stopped_td); - xhci_ring_cmd_db(xhci); - } - virt_ep->stopped_td = NULL; - virt_ep->stopped_stream = 0; - spin_unlock_irqrestore(&xhci->lock, flags); - if (ret) - xhci_warn(xhci, "FIXME allocate a new ring segment\n"); + /* For now just print debug to follow the situation */ + xhci_dbg(xhci, "Endpoint 0x%x ep reset callback called\n", + ep->desc.bEndpointAddress); } static int xhci_check_streams_endpoint(struct xhci_hcd *xhci, diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index df76d642e719..d745715a1e2f 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1746,7 +1746,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks); void xhci_init_driver(struct hc_driver *drv, int (*setup_fn)(struct usb_hcd *)); #ifdef CONFIG_PM -int xhci_suspend(struct xhci_hcd *xhci); +int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); int xhci_resume(struct xhci_hcd *xhci, bool hibernated); #else #define xhci_suspend NULL diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index cfd009dc4018..6c4eb3cf5efd 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -120,6 +120,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ + { USB_DEVICE(0x10C4, 0x8875) }, /* CEL MeshConnect USB Stick */ { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 0dad8ce5a609..1ebb351b9e9a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -470,6 +470,39 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_4701_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9300_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9301_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9302_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9303_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9304_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9305_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9306_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9307_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9308_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9309_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9310_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9311_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9312_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9313_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9314_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9315_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9316_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9317_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9318_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9319_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931F_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 6786b705ccf6..e52409c9be99 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -926,8 +926,8 @@ #define BAYER_CONTOUR_CABLE_PID 0x6001 /* - * The following are the values for the Matrix Orbital FTDI Range - * Anything in this range will use an FT232RL. + * Matrix Orbital Intelligent USB displays. + * http://www.matrixorbital.com */ #define MTXORB_VID 0x1B3D #define MTXORB_FTDI_RANGE_0100_PID 0x0100 @@ -1186,8 +1186,39 @@ #define MTXORB_FTDI_RANGE_01FD_PID 0x01FD #define MTXORB_FTDI_RANGE_01FE_PID 0x01FE #define MTXORB_FTDI_RANGE_01FF_PID 0x01FF - - +#define MTXORB_FTDI_RANGE_4701_PID 0x4701 +#define MTXORB_FTDI_RANGE_9300_PID 0x9300 +#define MTXORB_FTDI_RANGE_9301_PID 0x9301 +#define MTXORB_FTDI_RANGE_9302_PID 0x9302 +#define MTXORB_FTDI_RANGE_9303_PID 0x9303 +#define MTXORB_FTDI_RANGE_9304_PID 0x9304 +#define MTXORB_FTDI_RANGE_9305_PID 0x9305 +#define MTXORB_FTDI_RANGE_9306_PID 0x9306 +#define MTXORB_FTDI_RANGE_9307_PID 0x9307 +#define MTXORB_FTDI_RANGE_9308_PID 0x9308 +#define MTXORB_FTDI_RANGE_9309_PID 0x9309 +#define MTXORB_FTDI_RANGE_930A_PID 0x930A +#define MTXORB_FTDI_RANGE_930B_PID 0x930B +#define MTXORB_FTDI_RANGE_930C_PID 0x930C +#define MTXORB_FTDI_RANGE_930D_PID 0x930D +#define MTXORB_FTDI_RANGE_930E_PID 0x930E +#define MTXORB_FTDI_RANGE_930F_PID 0x930F +#define MTXORB_FTDI_RANGE_9310_PID 0x9310 +#define MTXORB_FTDI_RANGE_9311_PID 0x9311 +#define MTXORB_FTDI_RANGE_9312_PID 0x9312 +#define MTXORB_FTDI_RANGE_9313_PID 0x9313 +#define MTXORB_FTDI_RANGE_9314_PID 0x9314 +#define MTXORB_FTDI_RANGE_9315_PID 0x9315 +#define MTXORB_FTDI_RANGE_9316_PID 0x9316 +#define MTXORB_FTDI_RANGE_9317_PID 0x9317 +#define MTXORB_FTDI_RANGE_9318_PID 0x9318 +#define MTXORB_FTDI_RANGE_9319_PID 0x9319 +#define MTXORB_FTDI_RANGE_931A_PID 0x931A +#define MTXORB_FTDI_RANGE_931B_PID 0x931B +#define MTXORB_FTDI_RANGE_931C_PID 0x931C +#define MTXORB_FTDI_RANGE_931D_PID 0x931D +#define MTXORB_FTDI_RANGE_931E_PID 0x931E +#define MTXORB_FTDI_RANGE_931F_PID 0x931F /* * The Mobility Lab (TML) diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 93cb7cebda62..077c714f1285 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -311,24 +311,30 @@ static void usa26_indat_callback(struct urb *urb) if ((data[0] & 0x80) == 0) { /* no errors on individual bytes, only possible overrun err */ - if (data[0] & RXERROR_OVERRUN) - err = TTY_OVERRUN; - else - err = 0; + if (data[0] & RXERROR_OVERRUN) { + tty_insert_flip_char(&port->port, 0, + TTY_OVERRUN); + } for (i = 1; i < urb->actual_length ; ++i) - tty_insert_flip_char(&port->port, data[i], err); + tty_insert_flip_char(&port->port, data[i], + TTY_NORMAL); } else { /* some bytes had errors, every byte has status */ dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__); for (i = 0; i + 1 < urb->actual_length; i += 2) { - int stat = data[i], flag = 0; - if (stat & RXERROR_OVERRUN) - flag |= TTY_OVERRUN; - if (stat & RXERROR_FRAMING) - flag |= TTY_FRAME; - if (stat & RXERROR_PARITY) - flag |= TTY_PARITY; + int stat = data[i]; + int flag = TTY_NORMAL; + + if (stat & RXERROR_OVERRUN) { + tty_insert_flip_char(&port->port, 0, + TTY_OVERRUN); + } /* XXX should handle break (0x10) */ + if (stat & RXERROR_PARITY) + flag = TTY_PARITY; + else if (stat & RXERROR_FRAMING) + flag = TTY_FRAME; + tty_insert_flip_char(&port->port, data[i+1], flag); } @@ -649,14 +655,19 @@ static void usa49_indat_callback(struct urb *urb) } else { /* some bytes had errors, every byte has status */ for (i = 0; i + 1 < urb->actual_length; i += 2) { - int stat = data[i], flag = 0; - if (stat & RXERROR_OVERRUN) - flag |= TTY_OVERRUN; - if (stat & RXERROR_FRAMING) - flag |= TTY_FRAME; - if (stat & RXERROR_PARITY) - flag |= TTY_PARITY; + int stat = data[i]; + int flag = TTY_NORMAL; + + if (stat & RXERROR_OVERRUN) { + tty_insert_flip_char(&port->port, 0, + TTY_OVERRUN); + } /* XXX should handle break (0x10) */ + if (stat & RXERROR_PARITY) + flag = TTY_PARITY; + else if (stat & RXERROR_FRAMING) + flag = TTY_FRAME; + tty_insert_flip_char(&port->port, data[i+1], flag); } @@ -713,15 +724,19 @@ static void usa49wg_indat_callback(struct urb *urb) */ for (x = 0; x + 1 < len && i + 1 < urb->actual_length; x += 2) { - int stat = data[i], flag = 0; + int stat = data[i]; + int flag = TTY_NORMAL; - if (stat & RXERROR_OVERRUN) - flag |= TTY_OVERRUN; - if (stat & RXERROR_FRAMING) - flag |= TTY_FRAME; - if (stat & RXERROR_PARITY) - flag |= TTY_PARITY; + if (stat & RXERROR_OVERRUN) { + tty_insert_flip_char(&port->port, 0, + TTY_OVERRUN); + } /* XXX should handle break (0x10) */ + if (stat & RXERROR_PARITY) + flag = TTY_PARITY; + else if (stat & RXERROR_FRAMING) + flag = TTY_FRAME; + tty_insert_flip_char(&port->port, data[i+1], flag); i += 2; @@ -773,25 +788,31 @@ static void usa90_indat_callback(struct urb *urb) if ((data[0] & 0x80) == 0) { /* no errors on individual bytes, only possible overrun err*/ - if (data[0] & RXERROR_OVERRUN) - err = TTY_OVERRUN; - else - err = 0; + if (data[0] & RXERROR_OVERRUN) { + tty_insert_flip_char(&port->port, 0, + TTY_OVERRUN); + } for (i = 1; i < urb->actual_length ; ++i) tty_insert_flip_char(&port->port, - data[i], err); + data[i], TTY_NORMAL); } else { /* some bytes had errors, every byte has status */ dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__); for (i = 0; i + 1 < urb->actual_length; i += 2) { - int stat = data[i], flag = 0; - if (stat & RXERROR_OVERRUN) - flag |= TTY_OVERRUN; - if (stat & RXERROR_FRAMING) - flag |= TTY_FRAME; - if (stat & RXERROR_PARITY) - flag |= TTY_PARITY; + int stat = data[i]; + int flag = TTY_NORMAL; + + if (stat & RXERROR_OVERRUN) { + tty_insert_flip_char( + &port->port, 0, + TTY_OVERRUN); + } /* XXX should handle break (0x10) */ + if (stat & RXERROR_PARITY) + flag = TTY_PARITY; + else if (stat & RXERROR_FRAMING) + flag = TTY_FRAME; + tty_insert_flip_char(&port->port, data[i+1], flag); } diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index a7fe664b6b7d..70a098de429f 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -490,10 +490,9 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr, if (*tty_flag == TTY_NORMAL) *tty_flag = TTY_FRAME; } - if (lsr & UART_LSR_OE){ + if (lsr & UART_LSR_OE) { port->icount.overrun++; - if (*tty_flag == TTY_NORMAL) - *tty_flag = TTY_OVERRUN; + tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); } } @@ -511,12 +510,8 @@ static void ssu100_process_read_urb(struct urb *urb) if ((len >= 4) && (packet[0] == 0x1b) && (packet[1] == 0x1b) && ((packet[2] == 0x00) || (packet[2] == 0x01))) { - if (packet[2] == 0x00) { + if (packet[2] == 0x00) ssu100_update_lsr(port, packet[3], &flag); - if (flag == TTY_OVERRUN) - tty_insert_flip_char(&port->port, 0, - TTY_OVERRUN); - } if (packet[2] == 0x01) ssu100_update_msr(port, packet[3]); diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h index 2fefaf923e4a..18a283d6de1c 100644 --- a/drivers/usb/storage/unusual_uas.h +++ b/drivers/usb/storage/unusual_uas.h @@ -103,3 +103,10 @@ UNUSUAL_DEV(0x2109, 0x0711, 0x0000, 0x9999, "VL711", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_ATA_1X), + +/* Reported-by: Hans de Goede <hdegoede@redhat.com> */ +UNUSUAL_DEV(0x4971, 0x1012, 0x0000, 0x9999, + "Hitachi", + "External HDD", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_IGNORE_UAS), diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 8532c3e2aea7..1626dc66e763 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -161,7 +161,7 @@ static const struct s3c2410_wdt_variant drv_data_exynos5420 = { static const struct s3c2410_wdt_variant drv_data_exynos7 = { .disable_reg = EXYNOS5_WDT_DISABLE_REG_OFFSET, .mask_reset_reg = EXYNOS5_WDT_MASK_RESET_REG_OFFSET, - .mask_bit = 0, + .mask_bit = 23, .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET, .rst_stat_bit = 23, /* A57 WDTRESET */ .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT, |