diff options
Diffstat (limited to 'drivers')
1186 files changed, 23112 insertions, 12695 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 7b65a807b3dd..90ff0a47c12e 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -10,6 +10,7 @@ menuconfig ACPI bool "ACPI (Advanced Configuration and Power Interface) Support" depends on ARCH_SUPPORTS_ACPI select PNP + select NLS default y if X86 help Advanced Configuration and Power Interface (ACPI) support for diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 7c6afc111d76..bb857421c2e8 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -41,7 +41,8 @@ acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-$(CONFIG_PCI) += pci_root.o pci_link.o pci_irq.o obj-$(CONFIG_ACPI_MCFG) += pci_mcfg.o -acpi-y += acpi_lpss.o acpi_apd.o +acpi-$(CONFIG_PCI) += acpi_lpss.o +acpi-y += acpi_apd.o acpi-y += acpi_platform.o acpi-y += acpi_pnp.o acpi-$(CONFIG_ARM_AMBA) += acpi_amba.o diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index fdd90ffceb85..e48894e002ba 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -876,7 +876,7 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head) return (resv == its->its_count) ? resv : -ENODEV; } #else -static inline const struct iommu_ops *iort_fwspec_iommu_ops(struct device *dev); +static inline const struct iommu_ops *iort_fwspec_iommu_ops(struct device *dev) { return NULL; } static inline int iort_add_device_replay(const struct iommu_ops *ops, struct device *dev) @@ -952,9 +952,10 @@ static int rc_dma_get_range(struct device *dev, u64 *size) { struct acpi_iort_node *node; struct acpi_iort_root_complex *rc; + struct pci_bus *pbus = to_pci_dev(dev)->bus; node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX, - iort_match_node_callback, dev); + iort_match_node_callback, &pbus->dev); if (!node || node->revision < 1) return -ENODEV; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 99d820a693a8..147f6c7ea59c 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1029,6 +1029,9 @@ void __init acpi_early_init(void) acpi_permanent_mmap = true; + /* Initialize debug output. Linux does not use ACPICA defaults */ + acpi_dbg_level = ACPI_LV_INFO | ACPI_LV_REPAIR; + #ifdef CONFIG_X86 /* * If the machine falls into the DMI check table, @@ -1054,18 +1057,6 @@ void __init acpi_early_init(void) goto error0; } - /* - * ACPI 2.0 requires the EC driver to be loaded and work before - * the EC device is found in the namespace (i.e. before - * acpi_load_tables() is called). - * - * This is accomplished by looking for the ECDT table, and getting - * the EC parameters out of that. - * - * Ignore the result. Not having an ECDT is not fatal. - */ - status = acpi_ec_ecdt_probe(); - #ifdef CONFIG_X86 if (!acpi_ioapic) { /* compatible (0) means level (3) */ @@ -1142,6 +1133,18 @@ static int __init acpi_bus_init(void) goto error1; } + /* + * ACPI 2.0 requires the EC driver to be loaded and work before the EC + * device is found in the namespace. + * + * This is accomplished by looking for the ECDT table and getting the EC + * parameters out of that. + * + * Do that before calling acpi_initialize_objects() which may trigger EC + * address space accesses. + */ + acpi_ec_ecdt_probe(); + status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 7e6952edb5b0..6a9e1fb8913a 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -81,7 +81,11 @@ void acpi_debugfs_init(void); #else static inline void acpi_debugfs_init(void) { return; } #endif +#ifdef CONFIG_PCI void acpi_lpss_init(void); +#else +static inline void acpi_lpss_init(void) {} +#endif void acpi_apd_init(void); diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 011d3db19c80..e18ade5d74e9 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -26,7 +26,6 @@ #include <acpi/nfit.h> #include "intel.h" #include "nfit.h" -#include "intel.h" /* * For readq() and writeq() on 32-bit builds, the hi-lo, lo-hi order is @@ -78,12 +77,6 @@ const guid_t *to_nfit_uuid(enum nfit_uuids id) } EXPORT_SYMBOL(to_nfit_uuid); -static struct acpi_nfit_desc *to_acpi_nfit_desc( - struct nvdimm_bus_descriptor *nd_desc) -{ - return container_of(nd_desc, struct acpi_nfit_desc, nd_desc); -} - static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc) { struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc; @@ -416,10 +409,36 @@ static bool payload_dumpable(struct nvdimm *nvdimm, unsigned int func) return true; } +static int cmd_to_func(struct nfit_mem *nfit_mem, unsigned int cmd, + struct nd_cmd_pkg *call_pkg) +{ + if (call_pkg) { + int i; + + if (nfit_mem->family != call_pkg->nd_family) + return -ENOTTY; + + for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++) + if (call_pkg->nd_reserved2[i]) + return -EINVAL; + return call_pkg->nd_command; + } + + /* Linux ND commands == NVDIMM_FAMILY_INTEL function numbers */ + if (nfit_mem->family == NVDIMM_FAMILY_INTEL) + return cmd; + + /* + * Force function number validation to fail since 0 is never + * published as a valid function in dsm_mask. + */ + return 0; +} + int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc) { - struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc); + struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); union acpi_object in_obj, in_buf, *out_obj; const struct nd_cmd_desc *desc = NULL; @@ -429,30 +448,23 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, unsigned long cmd_mask, dsm_mask; u32 offset, fw_status = 0; acpi_handle handle; - unsigned int func; const guid_t *guid; - int rc, i; + int func, rc, i; if (cmd_rc) *cmd_rc = -EINVAL; - func = cmd; - if (cmd == ND_CMD_CALL) { - call_pkg = buf; - func = call_pkg->nd_command; - - for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++) - if (call_pkg->nd_reserved2[i]) - return -EINVAL; - } if (nvdimm) { struct acpi_device *adev = nfit_mem->adev; if (!adev) return -ENOTTY; - if (call_pkg && nfit_mem->family != call_pkg->nd_family) - return -ENOTTY; + if (cmd == ND_CMD_CALL) + call_pkg = buf; + func = cmd_to_func(nfit_mem, cmd, call_pkg); + if (func < 0) + return func; dimm_name = nvdimm_name(nvdimm); cmd_name = nvdimm_cmd_name(cmd); cmd_mask = nvdimm_cmd_mask(nvdimm); @@ -463,6 +475,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, } else { struct acpi_device *adev = to_acpi_dev(acpi_desc); + func = cmd; cmd_name = nvdimm_bus_cmd_name(cmd); cmd_mask = nd_desc->cmd_mask; dsm_mask = cmd_mask; @@ -477,7 +490,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, if (!desc || (cmd && (desc->out_num + desc->in_num == 0))) return -ENOTTY; - if (!test_bit(cmd, &cmd_mask) || !test_bit(func, &dsm_mask)) + /* + * Check for a valid command. For ND_CMD_CALL, we also have to + * make sure that the DSM function is supported. + */ + if (cmd == ND_CMD_CALL && !test_bit(func, &dsm_mask)) + return -ENOTTY; + else if (!test_bit(cmd, &cmd_mask)) return -ENOTTY; in_obj.type = ACPI_TYPE_PACKAGE; @@ -721,6 +740,7 @@ int nfit_get_smbios_id(u32 device_handle, u16 *flags) struct acpi_nfit_memory_map *memdev; struct acpi_nfit_desc *acpi_desc; struct nfit_mem *nfit_mem; + u16 physical_id; mutex_lock(&acpi_desc_lock); list_for_each_entry(acpi_desc, &acpi_descs, list) { @@ -728,10 +748,11 @@ int nfit_get_smbios_id(u32 device_handle, u16 *flags) list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) { memdev = __to_nfit_memdev(nfit_mem); if (memdev->device_handle == device_handle) { + *flags = memdev->flags; + physical_id = memdev->physical_id; mutex_unlock(&acpi_desc->init_mutex); mutex_unlock(&acpi_desc_lock); - *flags = memdev->flags; - return memdev->physical_id; + return physical_id; } } mutex_unlock(&acpi_desc->init_mutex); @@ -1872,6 +1893,13 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc, return 0; } + /* + * Function 0 is the command interrogation function, don't + * export it to potential userspace use, and enable it to be + * used as an error value in acpi_nfit_ctl(). + */ + dsm_mask &= ~1UL; + guid = to_nfit_uuid(nfit_mem->family); for_each_set_bit(i, &dsm_mask, BITS_PER_LONG) if (acpi_check_dsm(adev_dimm->handle, guid, @@ -2047,11 +2075,6 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc) if (!nvdimm) continue; - rc = nvdimm_security_setup_events(nvdimm); - if (rc < 0) - dev_warn(acpi_desc->dev, - "security event setup failed: %d\n", rc); - nfit_kernfs = sysfs_get_dirent(nvdimm_kobj(nvdimm)->sd, "nfit"); if (nfit_kernfs) nfit_mem->flags_attr = sysfs_get_dirent(nfit_kernfs, @@ -2231,7 +2254,6 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc, nd_set = devm_kzalloc(dev, sizeof(*nd_set), GFP_KERNEL); if (!nd_set) return -ENOMEM; - ndr_desc->nd_set = nd_set; guid_copy(&nd_set->type_guid, (guid_t *) spa->range_guid); info = devm_kzalloc(dev, sizeof_nfit_set_info(nr), GFP_KERNEL); @@ -3367,7 +3389,7 @@ EXPORT_SYMBOL_GPL(acpi_nfit_init); static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc) { - struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc); + struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); struct device *dev = acpi_desc->dev; /* Bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */ @@ -3384,7 +3406,7 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc) static int __acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, unsigned int cmd) { - struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc); + struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); if (nvdimm) return 0; diff --git a/drivers/acpi/nfit/intel.c b/drivers/acpi/nfit/intel.c index 850b2927b4e7..f70de71f79d6 100644 --- a/drivers/acpi/nfit/intel.c +++ b/drivers/acpi/nfit/intel.c @@ -146,7 +146,7 @@ static int intel_security_change_key(struct nvdimm *nvdimm, static void nvdimm_invalidate_cache(void); -static int intel_security_unlock(struct nvdimm *nvdimm, +static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm, const struct nvdimm_key_data *key_data) { struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); @@ -227,7 +227,7 @@ static int intel_security_disable(struct nvdimm *nvdimm, return 0; } -static int intel_security_erase(struct nvdimm *nvdimm, +static int __maybe_unused intel_security_erase(struct nvdimm *nvdimm, const struct nvdimm_key_data *key, enum nvdimm_passphrase_type ptype) { @@ -276,7 +276,7 @@ static int intel_security_erase(struct nvdimm *nvdimm, return 0; } -static int intel_security_query_overwrite(struct nvdimm *nvdimm) +static int __maybe_unused intel_security_query_overwrite(struct nvdimm *nvdimm) { int rc; struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); @@ -313,7 +313,7 @@ static int intel_security_query_overwrite(struct nvdimm *nvdimm) return 0; } -static int intel_security_overwrite(struct nvdimm *nvdimm, +static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm, const struct nvdimm_key_data *nkey) { int rc; diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 274699463b4f..7bbbf8256a41 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -146,9 +146,9 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) { struct acpi_srat_mem_affinity *p = (struct acpi_srat_mem_affinity *)header; - pr_debug("SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n", - (unsigned long)p->base_address, - (unsigned long)p->length, + pr_debug("SRAT Memory (0x%llx length 0x%llx) in proximity domain %d %s%s%s\n", + (unsigned long long)p->base_address, + (unsigned long long)p->length, p->proximity_domain, (p->flags & ACPI_SRAT_MEM_ENABLED) ? "enabled" : "disabled", diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c index 2579675b7082..e7c0006e6602 100644 --- a/drivers/acpi/pmic/intel_pmic_xpower.c +++ b/drivers/acpi/pmic/intel_pmic_xpower.c @@ -20,8 +20,11 @@ #define GPI1_LDO_ON (3 << 0) #define GPI1_LDO_OFF (4 << 0) -#define AXP288_ADC_TS_PIN_GPADC 0xf2 -#define AXP288_ADC_TS_PIN_ON 0xf3 +#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK GENMASK(1, 0) +#define AXP288_ADC_TS_CURRENT_OFF (0 << 0) +#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING (1 << 0) +#define AXP288_ADC_TS_CURRENT_ON_ONDEMAND (2 << 0) +#define AXP288_ADC_TS_CURRENT_ON (3 << 0) static struct pmic_table power_table[] = { { @@ -212,22 +215,44 @@ out: */ static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg) { + int ret, adc_ts_pin_ctrl; u8 buf[2]; - int ret; - ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, - AXP288_ADC_TS_PIN_GPADC); + /* + * The current-source used for the battery temp-sensor (TS) is shared + * with the GPADC. For proper fuel-gauge and charger operation the TS + * current-source needs to be permanently on. But to read the GPADC we + * need to temporary switch the TS current-source to ondemand, so that + * the GPADC can use it, otherwise we will always read an all 0 value. + * + * Note that the switching from on to on-ondemand is not necessary + * when the TS current-source is off (this happens on devices which + * do not use the TS-pin). + */ + ret = regmap_read(regmap, AXP288_ADC_TS_PIN_CTRL, &adc_ts_pin_ctrl); if (ret) return ret; - /* After switching to the GPADC pin give things some time to settle */ - usleep_range(6000, 10000); + if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) { + ret = regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL, + AXP288_ADC_TS_CURRENT_ON_OFF_MASK, + AXP288_ADC_TS_CURRENT_ON_ONDEMAND); + if (ret) + return ret; + + /* Wait a bit after switching the current-source */ + usleep_range(6000, 10000); + } ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2); if (ret == 0) ret = (buf[0] << 4) + ((buf[1] >> 4) & 0x0f); - regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON); + if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) { + regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL, + AXP288_ADC_TS_CURRENT_ON_OFF_MASK, + AXP288_ADC_TS_CURRENT_ON); + } return ret; } diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 1b475bc1ae16..665e93ca0b40 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -131,6 +131,23 @@ void acpi_power_resources_list_free(struct list_head *list) } } +static bool acpi_power_resource_is_dup(union acpi_object *package, + unsigned int start, unsigned int i) +{ + acpi_handle rhandle, dup; + unsigned int j; + + /* The caller is expected to check the package element types */ + rhandle = package->package.elements[i].reference.handle; + for (j = start; j < i; j++) { + dup = package->package.elements[j].reference.handle; + if (dup == rhandle) + return true; + } + + return false; +} + int acpi_extract_power_resources(union acpi_object *package, unsigned int start, struct list_head *list) { @@ -150,6 +167,11 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start, err = -ENODEV; break; } + + /* Some ACPI tables contain duplicate power resource references */ + if (acpi_power_resource_is_dup(package, start, i)) + continue; + err = acpi_add_power_resource(rhandle); if (err) break; diff --git a/drivers/android/binder.c b/drivers/android/binder.c index cdfc87629efb..4d2b2ad1ee0e 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -5854,9 +5854,10 @@ static int __init init_binder_device(const char *name) static int __init binder_init(void) { int ret; - char *device_name, *device_names, *device_tmp; + char *device_name, *device_tmp; struct binder_device *device; struct hlist_node *tmp; + char *device_names = NULL; ret = binder_alloc_shrinker_init(); if (ret) @@ -5898,23 +5899,29 @@ static int __init binder_init(void) &transaction_log_fops); } - /* - * Copy the module_parameter string, because we don't want to - * tokenize it in-place. - */ - device_names = kstrdup(binder_devices_param, GFP_KERNEL); - if (!device_names) { - ret = -ENOMEM; - goto err_alloc_device_names_failed; - } + if (strcmp(binder_devices_param, "") != 0) { + /* + * Copy the module_parameter string, because we don't want to + * tokenize it in-place. + */ + device_names = kstrdup(binder_devices_param, GFP_KERNEL); + if (!device_names) { + ret = -ENOMEM; + goto err_alloc_device_names_failed; + } - device_tmp = device_names; - while ((device_name = strsep(&device_tmp, ","))) { - ret = init_binder_device(device_name); - if (ret) - goto err_init_binder_device_failed; + device_tmp = device_names; + while ((device_name = strsep(&device_tmp, ","))) { + ret = init_binder_device(device_name); + if (ret) + goto err_init_binder_device_failed; + } } + ret = init_binderfs(); + if (ret) + goto err_init_binder_device_failed; + return ret; err_init_binder_device_failed: diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index 7fb97f503ef2..045b3e42d98b 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -46,4 +46,13 @@ static inline bool is_binderfs_device(const struct inode *inode) } #endif +#ifdef CONFIG_ANDROID_BINDERFS +extern int __init init_binderfs(void); +#else +static inline int __init init_binderfs(void) +{ + return 0; +} +#endif + #endif /* _LINUX_BINDER_INTERNAL_H */ diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c index 7496b10532aa..e773f45d19d9 100644 --- a/drivers/android/binderfs.c +++ b/drivers/android/binderfs.c @@ -11,6 +11,7 @@ #include <linux/kdev_t.h> #include <linux/kernel.h> #include <linux/list.h> +#include <linux/namei.h> #include <linux/magic.h> #include <linux/major.h> #include <linux/miscdevice.h> @@ -20,6 +21,7 @@ #include <linux/parser.h> #include <linux/radix-tree.h> #include <linux/sched.h> +#include <linux/seq_file.h> #include <linux/slab.h> #include <linux/spinlock_types.h> #include <linux/stddef.h> @@ -30,7 +32,7 @@ #include <linux/xarray.h> #include <uapi/asm-generic/errno-base.h> #include <uapi/linux/android/binder.h> -#include <uapi/linux/android/binder_ctl.h> +#include <uapi/linux/android/binderfs.h> #include "binder_internal.h" @@ -39,14 +41,32 @@ #define INODE_OFFSET 3 #define INTSTRLEN 21 #define BINDERFS_MAX_MINOR (1U << MINORBITS) - -static struct vfsmount *binderfs_mnt; +/* Ensure that the initial ipc namespace always has devices available. */ +#define BINDERFS_MAX_MINOR_CAPPED (BINDERFS_MAX_MINOR - 4) static dev_t binderfs_dev; static DEFINE_MUTEX(binderfs_minors_mutex); static DEFINE_IDA(binderfs_minors); /** + * binderfs_mount_opts - mount options for binderfs + * @max: maximum number of allocatable binderfs binder devices + */ +struct binderfs_mount_opts { + int max; +}; + +enum { + Opt_max, + Opt_err +}; + +static const match_table_t tokens = { + { Opt_max, "max=%d" }, + { Opt_err, NULL } +}; + +/** * binderfs_info - information about a binderfs mount * @ipc_ns: The ipc namespace the binderfs mount belongs to. * @control_dentry: This records the dentry of this binderfs mount @@ -55,13 +75,16 @@ static DEFINE_IDA(binderfs_minors); * created. * @root_gid: gid that needs to be used when a new binder device is * created. + * @mount_opts: The mount options in use. + * @device_count: The current number of allocated binder devices. */ struct binderfs_info { struct ipc_namespace *ipc_ns; struct dentry *control_dentry; kuid_t root_uid; kgid_t root_gid; - + struct binderfs_mount_opts mount_opts; + int device_count; }; static inline struct binderfs_info *BINDERFS_I(const struct inode *inode) @@ -84,7 +107,7 @@ bool is_binderfs_device(const struct inode *inode) * @userp: buffer to copy information about new device for userspace to * @req: struct binderfs_device as copied from userspace * - * This function allocated a new binder_device and reserves a new minor + * This function allocates a new binder_device and reserves a new minor * number for it. * Minor numbers are limited and tracked globally in binderfs_minors. The * function will stash a struct binder_device for the specific binder @@ -100,20 +123,34 @@ static int binderfs_binder_device_create(struct inode *ref_inode, struct binderfs_device *req) { int minor, ret; - struct dentry *dentry, *dup, *root; + struct dentry *dentry, *root; struct binder_device *device; - size_t name_len = BINDERFS_MAX_NAME + 1; char *name = NULL; + size_t name_len; struct inode *inode = NULL; struct super_block *sb = ref_inode->i_sb; struct binderfs_info *info = sb->s_fs_info; +#if defined(CONFIG_IPC_NS) + bool use_reserve = (info->ipc_ns == &init_ipc_ns); +#else + bool use_reserve = true; +#endif /* Reserve new minor number for the new device. */ mutex_lock(&binderfs_minors_mutex); - minor = ida_alloc_max(&binderfs_minors, BINDERFS_MAX_MINOR, GFP_KERNEL); - mutex_unlock(&binderfs_minors_mutex); - if (minor < 0) + if (++info->device_count <= info->mount_opts.max) + minor = ida_alloc_max(&binderfs_minors, + use_reserve ? BINDERFS_MAX_MINOR : + BINDERFS_MAX_MINOR_CAPPED, + GFP_KERNEL); + else + minor = -ENOSPC; + if (minor < 0) { + --info->device_count; + mutex_unlock(&binderfs_minors_mutex); return minor; + } + mutex_unlock(&binderfs_minors_mutex); ret = -ENOMEM; device = kzalloc(sizeof(*device), GFP_KERNEL); @@ -132,12 +169,13 @@ static int binderfs_binder_device_create(struct inode *ref_inode, inode->i_uid = info->root_uid; inode->i_gid = info->root_gid; - name = kmalloc(name_len, GFP_KERNEL); + req->name[BINDERFS_MAX_NAME] = '\0'; /* NUL-terminate */ + name_len = strlen(req->name); + /* Make sure to include terminating NUL byte */ + name = kmemdup(req->name, name_len + 1, GFP_KERNEL); if (!name) goto err; - strscpy(name, req->name, name_len); - device->binderfs_inode = inode; device->context.binder_context_mgr_uid = INVALID_UID; device->context.name = name; @@ -156,28 +194,25 @@ static int binderfs_binder_device_create(struct inode *ref_inode, root = sb->s_root; inode_lock(d_inode(root)); - dentry = d_alloc_name(root, name); - if (!dentry) { + + /* look it up */ + dentry = lookup_one_len(name, root, name_len); + if (IS_ERR(dentry)) { inode_unlock(d_inode(root)); - ret = -ENOMEM; + ret = PTR_ERR(dentry); goto err; } - /* Verify that the name userspace gave us is not already in use. */ - dup = d_lookup(root, &dentry->d_name); - if (dup) { - if (d_really_is_positive(dup)) { - dput(dup); - dput(dentry); - inode_unlock(d_inode(root)); - ret = -EEXIST; - goto err; - } - dput(dup); + if (d_really_is_positive(dentry)) { + /* already exists */ + dput(dentry); + inode_unlock(d_inode(root)); + ret = -EEXIST; + goto err; } inode->i_private = device; - d_add(dentry, inode); + d_instantiate(dentry, inode); fsnotify_create(root->d_inode, dentry); inode_unlock(d_inode(root)); @@ -187,6 +222,7 @@ err: kfree(name); kfree(device); mutex_lock(&binderfs_minors_mutex); + --info->device_count; ida_free(&binderfs_minors, minor); mutex_unlock(&binderfs_minors_mutex); iput(inode); @@ -232,6 +268,7 @@ static long binder_ctl_ioctl(struct file *file, unsigned int cmd, static void binderfs_evict_inode(struct inode *inode) { struct binder_device *device = inode->i_private; + struct binderfs_info *info = BINDERFS_I(inode); clear_inode(inode); @@ -239,6 +276,7 @@ static void binderfs_evict_inode(struct inode *inode) return; mutex_lock(&binderfs_minors_mutex); + --info->device_count; ida_free(&binderfs_minors, device->miscdev.minor); mutex_unlock(&binderfs_minors_mutex); @@ -246,43 +284,87 @@ static void binderfs_evict_inode(struct inode *inode) kfree(device); } +/** + * binderfs_parse_mount_opts - parse binderfs mount options + * @data: options to set (can be NULL in which case defaults are used) + */ +static int binderfs_parse_mount_opts(char *data, + struct binderfs_mount_opts *opts) +{ + char *p; + opts->max = BINDERFS_MAX_MINOR; + + while ((p = strsep(&data, ",")) != NULL) { + substring_t args[MAX_OPT_ARGS]; + int token; + int max_devices; + + if (!*p) + continue; + + token = match_token(p, tokens, args); + switch (token) { + case Opt_max: + if (match_int(&args[0], &max_devices) || + (max_devices < 0 || + (max_devices > BINDERFS_MAX_MINOR))) + return -EINVAL; + + opts->max = max_devices; + break; + default: + pr_err("Invalid mount options\n"); + return -EINVAL; + } + } + + return 0; +} + +static int binderfs_remount(struct super_block *sb, int *flags, char *data) +{ + struct binderfs_info *info = sb->s_fs_info; + return binderfs_parse_mount_opts(data, &info->mount_opts); +} + +static int binderfs_show_mount_opts(struct seq_file *seq, struct dentry *root) +{ + struct binderfs_info *info; + + info = root->d_sb->s_fs_info; + if (info->mount_opts.max <= BINDERFS_MAX_MINOR) + seq_printf(seq, ",max=%d", info->mount_opts.max); + + return 0; +} + static const struct super_operations binderfs_super_ops = { - .statfs = simple_statfs, - .evict_inode = binderfs_evict_inode, + .evict_inode = binderfs_evict_inode, + .remount_fs = binderfs_remount, + .show_options = binderfs_show_mount_opts, + .statfs = simple_statfs, }; +static inline bool is_binderfs_control_device(const struct dentry *dentry) +{ + struct binderfs_info *info = dentry->d_sb->s_fs_info; + return info->control_dentry == dentry; +} + static int binderfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) { - struct inode *inode = d_inode(old_dentry); - - /* binderfs doesn't support directories. */ - if (d_is_dir(old_dentry)) + if (is_binderfs_control_device(old_dentry) || + is_binderfs_control_device(new_dentry)) return -EPERM; - if (flags & ~RENAME_NOREPLACE) - return -EINVAL; - - if (!simple_empty(new_dentry)) - return -ENOTEMPTY; - - if (d_really_is_positive(new_dentry)) - simple_unlink(new_dir, new_dentry); - - old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime = - new_dir->i_mtime = inode->i_ctime = current_time(old_dir); - - return 0; + return simple_rename(old_dir, old_dentry, new_dir, new_dentry, flags); } static int binderfs_unlink(struct inode *dir, struct dentry *dentry) { - /* - * The control dentry is only ever touched during mount so checking it - * here should not require us to take lock. - */ - if (BINDERFS_I(dir)->control_dentry == dentry) + if (is_binderfs_control_device(dentry)) return -EPERM; return simple_unlink(dir, dentry); @@ -313,13 +395,16 @@ static int binderfs_binder_ctl_create(struct super_block *sb) struct inode *inode = NULL; struct dentry *root = sb->s_root; struct binderfs_info *info = sb->s_fs_info; +#if defined(CONFIG_IPC_NS) + bool use_reserve = (info->ipc_ns == &init_ipc_ns); +#else + bool use_reserve = true; +#endif device = kzalloc(sizeof(*device), GFP_KERNEL); if (!device) return -ENOMEM; - inode_lock(d_inode(root)); - /* If we have already created a binder-control node, return. */ if (info->control_dentry) { ret = 0; @@ -333,7 +418,10 @@ static int binderfs_binder_ctl_create(struct super_block *sb) /* Reserve a new minor number for the new device. */ mutex_lock(&binderfs_minors_mutex); - minor = ida_alloc_max(&binderfs_minors, BINDERFS_MAX_MINOR, GFP_KERNEL); + minor = ida_alloc_max(&binderfs_minors, + use_reserve ? BINDERFS_MAX_MINOR : + BINDERFS_MAX_MINOR_CAPPED, + GFP_KERNEL); mutex_unlock(&binderfs_minors_mutex); if (minor < 0) { ret = minor; @@ -358,12 +446,10 @@ static int binderfs_binder_ctl_create(struct super_block *sb) inode->i_private = device; info->control_dentry = dentry; d_add(dentry, inode); - inode_unlock(d_inode(root)); return 0; out: - inode_unlock(d_inode(root)); kfree(device); iput(inode); @@ -378,12 +464,9 @@ static const struct inode_operations binderfs_dir_inode_operations = { static int binderfs_fill_super(struct super_block *sb, void *data, int silent) { + int ret; struct binderfs_info *info; - int ret = -ENOMEM; struct inode *inode = NULL; - struct ipc_namespace *ipc_ns = sb->s_fs_info; - - get_ipc_ns(ipc_ns); sb->s_blocksize = PAGE_SIZE; sb->s_blocksize_bits = PAGE_SHIFT; @@ -405,11 +488,17 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_op = &binderfs_super_ops; sb->s_time_gran = 1; - info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL); - if (!info) - goto err_without_dentry; + sb->s_fs_info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL); + if (!sb->s_fs_info) + return -ENOMEM; + info = sb->s_fs_info; + + info->ipc_ns = get_ipc_ns(current->nsproxy->ipc_ns); + + ret = binderfs_parse_mount_opts(data, &info->mount_opts); + if (ret) + return ret; - info->ipc_ns = ipc_ns; info->root_gid = make_kgid(sb->s_user_ns, 0); if (!gid_valid(info->root_gid)) info->root_gid = GLOBAL_ROOT_GID; @@ -417,11 +506,9 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent) if (!uid_valid(info->root_uid)) info->root_uid = GLOBAL_ROOT_UID; - sb->s_fs_info = info; - inode = new_inode(sb); if (!inode) - goto err_without_dentry; + return -ENOMEM; inode->i_ino = FIRST_INODE; inode->i_fop = &simple_dir_operations; @@ -432,79 +519,28 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_root = d_make_root(inode); if (!sb->s_root) - goto err_without_dentry; - - ret = binderfs_binder_ctl_create(sb); - if (ret) - goto err_with_dentry; - - return 0; - -err_with_dentry: - dput(sb->s_root); - sb->s_root = NULL; - -err_without_dentry: - put_ipc_ns(ipc_ns); - iput(inode); - kfree(info); - - return ret; -} - -static int binderfs_test_super(struct super_block *sb, void *data) -{ - struct binderfs_info *info = sb->s_fs_info; - - if (info) - return info->ipc_ns == data; - - return 0; -} + return -ENOMEM; -static int binderfs_set_super(struct super_block *sb, void *data) -{ - sb->s_fs_info = data; - return set_anon_super(sb, NULL); + return binderfs_binder_ctl_create(sb); } static struct dentry *binderfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - struct super_block *sb; - struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; - - if (!ns_capable(ipc_ns->user_ns, CAP_SYS_ADMIN)) - return ERR_PTR(-EPERM); - - sb = sget_userns(fs_type, binderfs_test_super, binderfs_set_super, - flags, ipc_ns->user_ns, ipc_ns); - if (IS_ERR(sb)) - return ERR_CAST(sb); - - if (!sb->s_root) { - int ret = binderfs_fill_super(sb, data, flags & SB_SILENT ? 1 : 0); - if (ret) { - deactivate_locked_super(sb); - return ERR_PTR(ret); - } - - sb->s_flags |= SB_ACTIVE; - } - - return dget(sb->s_root); + return mount_nodev(fs_type, flags, data, binderfs_fill_super); } static void binderfs_kill_super(struct super_block *sb) { struct binderfs_info *info = sb->s_fs_info; + kill_litter_super(sb); + if (info && info->ipc_ns) put_ipc_ns(info->ipc_ns); kfree(info); - kill_litter_super(sb); } static struct file_system_type binder_fs_type = { @@ -514,7 +550,7 @@ static struct file_system_type binder_fs_type = { .fs_flags = FS_USERNS_MOUNT, }; -static int __init init_binderfs(void) +int __init init_binderfs(void) { int ret; @@ -530,15 +566,5 @@ static int __init init_binderfs(void) return ret; } - binderfs_mnt = kern_mount(&binder_fs_type); - if (IS_ERR(binderfs_mnt)) { - ret = PTR_ERR(binderfs_mnt); - binderfs_mnt = NULL; - unregister_filesystem(&binder_fs_type); - unregister_chrdev_region(binderfs_dev, BINDERFS_MAX_MINOR); - } - return ret; } - -device_initcall(init_binderfs); diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 4ca7a6b4eaae..8218db17ebdb 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -1091,7 +1091,7 @@ comment "Generic fallback / legacy drivers" config PATA_ACPI tristate "ACPI firmware driver for PATA" - depends on ATA_ACPI && ATA_BMDMA + depends on ATA_ACPI && ATA_BMDMA && PCI help This option enables an ACPI method driver which drives motherboard PATA controller interfaces through the ACPI diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index ef356e70e6de..8810475f307a 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -254,6 +254,8 @@ enum { AHCI_HFLAG_IS_MOBILE = (1 << 25), /* mobile chipset, use SATA_MOBILE_LPM_POLICY as default lpm_policy */ + AHCI_HFLAG_SUSPEND_PHYS = (1 << 26), /* handle PHYs during + suspend/resume */ /* ap->flags bits */ diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c index f9cb51be38eb..d4bba3ace45d 100644 --- a/drivers/ata/ahci_mvebu.c +++ b/drivers/ata/ahci_mvebu.c @@ -28,6 +28,11 @@ #define AHCI_WINDOW_BASE(win) (0x64 + ((win) << 4)) #define AHCI_WINDOW_SIZE(win) (0x68 + ((win) << 4)) +struct ahci_mvebu_plat_data { + int (*plat_config)(struct ahci_host_priv *hpriv); + unsigned int flags; +}; + static void ahci_mvebu_mbus_config(struct ahci_host_priv *hpriv, const struct mbus_dram_target_info *dram) { @@ -62,6 +67,35 @@ static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv) writel(0x80, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA); } +static int ahci_mvebu_armada_380_config(struct ahci_host_priv *hpriv) +{ + const struct mbus_dram_target_info *dram; + int rc = 0; + + dram = mv_mbus_dram_info(); + if (dram) + ahci_mvebu_mbus_config(hpriv, dram); + else + rc = -ENODEV; + + ahci_mvebu_regret_option(hpriv); + + return rc; +} + +static int ahci_mvebu_armada_3700_config(struct ahci_host_priv *hpriv) +{ + u32 reg; + + writel(0, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_ADDR); + + reg = readl(hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA); + reg |= BIT(6); + writel(reg, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA); + + return 0; +} + /** * ahci_mvebu_stop_engine * @@ -126,13 +160,9 @@ static int ahci_mvebu_resume(struct platform_device *pdev) { struct ata_host *host = platform_get_drvdata(pdev); struct ahci_host_priv *hpriv = host->private_data; - const struct mbus_dram_target_info *dram; + const struct ahci_mvebu_plat_data *pdata = hpriv->plat_data; - dram = mv_mbus_dram_info(); - if (dram) - ahci_mvebu_mbus_config(hpriv, dram); - - ahci_mvebu_regret_option(hpriv); + pdata->plat_config(hpriv); return ahci_platform_resume_host(&pdev->dev); } @@ -154,29 +184,30 @@ static struct scsi_host_template ahci_platform_sht = { static int ahci_mvebu_probe(struct platform_device *pdev) { + const struct ahci_mvebu_plat_data *pdata; struct ahci_host_priv *hpriv; - const struct mbus_dram_target_info *dram; int rc; + pdata = of_device_get_match_data(&pdev->dev); + if (!pdata) + return -EINVAL; + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); + hpriv->flags |= pdata->flags; + hpriv->plat_data = (void *)pdata; + rc = ahci_platform_enable_resources(hpriv); if (rc) return rc; hpriv->stop_engine = ahci_mvebu_stop_engine; - if (of_device_is_compatible(pdev->dev.of_node, - "marvell,armada-380-ahci")) { - dram = mv_mbus_dram_info(); - if (!dram) - return -ENODEV; - - ahci_mvebu_mbus_config(hpriv, dram); - ahci_mvebu_regret_option(hpriv); - } + rc = pdata->plat_config(hpriv); + if (rc) + goto disable_resources; rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info, &ahci_platform_sht); @@ -190,18 +221,28 @@ disable_resources: return rc; } +static const struct ahci_mvebu_plat_data ahci_mvebu_armada_380_plat_data = { + .plat_config = ahci_mvebu_armada_380_config, +}; + +static const struct ahci_mvebu_plat_data ahci_mvebu_armada_3700_plat_data = { + .plat_config = ahci_mvebu_armada_3700_config, + .flags = AHCI_HFLAG_SUSPEND_PHYS, +}; + static const struct of_device_id ahci_mvebu_of_match[] = { - { .compatible = "marvell,armada-380-ahci", }, - { .compatible = "marvell,armada-3700-ahci", }, + { + .compatible = "marvell,armada-380-ahci", + .data = &ahci_mvebu_armada_380_plat_data, + }, + { + .compatible = "marvell,armada-3700-ahci", + .data = &ahci_mvebu_armada_3700_plat_data, + }, { }, }; MODULE_DEVICE_TABLE(of, ahci_mvebu_of_match); -/* - * We currently don't provide power management related operations, - * since there is no suspend/resume support at the platform level for - * Armada 38x for the moment. - */ static struct platform_driver ahci_mvebu_driver = { .probe = ahci_mvebu_probe, .remove = ata_platform_remove_one, diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index 4b900fc659f7..81b1a3332ed6 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -56,6 +56,12 @@ static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv) if (rc) goto disable_phys; + rc = phy_set_mode(hpriv->phys[i], PHY_MODE_SATA); + if (rc) { + phy_exit(hpriv->phys[i]); + goto disable_phys; + } + rc = phy_power_on(hpriv->phys[i]); if (rc) { phy_exit(hpriv->phys[i]); @@ -738,6 +744,9 @@ int ahci_platform_suspend_host(struct device *dev) writel(ctl, mmio + HOST_CTL); readl(mmio + HOST_CTL); /* flush */ + if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS) + ahci_platform_disable_phys(hpriv); + return ata_host_suspend(host, PMSG_SUSPEND); } EXPORT_SYMBOL_GPL(ahci_platform_suspend_host); @@ -756,6 +765,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_suspend_host); int ahci_platform_resume_host(struct device *dev) { struct ata_host *host = dev_get_drvdata(dev); + struct ahci_host_priv *hpriv = host->private_data; int rc; if (dev->power.power_state.event == PM_EVENT_SUSPEND) { @@ -766,6 +776,9 @@ int ahci_platform_resume_host(struct device *dev) ahci_init_controller(host); } + if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS) + ahci_platform_enable_phys(hpriv); + ata_host_resume(host); return 0; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b8c3f9e6af89..adf28788cab5 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4554,6 +4554,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM, }, { "SAMSUNG SSD PM830 mSATA *", "CXM13D1Q", ATA_HORKAGE_NOLPM, }, { "SAMSUNG MZ7TD256HAFV-000L9", NULL, ATA_HORKAGE_NOLPM, }, + { "SAMSUNG MZ7TE512HMHP-000L1", "EXT06L0Q", ATA_HORKAGE_NOLPM, }, /* devices that don't properly handle queued TRIM commands */ { "Micron_M500IT_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c index 8cc9c429ad95..9e7fc302430f 100644 --- a/drivers/ata/pata_macio.c +++ b/drivers/ata/pata_macio.c @@ -915,6 +915,10 @@ static struct scsi_host_template pata_macio_sht = { .sg_tablesize = MAX_DCMDS, /* We may not need that strict one */ .dma_boundary = ATA_DMA_BOUNDARY, + /* Not sure what the real max is but we know it's less than 64K, let's + * use 64K minus 256 + */ + .max_segment_size = MAX_DBDMA_SEG, .slave_configure = pata_macio_slave_config, }; @@ -1044,11 +1048,6 @@ static int pata_macio_common_init(struct pata_macio_priv *priv, /* Make sure we have sane initial timings in the cache */ pata_macio_default_timings(priv); - /* Not sure what the real max is but we know it's less than 64K, let's - * use 64K minus 256 - */ - dma_set_max_seg_size(priv->dev, MAX_DBDMA_SEG); - /* Allocate libata host for 1 port */ memset(&pinfo, 0, sizeof(struct ata_port_info)); pmac_macio_calc_timing_masks(priv, &pinfo); diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 4dc528bf8e85..9c1247d42897 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -729,8 +729,8 @@ static int sata_fsl_port_start(struct ata_port *ap) if (!pp) return -ENOMEM; - mem = dma_zalloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma, - GFP_KERNEL); + mem = dma_alloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma, + GFP_KERNEL); if (!mem) { kfree(pp); return -ENOMEM; diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index e0bcf9b2dab0..174e84ce4379 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -245,8 +245,15 @@ struct inic_port_priv { static struct scsi_host_template inic_sht = { ATA_BASE_SHT(DRV_NAME), - .sg_tablesize = LIBATA_MAX_PRD, /* maybe it can be larger? */ - .dma_boundary = INIC_DMA_BOUNDARY, + .sg_tablesize = LIBATA_MAX_PRD, /* maybe it can be larger? */ + + /* + * This controller is braindamaged. dma_boundary is 0xffff like others + * but it will lock up the whole machine HARD if 65536 byte PRD entry + * is fed. Reduce maximum segment size. + */ + .dma_boundary = INIC_DMA_BOUNDARY, + .max_segment_size = 65536 - 512, }; static const int scr_map[] = { @@ -868,17 +875,6 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return rc; } - /* - * This controller is braindamaged. dma_boundary is 0xffff - * like others but it will lock up the whole machine HARD if - * 65536 byte PRD entry is fed. Reduce maximum segment size. - */ - rc = dma_set_max_seg_size(&pdev->dev, 65536 - 512); - if (rc) { - dev_err(&pdev->dev, "failed to set the maximum segment size\n"); - return rc; - } - rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl); if (rc) { dev_err(&pdev->dev, "failed to initialize controller\n"); diff --git a/drivers/atm/he.c b/drivers/atm/he.c index 29f102dcfec4..211607986134 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -533,9 +533,10 @@ static void he_init_tx_lbfp(struct he_dev *he_dev) static int he_init_tpdrq(struct he_dev *he_dev) { - he_dev->tpdrq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev, - CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), - &he_dev->tpdrq_phys, GFP_KERNEL); + he_dev->tpdrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev, + CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), + &he_dev->tpdrq_phys, + GFP_KERNEL); if (he_dev->tpdrq_base == NULL) { hprintk("failed to alloc tpdrq\n"); return -ENOMEM; @@ -717,7 +718,7 @@ static int he_init_cs_block_rcm(struct he_dev *he_dev) instead of '/ 512', use '>> 9' to prevent a call to divdu3 on x86 platforms */ - rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9; + rate_cps = (unsigned long long) (1UL << exp) * (man + 512) >> 9; if (rate_cps < 10) rate_cps = 10; /* 2.2.1 minimum payload rate is 10 cps */ @@ -805,9 +806,9 @@ static int he_init_group(struct he_dev *he_dev, int group) goto out_free_rbpl_virt; } - he_dev->rbpl_base = dma_zalloc_coherent(&he_dev->pci_dev->dev, - CONFIG_RBPL_SIZE * sizeof(struct he_rbp), - &he_dev->rbpl_phys, GFP_KERNEL); + he_dev->rbpl_base = dma_alloc_coherent(&he_dev->pci_dev->dev, + CONFIG_RBPL_SIZE * sizeof(struct he_rbp), + &he_dev->rbpl_phys, GFP_KERNEL); if (he_dev->rbpl_base == NULL) { hprintk("failed to alloc rbpl_base\n"); goto out_destroy_rbpl_pool; @@ -844,9 +845,9 @@ static int he_init_group(struct he_dev *he_dev, int group) /* rx buffer ready queue */ - he_dev->rbrq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev, - CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), - &he_dev->rbrq_phys, GFP_KERNEL); + he_dev->rbrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev, + CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), + &he_dev->rbrq_phys, GFP_KERNEL); if (he_dev->rbrq_base == NULL) { hprintk("failed to allocate rbrq\n"); goto out_free_rbpl; @@ -868,9 +869,9 @@ static int he_init_group(struct he_dev *he_dev, int group) /* tx buffer ready queue */ - he_dev->tbrq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev, - CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), - &he_dev->tbrq_phys, GFP_KERNEL); + he_dev->tbrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev, + CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), + &he_dev->tbrq_phys, GFP_KERNEL); if (he_dev->tbrq_base == NULL) { hprintk("failed to allocate tbrq\n"); goto out_free_rbpq_base; @@ -913,11 +914,9 @@ static int he_init_irq(struct he_dev *he_dev) /* 2.9.3.5 tail offset for each interrupt queue is located after the end of the interrupt queue */ - he_dev->irq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev, - (CONFIG_IRQ_SIZE + 1) - * sizeof(struct he_irq), - &he_dev->irq_phys, - GFP_KERNEL); + he_dev->irq_base = dma_alloc_coherent(&he_dev->pci_dev->dev, + (CONFIG_IRQ_SIZE + 1) * sizeof(struct he_irq), + &he_dev->irq_phys, GFP_KERNEL); if (he_dev->irq_base == NULL) { hprintk("failed to allocate irq\n"); return -ENOMEM; @@ -1464,9 +1463,9 @@ static int he_start(struct atm_dev *dev) /* host status page */ - he_dev->hsp = dma_zalloc_coherent(&he_dev->pci_dev->dev, - sizeof(struct he_hsp), - &he_dev->hsp_phys, GFP_KERNEL); + he_dev->hsp = dma_alloc_coherent(&he_dev->pci_dev->dev, + sizeof(struct he_hsp), + &he_dev->hsp_phys, GFP_KERNEL); if (he_dev->hsp == NULL) { hprintk("failed to allocate host status page\n"); return -ENOMEM; diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 6e737142ceaa..43a14579e80e 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -641,8 +641,8 @@ alloc_scq(struct idt77252_dev *card, int class) scq = kzalloc(sizeof(struct scq_info), GFP_KERNEL); if (!scq) return NULL; - scq->base = dma_zalloc_coherent(&card->pcidev->dev, SCQ_SIZE, - &scq->paddr, GFP_KERNEL); + scq->base = dma_alloc_coherent(&card->pcidev->dev, SCQ_SIZE, + &scq->paddr, GFP_KERNEL); if (scq->base == NULL) { kfree(scq); return NULL; @@ -971,8 +971,8 @@ init_rsq(struct idt77252_dev *card) { struct rsq_entry *rsqe; - card->rsq.base = dma_zalloc_coherent(&card->pcidev->dev, RSQSIZE, - &card->rsq.paddr, GFP_KERNEL); + card->rsq.base = dma_alloc_coherent(&card->pcidev->dev, RSQSIZE, + &card->rsq.paddr, GFP_KERNEL); if (card->rsq.base == NULL) { printk("%s: can't allocate RSQ.\n", card->name); return -1; @@ -3390,10 +3390,10 @@ static int init_card(struct atm_dev *dev) writel(0, SAR_REG_GP); /* Initialize RAW Cell Handle Register */ - card->raw_cell_hnd = dma_zalloc_coherent(&card->pcidev->dev, - 2 * sizeof(u32), - &card->raw_cell_paddr, - GFP_KERNEL); + card->raw_cell_hnd = dma_alloc_coherent(&card->pcidev->dev, + 2 * sizeof(u32), + &card->raw_cell_paddr, + GFP_KERNEL); if (!card->raw_cell_hnd) { printk("%s: memory allocation failure.\n", card->name); deinit_card(card); diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c index a43276c76fc6..21393ec3b9a4 100644 --- a/drivers/auxdisplay/ht16k33.c +++ b/drivers/auxdisplay/ht16k33.c @@ -509,7 +509,7 @@ static int ht16k33_remove(struct i2c_client *client) struct ht16k33_priv *priv = i2c_get_clientdata(client); struct ht16k33_fbdev *fbdev = &priv->fbdev; - cancel_delayed_work(&fbdev->work); + cancel_delayed_work_sync(&fbdev->work); unregister_framebuffer(fbdev->info); framebuffer_release(fbdev->info); free_page((unsigned long) fbdev->buffer); diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index cf78fa6d470d..a7359535caf5 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -79,8 +79,7 @@ static void cache_size(struct cacheinfo *this_leaf, struct device_node *np) ct_idx = get_cacheinfo_idx(this_leaf->type); propname = cache_type_info[ct_idx].size_prop; - if (of_property_read_u32(np, propname, &this_leaf->size)) - this_leaf->size = 0; + of_property_read_u32(np, propname, &this_leaf->size); } /* not cache_line_size() because that's a macro in include/linux/cache.h */ @@ -114,8 +113,7 @@ static void cache_nr_sets(struct cacheinfo *this_leaf, struct device_node *np) ct_idx = get_cacheinfo_idx(this_leaf->type); propname = cache_type_info[ct_idx].nr_sets_prop; - if (of_property_read_u32(np, propname, &this_leaf->number_of_sets)) - this_leaf->number_of_sets = 0; + of_property_read_u32(np, propname, &this_leaf->number_of_sets); } static void cache_associativity(struct cacheinfo *this_leaf) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index a690fd400260..0992e67e862b 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -32,6 +32,7 @@ #include <trace/events/power.h> #include <linux/cpufreq.h> #include <linux/cpuidle.h> +#include <linux/devfreq.h> #include <linux/timer.h> #include "../base.h" @@ -1078,6 +1079,7 @@ void dpm_resume(pm_message_t state) dpm_show_time(starttime, state, 0, NULL); cpufreq_resume(); + devfreq_resume(); trace_suspend_resume(TPS("dpm_resume"), state.event, false); } @@ -1852,6 +1854,7 @@ int dpm_suspend(pm_message_t state) trace_suspend_resume(TPS("dpm_suspend"), state.event, true); might_sleep(); + devfreq_suspend(); cpufreq_suspend(); mutex_lock(&dpm_list_mtx); diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 70624695b6d5..ccd296dbb95c 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -95,7 +95,7 @@ static void __update_runtime_status(struct device *dev, enum rpm_status status) static void pm_runtime_deactivate_timer(struct device *dev) { if (dev->power.timer_expires > 0) { - hrtimer_cancel(&dev->power.suspend_timer); + hrtimer_try_to_cancel(&dev->power.suspend_timer); dev->power.timer_expires = 0; } } @@ -121,7 +121,7 @@ static void pm_runtime_cancel_pending(struct device *dev) * Compute the autosuspend-delay expiration time based on the device's * power.last_busy time. If the delay has already expired or is disabled * (negative) or the power.use_autosuspend flag isn't set, return 0. - * Otherwise return the expiration time in jiffies (adjusted to be nonzero). + * Otherwise return the expiration time in nanoseconds (adjusted to be nonzero). * * This function may be called either with or without dev->power.lock held. * Either way it can be racy, since power.last_busy may be updated at any time. @@ -130,7 +130,7 @@ u64 pm_runtime_autosuspend_expiration(struct device *dev) { int autosuspend_delay; u64 last_busy, expires = 0; - u64 now = ktime_to_ns(ktime_get()); + u64 now = ktime_get_mono_fast_ns(); if (!dev->power.use_autosuspend) goto out; @@ -141,7 +141,7 @@ u64 pm_runtime_autosuspend_expiration(struct device *dev) last_busy = READ_ONCE(dev->power.last_busy); - expires = last_busy + autosuspend_delay * NSEC_PER_MSEC; + expires = last_busy + (u64)autosuspend_delay * NSEC_PER_MSEC; if (expires <= now) expires = 0; /* Already expired. */ @@ -525,7 +525,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) * We add a slack of 25% to gather wakeups * without sacrificing the granularity. */ - u64 slack = READ_ONCE(dev->power.autosuspend_delay) * + u64 slack = (u64)READ_ONCE(dev->power.autosuspend_delay) * (NSEC_PER_MSEC >> 2); dev->power.timer_expires = expires; @@ -905,8 +905,11 @@ static enum hrtimer_restart pm_suspend_timer_fn(struct hrtimer *timer) spin_lock_irqsave(&dev->power.lock, flags); expires = dev->power.timer_expires; - /* If 'expire' is after 'jiffies' we've been called too early. */ - if (expires > 0 && expires < ktime_to_ns(ktime_get())) { + /* + * If 'expires' is after the current time, we've been called + * too early. + */ + if (expires > 0 && expires < ktime_get_mono_fast_ns()) { dev->power.timer_expires = 0; rpm_suspend(dev, dev->power.timer_autosuspends ? (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC); @@ -925,7 +928,7 @@ static enum hrtimer_restart pm_suspend_timer_fn(struct hrtimer *timer) int pm_schedule_suspend(struct device *dev, unsigned int delay) { unsigned long flags; - ktime_t expires; + u64 expires; int retval; spin_lock_irqsave(&dev->power.lock, flags); @@ -942,8 +945,8 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay) /* Other scheduled or pending requests need to be canceled. */ pm_runtime_cancel_pending(dev); - expires = ktime_add(ktime_get(), ms_to_ktime(delay)); - dev->power.timer_expires = ktime_to_ns(expires); + expires = ktime_get_mono_fast_ns() + (u64)delay * NSEC_PER_MSEC; + dev->power.timer_expires = expires; dev->power.timer_autosuspends = 0; hrtimer_start(&dev->power.suspend_timer, expires, HRTIMER_MODE_ABS); diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 2e8f0144f9ab..9cbb4b0cd01b 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c @@ -33,7 +33,7 @@ struct regcache_rbtree_node { unsigned int blklen; /* the actual rbtree node holding this block */ struct rb_node node; -} __attribute__ ((packed)); +}; struct regcache_rbtree_ctx { struct rb_root root; diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 1bd1145ad8b5..5059748afd4c 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -35,6 +35,7 @@ struct regmap_irq_chip_data { int wake_count; void *status_reg_buf; + unsigned int *main_status_buf; unsigned int *status_buf; unsigned int *mask_buf; unsigned int *mask_buf_def; @@ -108,6 +109,9 @@ static void regmap_irq_sync_unlock(struct irq_data *data) * suppress pointless writes. */ for (i = 0; i < d->chip->num_regs; i++) { + if (!d->chip->mask_base) + continue; + reg = d->chip->mask_base + (i * map->reg_stride * d->irq_reg_stride); if (d->chip->mask_invert) { @@ -258,7 +262,7 @@ static int regmap_irq_set_type(struct irq_data *data, unsigned int type) const struct regmap_irq_type *t = &irq_data->type; if ((t->types_supported & type) != type) - return -ENOTSUPP; + return 0; reg = t->type_reg_offset / map->reg_stride; @@ -326,6 +330,33 @@ static const struct irq_chip regmap_irq_chip = { .irq_set_wake = regmap_irq_set_wake, }; +static inline int read_sub_irq_data(struct regmap_irq_chip_data *data, + unsigned int b) +{ + const struct regmap_irq_chip *chip = data->chip; + struct regmap *map = data->map; + struct regmap_irq_sub_irq_map *subreg; + int i, ret = 0; + + if (!chip->sub_reg_offsets) { + /* Assume linear mapping */ + ret = regmap_read(map, chip->status_base + + (b * map->reg_stride * data->irq_reg_stride), + &data->status_buf[b]); + } else { + subreg = &chip->sub_reg_offsets[b]; + for (i = 0; i < subreg->num_regs; i++) { + unsigned int offset = subreg->offset[i]; + + ret = regmap_read(map, chip->status_base + offset, + &data->status_buf[offset]); + if (ret) + break; + } + } + return ret; +} + static irqreturn_t regmap_irq_thread(int irq, void *d) { struct regmap_irq_chip_data *data = d; @@ -349,11 +380,65 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) } /* - * Read in the statuses, using a single bulk read if possible - * in order to reduce the I/O overheads. + * Read only registers with active IRQs if the chip has 'main status + * register'. Else read in the statuses, using a single bulk read if + * possible in order to reduce the I/O overheads. */ - if (!map->use_single_read && map->reg_stride == 1 && - data->irq_reg_stride == 1) { + + if (chip->num_main_regs) { + unsigned int max_main_bits; + unsigned long size; + + size = chip->num_regs * sizeof(unsigned int); + + max_main_bits = (chip->num_main_status_bits) ? + chip->num_main_status_bits : chip->num_regs; + /* Clear the status buf as we don't read all status regs */ + memset(data->status_buf, 0, size); + + /* We could support bulk read for main status registers + * but I don't expect to see devices with really many main + * status registers so let's only support single reads for the + * sake of simplicity. and add bulk reads only if needed + */ + for (i = 0; i < chip->num_main_regs; i++) { + ret = regmap_read(map, chip->main_status + + (i * map->reg_stride + * data->irq_reg_stride), + &data->main_status_buf[i]); + if (ret) { + dev_err(map->dev, + "Failed to read IRQ status %d\n", + ret); + goto exit; + } + } + + /* Read sub registers with active IRQs */ + for (i = 0; i < chip->num_main_regs; i++) { + unsigned int b; + const unsigned long mreg = data->main_status_buf[i]; + + for_each_set_bit(b, &mreg, map->format.val_bytes * 8) { + if (i * map->format.val_bytes * 8 + b > + max_main_bits) + break; + ret = read_sub_irq_data(data, b); + + if (ret != 0) { + dev_err(map->dev, + "Failed to read IRQ status %d\n", + ret); + if (chip->runtime_pm) + pm_runtime_put(map->dev); + goto exit; + } + } + + } + } else if (!map->use_single_read && map->reg_stride == 1 && + data->irq_reg_stride == 1) { + u8 *buf8 = data->status_reg_buf; u16 *buf16 = data->status_reg_buf; u32 *buf32 = data->status_reg_buf; @@ -518,6 +603,15 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, if (!d) return -ENOMEM; + if (chip->num_main_regs) { + d->main_status_buf = kcalloc(chip->num_main_regs, + sizeof(unsigned int), + GFP_KERNEL); + + if (!d->main_status_buf) + goto err_alloc; + } + d->status_buf = kcalloc(chip->num_regs, sizeof(unsigned int), GFP_KERNEL); if (!d->status_buf) @@ -588,6 +682,9 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, /* Mask all the interrupts by default */ for (i = 0; i < chip->num_regs; i++) { d->mask_buf[i] = d->mask_buf_def[i]; + if (!chip->mask_base) + continue; + reg = chip->mask_base + (i * map->reg_stride * d->irq_reg_stride); if (chip->mask_invert) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 6f2856c6d0f2..55481b40df9a 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4075,7 +4075,7 @@ static unsigned int floppy_check_events(struct gendisk *disk, if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { if (lock_fdc(drive)) - return -EINTR; + return 0; poll_drive(false, 0); process_fd_request(); } diff --git a/drivers/block/loop.c b/drivers/block/loop.c index b8a0720d3653..cf5538942834 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1190,6 +1190,12 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) goto out_unlock; } + if (lo->lo_offset != info->lo_offset || + lo->lo_sizelimit != info->lo_sizelimit) { + sync_blockdev(lo->lo_device); + kill_bdev(lo->lo_device); + } + /* I/O need to be drained during transfer transition */ blk_mq_freeze_queue(lo->lo_queue); @@ -1218,6 +1224,14 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) if (lo->lo_offset != info->lo_offset || lo->lo_sizelimit != info->lo_sizelimit) { + /* kill_bdev should have truncated all the pages */ + if (lo->lo_device->bd_inode->i_mapping->nrpages) { + err = -EAGAIN; + pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n", + __func__, lo->lo_number, lo->lo_file_name, + lo->lo_device->bd_inode->i_mapping->nrpages); + goto out_unfreeze; + } if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) { err = -EFBIG; goto out_unfreeze; @@ -1443,22 +1457,39 @@ static int loop_set_dio(struct loop_device *lo, unsigned long arg) static int loop_set_block_size(struct loop_device *lo, unsigned long arg) { + int err = 0; + if (lo->lo_state != Lo_bound) return -ENXIO; if (arg < 512 || arg > PAGE_SIZE || !is_power_of_2(arg)) return -EINVAL; + if (lo->lo_queue->limits.logical_block_size != arg) { + sync_blockdev(lo->lo_device); + kill_bdev(lo->lo_device); + } + blk_mq_freeze_queue(lo->lo_queue); + /* kill_bdev should have truncated all the pages */ + if (lo->lo_queue->limits.logical_block_size != arg && + lo->lo_device->bd_inode->i_mapping->nrpages) { + err = -EAGAIN; + pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n", + __func__, lo->lo_number, lo->lo_file_name, + lo->lo_device->bd_inode->i_mapping->nrpages); + goto out_unfreeze; + } + blk_queue_logical_block_size(lo->lo_queue, arg); blk_queue_physical_block_size(lo->lo_queue, arg); blk_queue_io_min(lo->lo_queue, arg); loop_update_dio(lo); - +out_unfreeze: blk_mq_unfreeze_queue(lo->lo_queue); - return 0; + return err; } static int lo_simple_ioctl(struct loop_device *lo, unsigned int cmd, diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 08696f5f00bb..7c9a949e876b 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -288,9 +288,10 @@ static void nbd_size_update(struct nbd_device *nbd) blk_queue_physical_block_size(nbd->disk->queue, config->blksize); set_capacity(nbd->disk, config->bytesize >> 9); if (bdev) { - if (bdev->bd_disk) + if (bdev->bd_disk) { bd_set_size(bdev, config->bytesize); - else + set_blocksize(bdev, config->blksize); + } else bdev->bd_invalidated = 1; bdput(bdev); } diff --git a/drivers/block/null_blk.h b/drivers/block/null_blk.h index b3df2793e7cd..34b22d6523ba 100644 --- a/drivers/block/null_blk.h +++ b/drivers/block/null_blk.h @@ -97,6 +97,7 @@ void null_zone_reset(struct nullb_cmd *cmd, sector_t sector); #else static inline int null_zone_init(struct nullb_device *dev) { + pr_err("null_blk: CONFIG_BLK_DEV_ZONED not enabled\n"); return -EINVAL; } static inline void null_zone_exit(struct nullb_device *dev) {} diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 8e5140bbf241..1e92b61d0bd5 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -5986,7 +5986,6 @@ static ssize_t do_rbd_remove(struct bus_type *bus, struct list_head *tmp; int dev_id; char opt_buf[6]; - bool already = false; bool force = false; int ret; @@ -6019,13 +6018,13 @@ static ssize_t do_rbd_remove(struct bus_type *bus, spin_lock_irq(&rbd_dev->lock); if (rbd_dev->open_count && !force) ret = -EBUSY; - else - already = test_and_set_bit(RBD_DEV_FLAG_REMOVING, - &rbd_dev->flags); + else if (test_and_set_bit(RBD_DEV_FLAG_REMOVING, + &rbd_dev->flags)) + ret = -EINPROGRESS; spin_unlock_irq(&rbd_dev->lock); } spin_unlock(&rbd_dev_list_lock); - if (ret < 0 || already) + if (ret) return ret; if (force) { diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c index a10d5736d8f7..ab893a7571a2 100644 --- a/drivers/block/skd_main.c +++ b/drivers/block/skd_main.c @@ -2641,8 +2641,8 @@ static int skd_cons_skcomp(struct skd_device *skdev) "comp pci_alloc, total bytes %zd entries %d\n", SKD_SKCOMP_SIZE, SKD_N_COMPLETION_ENTRY); - skcomp = dma_zalloc_coherent(&skdev->pdev->dev, SKD_SKCOMP_SIZE, - &skdev->cq_dma_address, GFP_KERNEL); + skcomp = dma_alloc_coherent(&skdev->pdev->dev, SKD_SKCOMP_SIZE, + &skdev->cq_dma_address, GFP_KERNEL); if (skcomp == NULL) { rc = -ENOMEM; diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 33c5cc879f24..04ca65912638 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -316,11 +316,9 @@ static ssize_t idle_store(struct device *dev, * See the comment in writeback_store. */ zram_slot_lock(zram, index); - if (!zram_allocated(zram, index) || - zram_test_flag(zram, index, ZRAM_UNDER_WB)) - goto next; - zram_set_flag(zram, index, ZRAM_IDLE); -next: + if (zram_allocated(zram, index) && + !zram_test_flag(zram, index, ZRAM_UNDER_WB)) + zram_set_flag(zram, index, ZRAM_IDLE); zram_slot_unlock(zram, index); } @@ -330,6 +328,41 @@ next: } #ifdef CONFIG_ZRAM_WRITEBACK +static ssize_t writeback_limit_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct zram *zram = dev_to_zram(dev); + u64 val; + ssize_t ret = -EINVAL; + + if (kstrtoull(buf, 10, &val)) + return ret; + + down_read(&zram->init_lock); + spin_lock(&zram->wb_limit_lock); + zram->wb_limit_enable = val; + spin_unlock(&zram->wb_limit_lock); + up_read(&zram->init_lock); + ret = len; + + return ret; +} + +static ssize_t writeback_limit_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + bool val; + struct zram *zram = dev_to_zram(dev); + + down_read(&zram->init_lock); + spin_lock(&zram->wb_limit_lock); + val = zram->wb_limit_enable; + spin_unlock(&zram->wb_limit_lock); + up_read(&zram->init_lock); + + return scnprintf(buf, PAGE_SIZE, "%d\n", val); +} + static ssize_t writeback_limit_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -341,9 +374,9 @@ static ssize_t writeback_limit_store(struct device *dev, return ret; down_read(&zram->init_lock); - atomic64_set(&zram->stats.bd_wb_limit, val); - if (val == 0) - zram->stop_writeback = false; + spin_lock(&zram->wb_limit_lock); + zram->bd_wb_limit = val; + spin_unlock(&zram->wb_limit_lock); up_read(&zram->init_lock); ret = len; @@ -357,7 +390,9 @@ static ssize_t writeback_limit_show(struct device *dev, struct zram *zram = dev_to_zram(dev); down_read(&zram->init_lock); - val = atomic64_read(&zram->stats.bd_wb_limit); + spin_lock(&zram->wb_limit_lock); + val = zram->bd_wb_limit; + spin_unlock(&zram->wb_limit_lock); up_read(&zram->init_lock); return scnprintf(buf, PAGE_SIZE, "%llu\n", val); @@ -588,8 +623,8 @@ static int read_from_bdev_async(struct zram *zram, struct bio_vec *bvec, return 1; } -#define HUGE_WRITEBACK 0x1 -#define IDLE_WRITEBACK 0x2 +#define HUGE_WRITEBACK 1 +#define IDLE_WRITEBACK 2 static ssize_t writeback_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -602,7 +637,7 @@ static ssize_t writeback_store(struct device *dev, struct page *page; ssize_t ret, sz; char mode_buf[8]; - unsigned long mode = -1UL; + int mode = -1; unsigned long blk_idx = 0; sz = strscpy(mode_buf, buf, sizeof(mode_buf)); @@ -618,7 +653,7 @@ static ssize_t writeback_store(struct device *dev, else if (!strcmp(mode_buf, "huge")) mode = HUGE_WRITEBACK; - if (mode == -1UL) + if (mode == -1) return -EINVAL; down_read(&zram->init_lock); @@ -645,10 +680,13 @@ static ssize_t writeback_store(struct device *dev, bvec.bv_len = PAGE_SIZE; bvec.bv_offset = 0; - if (zram->stop_writeback) { + spin_lock(&zram->wb_limit_lock); + if (zram->wb_limit_enable && !zram->bd_wb_limit) { + spin_unlock(&zram->wb_limit_lock); ret = -EIO; break; } + spin_unlock(&zram->wb_limit_lock); if (!blk_idx) { blk_idx = alloc_block_bdev(zram); @@ -667,10 +705,11 @@ static ssize_t writeback_store(struct device *dev, zram_test_flag(zram, index, ZRAM_UNDER_WB)) goto next; - if ((mode & IDLE_WRITEBACK && - !zram_test_flag(zram, index, ZRAM_IDLE)) && - (mode & HUGE_WRITEBACK && - !zram_test_flag(zram, index, ZRAM_HUGE))) + if (mode == IDLE_WRITEBACK && + !zram_test_flag(zram, index, ZRAM_IDLE)) + goto next; + if (mode == HUGE_WRITEBACK && + !zram_test_flag(zram, index, ZRAM_HUGE)) goto next; /* * Clearing ZRAM_UNDER_WB is duty of caller. @@ -732,11 +771,10 @@ static ssize_t writeback_store(struct device *dev, zram_set_element(zram, index, blk_idx); blk_idx = 0; atomic64_inc(&zram->stats.pages_stored); - if (atomic64_add_unless(&zram->stats.bd_wb_limit, - -1 << (PAGE_SHIFT - 12), 0)) { - if (atomic64_read(&zram->stats.bd_wb_limit) == 0) - zram->stop_writeback = true; - } + spin_lock(&zram->wb_limit_lock); + if (zram->wb_limit_enable && zram->bd_wb_limit > 0) + zram->bd_wb_limit -= 1UL << (PAGE_SHIFT - 12); + spin_unlock(&zram->wb_limit_lock); next: zram_slot_unlock(zram, index); } @@ -1812,6 +1850,7 @@ static DEVICE_ATTR_RW(comp_algorithm); static DEVICE_ATTR_RW(backing_dev); static DEVICE_ATTR_WO(writeback); static DEVICE_ATTR_RW(writeback_limit); +static DEVICE_ATTR_RW(writeback_limit_enable); #endif static struct attribute *zram_disk_attrs[] = { @@ -1828,6 +1867,7 @@ static struct attribute *zram_disk_attrs[] = { &dev_attr_backing_dev.attr, &dev_attr_writeback.attr, &dev_attr_writeback_limit.attr, + &dev_attr_writeback_limit_enable.attr, #endif &dev_attr_io_stat.attr, &dev_attr_mm_stat.attr, @@ -1867,7 +1907,9 @@ static int zram_add(void) device_id = ret; init_rwsem(&zram->init_lock); - +#ifdef CONFIG_ZRAM_WRITEBACK + spin_lock_init(&zram->wb_limit_lock); +#endif queue = blk_alloc_queue(GFP_KERNEL); if (!queue) { pr_err("Error allocating disk queue for device %d\n", diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h index 4bd3afd15e83..f2fd46daa760 100644 --- a/drivers/block/zram/zram_drv.h +++ b/drivers/block/zram/zram_drv.h @@ -86,7 +86,6 @@ struct zram_stats { atomic64_t bd_count; /* no. of pages in backing device */ atomic64_t bd_reads; /* no. of reads from backing device */ atomic64_t bd_writes; /* no. of writes from backing device */ - atomic64_t bd_wb_limit; /* writeback limit of backing device */ #endif }; @@ -114,8 +113,10 @@ struct zram { */ bool claim; /* Protected by bdev->bd_mutex */ struct file *backing_dev; - bool stop_writeback; #ifdef CONFIG_ZRAM_WRITEBACK + spinlock_t wb_limit_lock; + bool wb_limit_enable; + u64 bd_wb_limit; struct block_device *bdev; unsigned int old_block_size; unsigned long *bitmap; diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index f94d33525771..d299ec79e4c3 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -781,12 +781,12 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("smartreflex", 0, -1, 0x38, -1, 0x00000000, 0xffffffff, SYSC_QUIRK_LEGACY_IDLE), SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000015, 0xffffffff, - SYSC_QUIRK_LEGACY_IDLE), + 0), /* Some timers on omap4 and later */ SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x50002100, 0xffffffff, - SYSC_QUIRK_LEGACY_IDLE), + 0), SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff, - SYSC_QUIRK_LEGACY_IDLE), + 0), SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff, SYSC_QUIRK_LEGACY_IDLE), /* Uarts on omap4 and later */ diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index a74ce885b541..c518659b4d9f 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -32,6 +32,7 @@ #include <linux/moduleparam.h> #include <linux/workqueue.h> #include <linux/uuid.h> +#include <linux/nospec.h> #define IPMI_DRIVER_VERSION "39.2" @@ -62,7 +63,8 @@ static void ipmi_debug_msg(const char *title, unsigned char *data, { } #endif -static int initialized; +static bool initialized; +static bool drvregistered; enum ipmi_panic_event_op { IPMI_SEND_PANIC_EVENT_NONE, @@ -612,7 +614,7 @@ static DEFINE_MUTEX(ipmidriver_mutex); static LIST_HEAD(ipmi_interfaces); static DEFINE_MUTEX(ipmi_interfaces_mutex); -DEFINE_STATIC_SRCU(ipmi_interfaces_srcu); +struct srcu_struct ipmi_interfaces_srcu; /* * List of watchers that want to know when smi's are added and deleted. @@ -720,7 +722,15 @@ struct watcher_entry { int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) { struct ipmi_smi *intf; - int index; + int index, rv; + + /* + * Make sure the driver is actually initialized, this handles + * problems with initialization order. + */ + rv = ipmi_init_msghandler(); + if (rv) + return rv; mutex_lock(&smi_watchers_mutex); @@ -884,7 +894,7 @@ static int deliver_response(struct ipmi_smi *intf, struct ipmi_recv_msg *msg) if (user) { user->handler->ipmi_recv_hndl(msg, user->handler_data); - release_ipmi_user(msg->user, index); + release_ipmi_user(user, index); } else { /* User went away, give up. */ ipmi_free_recv_msg(msg); @@ -1076,7 +1086,7 @@ int ipmi_create_user(unsigned int if_num, { unsigned long flags; struct ipmi_user *new_user; - int rv = 0, index; + int rv, index; struct ipmi_smi *intf; /* @@ -1094,18 +1104,9 @@ int ipmi_create_user(unsigned int if_num, * Make sure the driver is actually initialized, this handles * problems with initialization order. */ - if (!initialized) { - rv = ipmi_init_msghandler(); - if (rv) - return rv; - - /* - * The init code doesn't return an error if it was turned - * off, but it won't initialize. Check that. - */ - if (!initialized) - return -ENODEV; - } + rv = ipmi_init_msghandler(); + if (rv) + return rv; new_user = kmalloc(sizeof(*new_user), GFP_KERNEL); if (!new_user) @@ -1183,6 +1184,7 @@ EXPORT_SYMBOL(ipmi_get_smi_info); static void free_user(struct kref *ref) { struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount); + cleanup_srcu_struct(&user->release_barrier); kfree(user); } @@ -1259,7 +1261,6 @@ int ipmi_destroy_user(struct ipmi_user *user) { _ipmi_destroy_user(user); - cleanup_srcu_struct(&user->release_barrier); kref_put(&user->refcount, free_user); return 0; @@ -1298,10 +1299,12 @@ int ipmi_set_my_address(struct ipmi_user *user, if (!user) return -ENODEV; - if (channel >= IPMI_MAX_CHANNELS) + if (channel >= IPMI_MAX_CHANNELS) { rv = -EINVAL; - else + } else { + channel = array_index_nospec(channel, IPMI_MAX_CHANNELS); user->intf->addrinfo[channel].address = address; + } release_ipmi_user(user, index); return rv; @@ -1318,10 +1321,12 @@ int ipmi_get_my_address(struct ipmi_user *user, if (!user) return -ENODEV; - if (channel >= IPMI_MAX_CHANNELS) + if (channel >= IPMI_MAX_CHANNELS) { rv = -EINVAL; - else + } else { + channel = array_index_nospec(channel, IPMI_MAX_CHANNELS); *address = user->intf->addrinfo[channel].address; + } release_ipmi_user(user, index); return rv; @@ -1338,10 +1343,12 @@ int ipmi_set_my_LUN(struct ipmi_user *user, if (!user) return -ENODEV; - if (channel >= IPMI_MAX_CHANNELS) + if (channel >= IPMI_MAX_CHANNELS) { rv = -EINVAL; - else + } else { + channel = array_index_nospec(channel, IPMI_MAX_CHANNELS); user->intf->addrinfo[channel].lun = LUN & 0x3; + } release_ipmi_user(user, index); return rv; @@ -1358,10 +1365,12 @@ int ipmi_get_my_LUN(struct ipmi_user *user, if (!user) return -ENODEV; - if (channel >= IPMI_MAX_CHANNELS) + if (channel >= IPMI_MAX_CHANNELS) { rv = -EINVAL; - else + } else { + channel = array_index_nospec(channel, IPMI_MAX_CHANNELS); *address = user->intf->addrinfo[channel].lun; + } release_ipmi_user(user, index); return rv; @@ -2184,6 +2193,7 @@ static int check_addr(struct ipmi_smi *intf, { if (addr->channel >= IPMI_MAX_CHANNELS) return -EINVAL; + addr->channel = array_index_nospec(addr->channel, IPMI_MAX_CHANNELS); *lun = intf->addrinfo[addr->channel].lun; *saddr = intf->addrinfo[addr->channel].address; return 0; @@ -3291,17 +3301,9 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers, * Make sure the driver is actually initialized, this handles * problems with initialization order. */ - if (!initialized) { - rv = ipmi_init_msghandler(); - if (rv) - return rv; - /* - * The init code doesn't return an error if it was turned - * off, but it won't initialize. Check that. - */ - if (!initialized) - return -ENODEV; - } + rv = ipmi_init_msghandler(); + if (rv) + return rv; intf = kzalloc(sizeof(*intf), GFP_KERNEL); if (!intf) @@ -5017,6 +5019,22 @@ static int panic_event(struct notifier_block *this, return NOTIFY_DONE; } +/* Must be called with ipmi_interfaces_mutex held. */ +static int ipmi_register_driver(void) +{ + int rv; + + if (drvregistered) + return 0; + + rv = driver_register(&ipmidriver.driver); + if (rv) + pr_err("Could not register IPMI driver\n"); + else + drvregistered = true; + return rv; +} + static struct notifier_block panic_block = { .notifier_call = panic_event, .next = NULL, @@ -5027,66 +5045,75 @@ static int ipmi_init_msghandler(void) { int rv; + mutex_lock(&ipmi_interfaces_mutex); + rv = ipmi_register_driver(); + if (rv) + goto out; if (initialized) - return 0; - - rv = driver_register(&ipmidriver.driver); - if (rv) { - pr_err("Could not register IPMI driver\n"); - return rv; - } + goto out; - pr_info("version " IPMI_DRIVER_VERSION "\n"); + init_srcu_struct(&ipmi_interfaces_srcu); timer_setup(&ipmi_timer, ipmi_timeout, 0); mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES); atomic_notifier_chain_register(&panic_notifier_list, &panic_block); - initialized = 1; + initialized = true; - return 0; +out: + mutex_unlock(&ipmi_interfaces_mutex); + return rv; } static int __init ipmi_init_msghandler_mod(void) { - ipmi_init_msghandler(); - return 0; + int rv; + + pr_info("version " IPMI_DRIVER_VERSION "\n"); + + mutex_lock(&ipmi_interfaces_mutex); + rv = ipmi_register_driver(); + mutex_unlock(&ipmi_interfaces_mutex); + + return rv; } static void __exit cleanup_ipmi(void) { int count; - if (!initialized) - return; - - atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block); + if (initialized) { + atomic_notifier_chain_unregister(&panic_notifier_list, + &panic_block); - /* - * This can't be called if any interfaces exist, so no worry - * about shutting down the interfaces. - */ + /* + * This can't be called if any interfaces exist, so no worry + * about shutting down the interfaces. + */ - /* - * Tell the timer to stop, then wait for it to stop. This - * avoids problems with race conditions removing the timer - * here. - */ - atomic_inc(&stop_operation); - del_timer_sync(&ipmi_timer); + /* + * Tell the timer to stop, then wait for it to stop. This + * avoids problems with race conditions removing the timer + * here. + */ + atomic_inc(&stop_operation); + del_timer_sync(&ipmi_timer); - driver_unregister(&ipmidriver.driver); + initialized = false; - initialized = 0; + /* Check for buffer leaks. */ + count = atomic_read(&smi_msg_inuse_count); + if (count != 0) + pr_warn("SMI message count %d at exit\n", count); + count = atomic_read(&recv_msg_inuse_count); + if (count != 0) + pr_warn("recv message count %d at exit\n", count); - /* Check for buffer leaks. */ - count = atomic_read(&smi_msg_inuse_count); - if (count != 0) - pr_warn("SMI message count %d at exit\n", count); - count = atomic_read(&recv_msg_inuse_count); - if (count != 0) - pr_warn("recv message count %d at exit\n", count); + cleanup_srcu_struct(&ipmi_interfaces_srcu); + } + if (drvregistered) + driver_unregister(&ipmidriver.driver); } module_exit(cleanup_ipmi); diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index ca9528c4f183..b7a1ae2afaea 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -632,8 +632,9 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, /* Remove the multi-part read marker. */ len -= 2; + data += 2; for (i = 0; i < len; i++) - ssif_info->data[i] = data[i+2]; + ssif_info->data[i] = data[i]; ssif_info->multi_len = len; ssif_info->multi_pos = 1; @@ -661,8 +662,19 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, } blocknum = data[0]; + len--; + data++; + + if (blocknum != 0xff && len != 31) { + /* All blocks but the last must have 31 data bytes. */ + result = -EIO; + if (ssif_info->ssif_debug & SSIF_DEBUG_MSG) + pr_info("Received middle message <31\n"); - if (ssif_info->multi_len + len - 1 > IPMI_MAX_MSG_LENGTH) { + goto continue_op; + } + + if (ssif_info->multi_len + len > IPMI_MAX_MSG_LENGTH) { /* Received message too big, abort the operation. */ result = -E2BIG; if (ssif_info->ssif_debug & SSIF_DEBUG_MSG) @@ -671,16 +683,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, goto continue_op; } - /* Remove the blocknum from the data. */ - len--; for (i = 0; i < len; i++) - ssif_info->data[i + ssif_info->multi_len] = data[i + 1]; + ssif_info->data[i + ssif_info->multi_len] = data[i]; ssif_info->multi_len += len; if (blocknum == 0xff) { /* End of read */ len = ssif_info->multi_len; data = ssif_info->data; - } else if (blocknum + 1 != ssif_info->multi_pos) { + } else if (blocknum != ssif_info->multi_pos) { /* * Out of sequence block, just abort. Block * numbers start at zero for the second block, @@ -707,6 +717,7 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, } } + continue_op: if (result < 0) { ssif_inc_stat(ssif_info, receive_errors); } else { @@ -714,8 +725,6 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, ssif_inc_stat(ssif_info, received_message_parts); } - - continue_op: if (ssif_info->ssif_debug & SSIF_DEBUG_STATE) pr_info("DONE 1: state = %d, result=%d\n", ssif_info->ssif_state, result); diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index b5e3103c1175..e43c876a9223 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c @@ -59,6 +59,7 @@ #include <linux/mutex.h> #include <linux/delay.h> #include <linux/serial_8250.h> +#include <linux/nospec.h> #include "smapi.h" #include "mwavedd.h" #include "3780i.h" @@ -289,6 +290,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, ipcnum); return -EINVAL; } + ipcnum = array_index_nospec(ipcnum, + ARRAY_SIZE(pDrvData->IPCs)); PRINTK_3(TRACE_MWAVE, "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" " ipcnum %x entry usIntCount %x\n", @@ -317,6 +320,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, " Invalid ipcnum %x\n", ipcnum); return -EINVAL; } + ipcnum = array_index_nospec(ipcnum, + ARRAY_SIZE(pDrvData->IPCs)); PRINTK_3(TRACE_MWAVE, "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC" " ipcnum %x, usIntCount %x\n", @@ -383,6 +388,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, ipcnum); return -EINVAL; } + ipcnum = array_index_nospec(ipcnum, + ARRAY_SIZE(pDrvData->IPCs)); mutex_lock(&mwave_mutex); if (pDrvData->IPCs[ipcnum].bIsEnabled == true) { pDrvData->IPCs[ipcnum].bIsEnabled = false; diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index e5b2fe80eab4..d2f0bb5ba47e 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -293,7 +293,6 @@ config COMMON_CLK_BD718XX source "drivers/clk/actions/Kconfig" source "drivers/clk/bcm/Kconfig" source "drivers/clk/hisilicon/Kconfig" -source "drivers/clk/imx/Kconfig" source "drivers/clk/imgtec/Kconfig" source "drivers/clk/imx/Kconfig" source "drivers/clk/ingenic/Kconfig" diff --git a/drivers/clk/at91/at91sam9x5.c b/drivers/clk/at91/at91sam9x5.c index 2fe225a697df..3487e03d4bc6 100644 --- a/drivers/clk/at91/at91sam9x5.c +++ b/drivers/clk/at91/at91sam9x5.c @@ -144,8 +144,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, return; at91sam9x5_pmc = pmc_data_allocate(PMC_MAIN + 1, - nck(at91sam9x5_systemck), - nck(at91sam9x35_periphck), 0); + nck(at91sam9x5_systemck), 31, 0); if (!at91sam9x5_pmc) return; @@ -210,7 +209,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, parent_names[1] = "mainck"; parent_names[2] = "plladivck"; parent_names[3] = "utmick"; - parent_names[4] = "mck"; + parent_names[4] = "masterck"; for (i = 0; i < 2; i++) { char name[6]; diff --git a/drivers/clk/at91/sama5d2.c b/drivers/clk/at91/sama5d2.c index d69ad96fe988..cd0ef7274fdb 100644 --- a/drivers/clk/at91/sama5d2.c +++ b/drivers/clk/at91/sama5d2.c @@ -240,7 +240,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) parent_names[1] = "mainck"; parent_names[2] = "plladivck"; parent_names[3] = "utmick"; - parent_names[4] = "mck"; + parent_names[4] = "masterck"; for (i = 0; i < 3; i++) { char name[6]; @@ -291,7 +291,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) parent_names[1] = "mainck"; parent_names[2] = "plladivck"; parent_names[3] = "utmick"; - parent_names[4] = "mck"; + parent_names[4] = "masterck"; parent_names[5] = "audiopll_pmcck"; for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) { hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, diff --git a/drivers/clk/at91/sama5d4.c b/drivers/clk/at91/sama5d4.c index e358be7f6c8d..b645a9d59cdb 100644 --- a/drivers/clk/at91/sama5d4.c +++ b/drivers/clk/at91/sama5d4.c @@ -207,7 +207,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np) parent_names[1] = "mainck"; parent_names[2] = "plladivck"; parent_names[3] = "utmick"; - parent_names[4] = "mck"; + parent_names[4] = "masterck"; for (i = 0; i < 3; i++) { char name[6]; diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 5b393e711e94..7d16ab0784ec 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -262,8 +262,10 @@ static int vc5_mux_set_parent(struct clk_hw *hw, u8 index) if (vc5->clk_mux_ins == VC5_MUX_IN_XIN) src = VC5_PRIM_SRC_SHDN_EN_XTAL; - if (vc5->clk_mux_ins == VC5_MUX_IN_CLKIN) + else if (vc5->clk_mux_ins == VC5_MUX_IN_CLKIN) src = VC5_PRIM_SRC_SHDN_EN_CLKIN; + else /* Invalid; should have been caught by vc5_probe() */ + return -EINVAL; } return regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, mask, src); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 75d13c0eff12..d2477a5058ac 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1513,9 +1513,19 @@ static int clk_fetch_parent_index(struct clk_core *core, if (!parent) return -EINVAL; - for (i = 0; i < core->num_parents; i++) - if (clk_core_get_parent_by_index(core, i) == parent) + for (i = 0; i < core->num_parents; i++) { + if (core->parents[i] == parent) + return i; + + if (core->parents[i]) + continue; + + /* Fallback to comparing globally unique names */ + if (!strcmp(parent->name, core->parent_names[i])) { + core->parents[i] = parent; return i; + } + } return -EINVAL; } @@ -2779,7 +2789,7 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level) seq_printf(s, "\"protect_count\": %d,", c->protect_count); seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c)); seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c)); - seq_printf(s, "\"phase\": %d", clk_core_get_phase(c)); + seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c)); seq_printf(s, "\"duty_cycle\": %u", clk_core_get_scaled_duty_cycle(c, 100000)); } diff --git a/drivers/clk/imx/clk-frac-pll.c b/drivers/clk/imx/clk-frac-pll.c index 0026c3969b1e..76b9eb15604e 100644 --- a/drivers/clk/imx/clk-frac-pll.c +++ b/drivers/clk/imx/clk-frac-pll.c @@ -155,13 +155,14 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, { struct clk_frac_pll *pll = to_clk_frac_pll(hw); u32 val, divfi, divff; - u64 temp64 = parent_rate; + u64 temp64; int ret; parent_rate *= 8; rate *= 2; divfi = rate / parent_rate; - temp64 *= rate - divfi; + temp64 = parent_rate * divfi; + temp64 = rate - temp64; temp64 *= PLL_FRAC_DENOM; do_div(temp64, parent_rate); divff = temp64; diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c index 99c2508de8e5..fb6edf1b8aa2 100644 --- a/drivers/clk/imx/clk-imx8qxp-lpcg.c +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c @@ -169,6 +169,8 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) return -ENODEV; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; base = devm_ioremap(dev, res->start, resource_size(res)); if (!base) return -ENOMEM; diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c index 61fefc046ec5..d083b860f083 100644 --- a/drivers/clk/mmp/clk-of-mmp2.c +++ b/drivers/clk/mmp/clk-of-mmp2.c @@ -53,7 +53,6 @@ #define APMU_DISP1 0x110 #define APMU_CCIC0 0x50 #define APMU_CCIC1 0xf4 -#define APMU_SP 0x68 #define MPMU_UART_PLL 0x14 struct mmp2_clk_unit { @@ -210,8 +209,6 @@ static struct mmp_clk_mix_config ccic1_mix_config = { .reg_info = DEFINE_MIX_REG_INFO(4, 16, 2, 6, 32), }; -static DEFINE_SPINLOCK(sp_lock); - static struct mmp_param_mux_clk apmu_mux_clks[] = { {MMP2_CLK_DISP0_MUX, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 2, 0, &disp0_lock}, {MMP2_CLK_DISP1_MUX, "disp1_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP1, 6, 2, 0, &disp1_lock}, @@ -242,7 +239,6 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = { {MMP2_CLK_CCIC1, "ccic1_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x1b, 0x1b, 0x0, 0, &ccic1_lock}, {MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock}, {MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock}, - {MMP2_CLK_SP, "sp_clk", NULL, CLK_SET_RATE_PARENT, APMU_SP, 0x1b, 0x1b, 0x0, 0, &sp_lock}, }; static void mmp2_axi_periph_clk_init(struct mmp2_clk_unit *pxa_unit) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 1b1ba54e33dd..1c04575c118f 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -215,6 +215,7 @@ config MSM_MMCC_8996 config MSM_GCC_8998 tristate "MSM8998 Global Clock Controller" + select QCOM_GDSC help Support for the global clock controller on msm8998 devices. Say Y if you want to use peripheral devices such as UART, SPI, diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c index c782e62dd98b..58fa5c247af1 100644 --- a/drivers/clk/qcom/gcc-sdm845.c +++ b/drivers/clk/qcom/gcc-sdm845.c @@ -115,8 +115,8 @@ static const char * const gcc_parent_names_6[] = { "core_bi_pll_test_se", }; -static const char * const gcc_parent_names_7[] = { - "bi_tcxo", +static const char * const gcc_parent_names_7_ao[] = { + "bi_tcxo_ao", "gpll0", "gpll0_out_even", "core_bi_pll_test_se", @@ -128,6 +128,12 @@ static const char * const gcc_parent_names_8[] = { "core_bi_pll_test_se", }; +static const char * const gcc_parent_names_8_ao[] = { + "bi_tcxo_ao", + "gpll0", + "core_bi_pll_test_se", +}; + static const struct parent_map gcc_parent_map_10[] = { { P_BI_TCXO, 0 }, { P_GPLL0_OUT_MAIN, 1 }, @@ -210,7 +216,7 @@ static struct clk_rcg2 gcc_cpuss_ahb_clk_src = { .freq_tbl = ftbl_gcc_cpuss_ahb_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_cpuss_ahb_clk_src", - .parent_names = gcc_parent_names_7, + .parent_names = gcc_parent_names_7_ao, .num_parents = 4, .ops = &clk_rcg2_ops, }, @@ -229,7 +235,7 @@ static struct clk_rcg2 gcc_cpuss_rbcpr_clk_src = { .freq_tbl = ftbl_gcc_cpuss_rbcpr_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_cpuss_rbcpr_clk_src", - .parent_names = gcc_parent_names_8, + .parent_names = gcc_parent_names_8_ao, .num_parents = 3, .ops = &clk_rcg2_ops, }, diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c index 2d5d8b43727e..c4d0b6f6abf2 100644 --- a/drivers/clk/socfpga/clk-pll-s10.c +++ b/drivers/clk/socfpga/clk-pll-s10.c @@ -43,7 +43,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk, /* Read mdiv and fdiv from the fdbck register */ reg = readl(socfpgaclk->hw.reg + 0x4); mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT; - vco_freq = (unsigned long long)parent_rate * (mdiv + 6); + vco_freq = (unsigned long long)vco_freq * (mdiv + 6); return (unsigned long)vco_freq; } diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c index 5b238fc314ac..8281dfbf38c2 100644 --- a/drivers/clk/socfpga/clk-s10.c +++ b/drivers/clk/socfpga/clk-s10.c @@ -12,17 +12,17 @@ #include "stratix10-clk.h" -static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk", - "f2s_free_clk",}; +static const char * const pll_mux[] = { "osc1", "cb-intosc-hs-div2-clk", + "f2s-free-clk",}; static const char * const cntr_mux[] = { "main_pll", "periph_pll", - "osc1", "cb_intosc_hs_div2_clk", - "f2s_free_clk"}; -static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",}; + "osc1", "cb-intosc-hs-div2-clk", + "f2s-free-clk"}; +static const char * const boot_mux[] = { "osc1", "cb-intosc-hs-div2-clk",}; static const char * const noc_free_mux[] = {"main_noc_base_clk", "peri_noc_base_clk", - "osc1", "cb_intosc_hs_div2_clk", - "f2s_free_clk"}; + "osc1", "cb-intosc-hs-div2-clk", + "f2s-free-clk"}; static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"}; static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"}; @@ -33,14 +33,14 @@ static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk" static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"}; static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",}; -static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"}; +static const char * const s2f_usr0_mux[] = {"f2s-free-clk", "boot_clk"}; static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"}; static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"}; static const char * const mpu_free_mux[] = {"main_mpu_base_clk", "peri_mpu_base_clk", - "osc1", "cb_intosc_hs_div2_clk", - "f2s_free_clk"}; + "osc1", "cb-intosc-hs-div2-clk", + "f2s-free-clk"}; /* clocks in AO (always on) controller */ static const struct stratix10_pll_clock s10_pll_clks[] = { diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 3b97f60540ad..609970c0b666 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c @@ -264,9 +264,9 @@ static SUNXI_CCU_GATE(ahb1_mmc1_clk, "ahb1-mmc1", "ahb1", static SUNXI_CCU_GATE(ahb1_mmc2_clk, "ahb1-mmc2", "ahb1", 0x060, BIT(10), 0); static SUNXI_CCU_GATE(ahb1_mmc3_clk, "ahb1-mmc3", "ahb1", - 0x060, BIT(12), 0); + 0x060, BIT(11), 0); static SUNXI_CCU_GATE(ahb1_nand1_clk, "ahb1-nand1", "ahb1", - 0x060, BIT(13), 0); + 0x060, BIT(12), 0); static SUNXI_CCU_GATE(ahb1_nand0_clk, "ahb1-nand0", "ahb1", 0x060, BIT(13), 0); static SUNXI_CCU_GATE(ahb1_sdram_clk, "ahb1-sdram", "ahb1", diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c index 621b1cd996db..ac12f261f8ca 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c @@ -542,7 +542,7 @@ static struct ccu_reset_map sun8i_v3s_ccu_resets[] = { [RST_BUS_OHCI0] = { 0x2c0, BIT(29) }, [RST_BUS_VE] = { 0x2c4, BIT(0) }, - [RST_BUS_TCON0] = { 0x2c4, BIT(3) }, + [RST_BUS_TCON0] = { 0x2c4, BIT(4) }, [RST_BUS_CSI] = { 0x2c4, BIT(8) }, [RST_BUS_DE] = { 0x2c4, BIT(12) }, [RST_BUS_DBG] = { 0x2c4, BIT(31) }, diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c index 269d3595758b..edc31bb56674 100644 --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c @@ -133,9 +133,11 @@ static int tegra124_dfll_fcpu_remove(struct platform_device *pdev) struct tegra_dfll_soc_data *soc; soc = tegra_dfll_unregister(pdev); - if (IS_ERR(soc)) + if (IS_ERR(soc)) { dev_err(&pdev->dev, "failed to unregister DFLL: %ld\n", PTR_ERR(soc)); + return PTR_ERR(soc); + } tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq); diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index 8d77090ad94a..0241450f3eb3 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -403,8 +403,10 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div, num_dividers = i; tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL); - if (!tmp) + if (!tmp) { + *table = ERR_PTR(-ENOMEM); return -ENOMEM; + } valid_div = 0; *width = 0; @@ -439,6 +441,7 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup) { struct clk_omap_divider *div; struct clk_omap_reg *reg; + int ret; if (!setup) return NULL; @@ -458,6 +461,12 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup) div->flags |= CLK_DIVIDER_POWER_OF_TWO; div->table = _get_div_table_from_setup(setup, &div->width); + if (IS_ERR(div->table)) { + ret = PTR_ERR(div->table); + kfree(div); + return ERR_PTR(ret); + } + div->shift = setup->bit_shift; div->latch = -EINVAL; diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c index f65cc0ff76ab..b0908ec62f73 100644 --- a/drivers/clk/zynqmp/clkc.c +++ b/drivers/clk/zynqmp/clkc.c @@ -669,8 +669,8 @@ static int zynqmp_clk_setup(struct device_node *np) if (ret) return ret; - zynqmp_data = kzalloc(sizeof(*zynqmp_data) + sizeof(*zynqmp_data) * - clock_max_idx, GFP_KERNEL); + zynqmp_data = kzalloc(struct_size(zynqmp_data, hws, clock_max_idx), + GFP_KERNEL); if (!zynqmp_data) return -ENOMEM; diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index 595124074821..c364027638e1 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -154,6 +154,10 @@ static int omap_dm_timer_of_set_source(struct omap_dm_timer *timer) if (IS_ERR(parent)) return -ENODEV; + /* Bail out if both clocks point to fck */ + if (clk_is_match(parent, timer->fclk)) + return 0; + ret = clk_set_parent(timer->fclk, parent); if (ret < 0) pr_err("%s: failed to set parent\n", __func__); @@ -864,7 +868,6 @@ static int omap_dm_timer_probe(struct platform_device *pdev) timer->pdev = pdev; pm_runtime_enable(dev); - pm_runtime_irq_safe(dev); if (!timer->reserved) { ret = pm_runtime_get_sync(dev); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 6f23ebb395f1..e35a886e00bc 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1530,17 +1530,16 @@ static unsigned int __cpufreq_get(struct cpufreq_policy *policy) { unsigned int ret_freq = 0; - if (!cpufreq_driver->get) + if (unlikely(policy_is_inactive(policy)) || !cpufreq_driver->get) return ret_freq; ret_freq = cpufreq_driver->get(policy->cpu); /* - * Updating inactive policies is invalid, so avoid doing that. Also - * if fast frequency switching is used with the given policy, the check + * If fast frequency switching is used with the given policy, the check * against policy->cur is pointless, so skip it in that case too. */ - if (unlikely(policy_is_inactive(policy)) || policy->fast_switch_enabled) + if (policy->fast_switch_enabled) return ret_freq; if (ret_freq && policy->cur && @@ -1569,10 +1568,7 @@ unsigned int cpufreq_get(unsigned int cpu) if (policy) { down_read(&policy->rwsem); - - if (!policy_is_inactive(policy)) - ret_freq = __cpufreq_get(policy); - + ret_freq = __cpufreq_get(policy); up_read(&policy->rwsem); cpufreq_cpu_put(policy); diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c index 50b1551ba894..9ed46d188cb5 100644 --- a/drivers/cpufreq/scmi-cpufreq.c +++ b/drivers/cpufreq/scmi-cpufreq.c @@ -52,9 +52,9 @@ scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index) int ret; struct scmi_data *priv = policy->driver_data; struct scmi_perf_ops *perf_ops = handle->perf_ops; - u64 freq = policy->freq_table[index].frequency * 1000; + u64 freq = policy->freq_table[index].frequency; - ret = perf_ops->freq_set(handle, priv->domain_id, freq, false); + ret = perf_ops->freq_set(handle, priv->domain_id, freq * 1000, false); if (!ret) arch_set_freq_scale(policy->related_cpus, freq, policy->cpuinfo.max_freq); @@ -176,7 +176,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy) out_free_priv: kfree(priv); out_free_opp: - dev_pm_opp_cpumask_remove_table(policy->cpus); + dev_pm_opp_remove_all_dynamic(cpu_dev); return ret; } @@ -187,8 +187,8 @@ static int scmi_cpufreq_exit(struct cpufreq_policy *policy) cpufreq_cooling_unregister(priv->cdev); dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); + dev_pm_opp_remove_all_dynamic(priv->cpu_dev); kfree(priv); - dev_pm_opp_cpumask_remove_table(policy->related_cpus); return 0; } diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c index 87a98ec77773..99449738faa4 100644 --- a/drivers/cpufreq/scpi-cpufreq.c +++ b/drivers/cpufreq/scpi-cpufreq.c @@ -177,7 +177,7 @@ out_free_cpufreq_table: out_free_priv: kfree(priv); out_free_opp: - dev_pm_opp_cpumask_remove_table(policy->cpus); + dev_pm_opp_remove_all_dynamic(cpu_dev); return ret; } @@ -190,7 +190,7 @@ static int scpi_cpufreq_exit(struct cpufreq_policy *policy) clk_put(priv->clk); dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); kfree(priv); - dev_pm_opp_cpumask_remove_table(policy->related_cpus); + dev_pm_opp_remove_all_dynamic(priv->cpu_dev); return 0; } diff --git a/drivers/cpuidle/poll_state.c b/drivers/cpuidle/poll_state.c index b17d153e724f..23a1b27579a5 100644 --- a/drivers/cpuidle/poll_state.c +++ b/drivers/cpuidle/poll_state.c @@ -21,7 +21,7 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev, local_irq_enable(); if (!current_set_polling_and_test()) { unsigned int loop_count = 0; - u64 limit = TICK_USEC; + u64 limit = TICK_NSEC; int i; for (i = 1; i < drv->state_count; i++) { diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 5a90075f719d..0be55fcc19ba 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -692,6 +692,7 @@ config CRYPTO_DEV_BCM_SPU depends on ARCH_BCM_IPROC depends on MAILBOX default m + select CRYPTO_AUTHENC select CRYPTO_DES select CRYPTO_MD5 select CRYPTO_SHA1 diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 63cb6956c948..acf79889d903 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -283,9 +283,9 @@ static u32 crypto4xx_put_pd_to_pdr(struct crypto4xx_device *dev, u32 idx) */ static u32 crypto4xx_build_gdr(struct crypto4xx_device *dev) { - dev->gdr = dma_zalloc_coherent(dev->core_dev->device, - sizeof(struct ce_gd) * PPC4XX_NUM_GD, - &dev->gdr_pa, GFP_ATOMIC); + dev->gdr = dma_alloc_coherent(dev->core_dev->device, + sizeof(struct ce_gd) * PPC4XX_NUM_GD, + &dev->gdr_pa, GFP_ATOMIC); if (!dev->gdr) return -ENOMEM; diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c index c9393ffb70ed..5567cbda2798 100644 --- a/drivers/crypto/bcm/cipher.c +++ b/drivers/crypto/bcm/cipher.c @@ -2845,44 +2845,28 @@ static int aead_authenc_setkey(struct crypto_aead *cipher, struct spu_hw *spu = &iproc_priv.spu; struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher); struct crypto_tfm *tfm = crypto_aead_tfm(cipher); - struct rtattr *rta = (void *)key; - struct crypto_authenc_key_param *param; - const u8 *origkey = key; - const unsigned int origkeylen = keylen; - - int ret = 0; + struct crypto_authenc_keys keys; + int ret; flow_log("%s() aead:%p key:%p keylen:%u\n", __func__, cipher, key, keylen); flow_dump(" key: ", key, keylen); - if (!RTA_OK(rta, keylen)) - goto badkey; - if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM) - goto badkey; - if (RTA_PAYLOAD(rta) < sizeof(*param)) + ret = crypto_authenc_extractkeys(&keys, key, keylen); + if (ret) goto badkey; - param = RTA_DATA(rta); - ctx->enckeylen = be32_to_cpu(param->enckeylen); - - key += RTA_ALIGN(rta->rta_len); - keylen -= RTA_ALIGN(rta->rta_len); - - if (keylen < ctx->enckeylen) - goto badkey; - if (ctx->enckeylen > MAX_KEY_SIZE) + if (keys.enckeylen > MAX_KEY_SIZE || + keys.authkeylen > MAX_KEY_SIZE) goto badkey; - ctx->authkeylen = keylen - ctx->enckeylen; - - if (ctx->authkeylen > MAX_KEY_SIZE) - goto badkey; + ctx->enckeylen = keys.enckeylen; + ctx->authkeylen = keys.authkeylen; - memcpy(ctx->enckey, key + ctx->authkeylen, ctx->enckeylen); + memcpy(ctx->enckey, keys.enckey, keys.enckeylen); /* May end up padding auth key. So make sure it's zeroed. */ memset(ctx->authkey, 0, sizeof(ctx->authkey)); - memcpy(ctx->authkey, key, ctx->authkeylen); + memcpy(ctx->authkey, keys.authkey, keys.authkeylen); switch (ctx->alg->cipher_info.alg) { case CIPHER_ALG_DES: @@ -2890,7 +2874,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher, u32 tmp[DES_EXPKEY_WORDS]; u32 flags = CRYPTO_TFM_RES_WEAK_KEY; - if (des_ekey(tmp, key) == 0) { + if (des_ekey(tmp, keys.enckey) == 0) { if (crypto_aead_get_flags(cipher) & CRYPTO_TFM_REQ_WEAK_KEY) { crypto_aead_set_flags(cipher, flags); @@ -2905,7 +2889,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher, break; case CIPHER_ALG_3DES: if (ctx->enckeylen == (DES_KEY_SIZE * 3)) { - const u32 *K = (const u32 *)key; + const u32 *K = (const u32 *)keys.enckey; u32 flags = CRYPTO_TFM_RES_BAD_KEY_SCHED; if (!((K[0] ^ K[2]) | (K[1] ^ K[3])) || @@ -2956,9 +2940,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher, ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK; ctx->fallback_cipher->base.crt_flags |= tfm->crt_flags & CRYPTO_TFM_REQ_MASK; - ret = - crypto_aead_setkey(ctx->fallback_cipher, origkey, - origkeylen); + ret = crypto_aead_setkey(ctx->fallback_cipher, key, keylen); if (ret) { flow_log(" fallback setkey() returned:%d\n", ret); tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 92e593e2069a..80ae69f906fb 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -3476,7 +3476,7 @@ static int __init caam_algapi_init(void) * Skip algorithms requiring message digests * if MD or MD size is not supported by device. */ - if ((c2_alg_sel & ~OP_ALG_ALGSEL_SUBMASK) == 0x40 && + if (is_mdha(c2_alg_sel) && (!md_inst || t_alg->aead.maxauthsize > md_limit)) continue; diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index 81712aa5d0f2..bb1a2cdf1951 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c @@ -1072,13 +1072,16 @@ static int ahash_final_no_ctx(struct ahash_request *req) desc = edesc->hw_desc; - state->buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE); - if (dma_mapping_error(jrdev, state->buf_dma)) { - dev_err(jrdev, "unable to map src\n"); - goto unmap; - } + if (buflen) { + state->buf_dma = dma_map_single(jrdev, buf, buflen, + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, state->buf_dma)) { + dev_err(jrdev, "unable to map src\n"); + goto unmap; + } - append_seq_in_ptr(desc, state->buf_dma, buflen, 0); + append_seq_in_ptr(desc, state->buf_dma, buflen, 0); + } edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result, digestsize); diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h index ec10230178c5..4b6854bf896a 100644 --- a/drivers/crypto/caam/desc.h +++ b/drivers/crypto/caam/desc.h @@ -1155,6 +1155,7 @@ #define OP_ALG_ALGSEL_DES (0x20 << OP_ALG_ALGSEL_SHIFT) #define OP_ALG_ALGSEL_3DES (0x21 << OP_ALG_ALGSEL_SHIFT) #define OP_ALG_ALGSEL_ARC4 (0x30 << OP_ALG_ALGSEL_SHIFT) +#define OP_ALG_CHA_MDHA (0x40 << OP_ALG_ALGSEL_SHIFT) #define OP_ALG_ALGSEL_MD5 (0x40 << OP_ALG_ALGSEL_SHIFT) #define OP_ALG_ALGSEL_SHA1 (0x41 << OP_ALG_ALGSEL_SHIFT) #define OP_ALG_ALGSEL_SHA224 (0x42 << OP_ALG_ALGSEL_SHIFT) diff --git a/drivers/crypto/caam/error.h b/drivers/crypto/caam/error.h index 67ea94079837..8c6b83e02a70 100644 --- a/drivers/crypto/caam/error.h +++ b/drivers/crypto/caam/error.h @@ -7,6 +7,9 @@ #ifndef CAAM_ERROR_H #define CAAM_ERROR_H + +#include "desc.h" + #define CAAM_ERROR_STR_MAX 302 void caam_strstatus(struct device *dev, u32 status, bool qi_v2); @@ -17,4 +20,10 @@ void caam_strstatus(struct device *dev, u32 status, bool qi_v2); void caam_dump_sg(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, struct scatterlist *sg, size_t tlen, bool ascii); + +static inline bool is_mdha(u32 algtype) +{ + return (algtype & OP_ALG_ALGSEL_MASK & ~OP_ALG_ALGSEL_SUBMASK) == + OP_ALG_CHA_MDHA; +} #endif /* CAAM_ERROR_H */ diff --git a/drivers/crypto/cavium/cpt/cptpf_main.c b/drivers/crypto/cavium/cpt/cptpf_main.c index 06ad85ab5e86..a876535529d1 100644 --- a/drivers/crypto/cavium/cpt/cptpf_main.c +++ b/drivers/crypto/cavium/cpt/cptpf_main.c @@ -278,8 +278,8 @@ static int cpt_ucode_load_fw(struct cpt_device *cpt, const u8 *fw, bool is_ae) mcode->num_cores = is_ae ? 6 : 10; /* Allocate DMAable space */ - mcode->code = dma_zalloc_coherent(&cpt->pdev->dev, mcode->code_size, - &mcode->phys_base, GFP_KERNEL); + mcode->code = dma_alloc_coherent(&cpt->pdev->dev, mcode->code_size, + &mcode->phys_base, GFP_KERNEL); if (!mcode->code) { dev_err(dev, "Unable to allocate space for microcode"); ret = -ENOMEM; diff --git a/drivers/crypto/cavium/cpt/cptvf_main.c b/drivers/crypto/cavium/cpt/cptvf_main.c index 5c796ed55eba..2ca431ed1db8 100644 --- a/drivers/crypto/cavium/cpt/cptvf_main.c +++ b/drivers/crypto/cavium/cpt/cptvf_main.c @@ -236,9 +236,10 @@ static int alloc_command_queues(struct cpt_vf *cptvf, c_size = (rem_q_size > qcsize_bytes) ? qcsize_bytes : rem_q_size; - curr->head = (u8 *)dma_zalloc_coherent(&pdev->dev, - c_size + CPT_NEXT_CHUNK_PTR_SIZE, - &curr->dma_addr, GFP_KERNEL); + curr->head = (u8 *)dma_alloc_coherent(&pdev->dev, + c_size + CPT_NEXT_CHUNK_PTR_SIZE, + &curr->dma_addr, + GFP_KERNEL); if (!curr->head) { dev_err(&pdev->dev, "Command Q (%d) chunk (%d) allocation failed\n", i, queue->nchunks); diff --git a/drivers/crypto/cavium/nitrox/nitrox_lib.c b/drivers/crypto/cavium/nitrox/nitrox_lib.c index 9138bae12521..4ace9bcd603a 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_lib.c +++ b/drivers/crypto/cavium/nitrox/nitrox_lib.c @@ -25,9 +25,9 @@ static int nitrox_cmdq_init(struct nitrox_cmdq *cmdq, int align_bytes) struct nitrox_device *ndev = cmdq->ndev; cmdq->qsize = (ndev->qlen * cmdq->instr_size) + align_bytes; - cmdq->unalign_base = dma_zalloc_coherent(DEV(ndev), cmdq->qsize, - &cmdq->unalign_dma, - GFP_KERNEL); + cmdq->unalign_base = dma_alloc_coherent(DEV(ndev), cmdq->qsize, + &cmdq->unalign_dma, + GFP_KERNEL); if (!cmdq->unalign_base) return -ENOMEM; diff --git a/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c b/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c index e34e4df8fd24..4c97478d44bd 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c +++ b/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c @@ -537,6 +537,8 @@ static void process_response_list(struct nitrox_cmdq *cmdq) struct nitrox_device *ndev = cmdq->ndev; struct nitrox_softreq *sr; int req_completed = 0, err = 0, budget; + completion_t callback; + void *cb_arg; /* check all pending requests */ budget = atomic_read(&cmdq->pending_count); @@ -564,13 +566,13 @@ static void process_response_list(struct nitrox_cmdq *cmdq) smp_mb__after_atomic(); /* remove from response list */ response_list_del(sr, cmdq); - /* ORH error code */ err = READ_ONCE(*sr->resp.orh) & 0xff; + callback = sr->callback; + cb_arg = sr->cb_arg; softreq_destroy(sr); - - if (sr->callback) - sr->callback(sr->cb_arg, err); + if (callback) + callback(cb_arg, err); req_completed++; } diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c index 44a4d2779b15..c9bfd4f439ce 100644 --- a/drivers/crypto/ccp/ccp-dev-v5.c +++ b/drivers/crypto/ccp/ccp-dev-v5.c @@ -822,9 +822,9 @@ static int ccp5_init(struct ccp_device *ccp) /* Page alignment satisfies our needs for N <= 128 */ BUILD_BUG_ON(COMMANDS_PER_QUEUE > 128); cmd_q->qsize = Q_SIZE(Q_DESC_SIZE); - cmd_q->qbase = dma_zalloc_coherent(dev, cmd_q->qsize, - &cmd_q->qbase_dma, - GFP_KERNEL); + cmd_q->qbase = dma_alloc_coherent(dev, cmd_q->qsize, + &cmd_q->qbase_dma, + GFP_KERNEL); if (!cmd_q->qbase) { dev_err(dev, "unable to allocate command queue\n"); ret = -ENOMEM; diff --git a/drivers/crypto/ccree/cc_aead.c b/drivers/crypto/ccree/cc_aead.c index f2643cda45db..a3527c00b29a 100644 --- a/drivers/crypto/ccree/cc_aead.c +++ b/drivers/crypto/ccree/cc_aead.c @@ -549,13 +549,12 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) { struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); - struct rtattr *rta = (struct rtattr *)key; struct cc_crypto_req cc_req = {}; - struct crypto_authenc_key_param *param; struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ]; - int rc = -EINVAL; unsigned int seq_len = 0; struct device *dev = drvdata_to_dev(ctx->drvdata); + const u8 *enckey, *authkey; + int rc; dev_dbg(dev, "Setting key in context @%p for %s. key=%p keylen=%u\n", ctx, crypto_tfm_alg_name(crypto_aead_tfm(tfm)), key, keylen); @@ -563,35 +562,33 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key, /* STAT_PHASE_0: Init and sanity checks */ if (ctx->auth_mode != DRV_HASH_NULL) { /* authenc() alg. */ - if (!RTA_OK(rta, keylen)) - goto badkey; - if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM) - goto badkey; - if (RTA_PAYLOAD(rta) < sizeof(*param)) - goto badkey; - param = RTA_DATA(rta); - ctx->enc_keylen = be32_to_cpu(param->enckeylen); - key += RTA_ALIGN(rta->rta_len); - keylen -= RTA_ALIGN(rta->rta_len); - if (keylen < ctx->enc_keylen) + struct crypto_authenc_keys keys; + + rc = crypto_authenc_extractkeys(&keys, key, keylen); + if (rc) goto badkey; - ctx->auth_keylen = keylen - ctx->enc_keylen; + enckey = keys.enckey; + authkey = keys.authkey; + ctx->enc_keylen = keys.enckeylen; + ctx->auth_keylen = keys.authkeylen; if (ctx->cipher_mode == DRV_CIPHER_CTR) { /* the nonce is stored in bytes at end of key */ + rc = -EINVAL; if (ctx->enc_keylen < (AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE)) goto badkey; /* Copy nonce from last 4 bytes in CTR key to * first 4 bytes in CTR IV */ - memcpy(ctx->ctr_nonce, key + ctx->auth_keylen + - ctx->enc_keylen - CTR_RFC3686_NONCE_SIZE, - CTR_RFC3686_NONCE_SIZE); + memcpy(ctx->ctr_nonce, enckey + ctx->enc_keylen - + CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE); /* Set CTR key size */ ctx->enc_keylen -= CTR_RFC3686_NONCE_SIZE; } } else { /* non-authenc - has just one key */ + enckey = key; + authkey = NULL; ctx->enc_keylen = keylen; ctx->auth_keylen = 0; } @@ -603,13 +600,14 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key, /* STAT_PHASE_1: Copy key to ctx */ /* Get key material */ - memcpy(ctx->enckey, key + ctx->auth_keylen, ctx->enc_keylen); + memcpy(ctx->enckey, enckey, ctx->enc_keylen); if (ctx->enc_keylen == 24) memset(ctx->enckey + 24, 0, CC_AES_KEY_SIZE_MAX - 24); if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { - memcpy(ctx->auth_state.xcbc.xcbc_keys, key, ctx->auth_keylen); + memcpy(ctx->auth_state.xcbc.xcbc_keys, authkey, + ctx->auth_keylen); } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC */ - rc = cc_get_plain_hmac_key(tfm, key, ctx->auth_keylen); + rc = cc_get_plain_hmac_key(tfm, authkey, ctx->auth_keylen); if (rc) goto badkey; } diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c index 8ada308d72ee..b0125ad65825 100644 --- a/drivers/crypto/ccree/cc_driver.c +++ b/drivers/crypto/ccree/cc_driver.c @@ -380,7 +380,7 @@ static int init_cc_resources(struct platform_device *plat_dev) rc = cc_ivgen_init(new_drvdata); if (rc) { dev_err(dev, "cc_ivgen_init failed\n"); - goto post_power_mgr_err; + goto post_buf_mgr_err; } /* Allocate crypto algs */ @@ -403,6 +403,9 @@ static int init_cc_resources(struct platform_device *plat_dev) goto post_hash_err; } + /* All set, we can allow autosuspend */ + cc_pm_go(new_drvdata); + /* If we got here and FIPS mode is enabled * it means all FIPS test passed, so let TEE * know we're good. @@ -417,8 +420,6 @@ post_cipher_err: cc_cipher_free(new_drvdata); post_ivgen_err: cc_ivgen_fini(new_drvdata); -post_power_mgr_err: - cc_pm_fini(new_drvdata); post_buf_mgr_err: cc_buffer_mgr_fini(new_drvdata); post_req_mgr_err: diff --git a/drivers/crypto/ccree/cc_pm.c b/drivers/crypto/ccree/cc_pm.c index d990f472e89f..6ff7e75ad90e 100644 --- a/drivers/crypto/ccree/cc_pm.c +++ b/drivers/crypto/ccree/cc_pm.c @@ -100,20 +100,19 @@ int cc_pm_put_suspend(struct device *dev) int cc_pm_init(struct cc_drvdata *drvdata) { - int rc = 0; struct device *dev = drvdata_to_dev(drvdata); /* must be before the enabling to avoid resdundent suspending */ pm_runtime_set_autosuspend_delay(dev, CC_SUSPEND_TIMEOUT); pm_runtime_use_autosuspend(dev); /* activate the PM module */ - rc = pm_runtime_set_active(dev); - if (rc) - return rc; - /* enable the PM module*/ - pm_runtime_enable(dev); + return pm_runtime_set_active(dev); +} - return rc; +/* enable the PM module*/ +void cc_pm_go(struct cc_drvdata *drvdata) +{ + pm_runtime_enable(drvdata_to_dev(drvdata)); } void cc_pm_fini(struct cc_drvdata *drvdata) diff --git a/drivers/crypto/ccree/cc_pm.h b/drivers/crypto/ccree/cc_pm.h index 020a5403c58b..907a6db4d6c0 100644 --- a/drivers/crypto/ccree/cc_pm.h +++ b/drivers/crypto/ccree/cc_pm.h @@ -16,6 +16,7 @@ extern const struct dev_pm_ops ccree_pm; int cc_pm_init(struct cc_drvdata *drvdata); +void cc_pm_go(struct cc_drvdata *drvdata); void cc_pm_fini(struct cc_drvdata *drvdata); int cc_pm_suspend(struct device *dev); int cc_pm_resume(struct device *dev); @@ -29,6 +30,8 @@ static inline int cc_pm_init(struct cc_drvdata *drvdata) return 0; } +static inline void cc_pm_go(struct cc_drvdata *drvdata) {} + static inline void cc_pm_fini(struct cc_drvdata *drvdata) {} static inline int cc_pm_suspend(struct device *dev) diff --git a/drivers/crypto/hisilicon/sec/sec_algs.c b/drivers/crypto/hisilicon/sec/sec_algs.c index cdc4f9a171d9..adc0cd8ae97b 100644 --- a/drivers/crypto/hisilicon/sec/sec_algs.c +++ b/drivers/crypto/hisilicon/sec/sec_algs.c @@ -241,8 +241,8 @@ static int sec_alg_skcipher_setkey(struct crypto_skcipher *tfm, memset(ctx->key, 0, SEC_MAX_CIPHER_KEY); } else { /* new key */ - ctx->key = dma_zalloc_coherent(dev, SEC_MAX_CIPHER_KEY, - &ctx->pkey, GFP_KERNEL); + ctx->key = dma_alloc_coherent(dev, SEC_MAX_CIPHER_KEY, + &ctx->pkey, GFP_KERNEL); if (!ctx->key) { mutex_unlock(&ctx->lock); return -ENOMEM; diff --git a/drivers/crypto/hisilicon/sec/sec_drv.c b/drivers/crypto/hisilicon/sec/sec_drv.c index c1ee4e7bf996..91ee2bb575df 100644 --- a/drivers/crypto/hisilicon/sec/sec_drv.c +++ b/drivers/crypto/hisilicon/sec/sec_drv.c @@ -1082,9 +1082,8 @@ static int sec_queue_res_cfg(struct sec_queue *queue) struct sec_queue_ring_db *ring_db = &queue->ring_db; int ret; - ring_cmd->vaddr = dma_zalloc_coherent(dev, SEC_Q_CMD_SIZE, - &ring_cmd->paddr, - GFP_KERNEL); + ring_cmd->vaddr = dma_alloc_coherent(dev, SEC_Q_CMD_SIZE, + &ring_cmd->paddr, GFP_KERNEL); if (!ring_cmd->vaddr) return -ENOMEM; @@ -1092,17 +1091,15 @@ static int sec_queue_res_cfg(struct sec_queue *queue) mutex_init(&ring_cmd->lock); ring_cmd->callback = sec_alg_callback; - ring_cq->vaddr = dma_zalloc_coherent(dev, SEC_Q_CQ_SIZE, - &ring_cq->paddr, - GFP_KERNEL); + ring_cq->vaddr = dma_alloc_coherent(dev, SEC_Q_CQ_SIZE, + &ring_cq->paddr, GFP_KERNEL); if (!ring_cq->vaddr) { ret = -ENOMEM; goto err_free_ring_cmd; } - ring_db->vaddr = dma_zalloc_coherent(dev, SEC_Q_DB_SIZE, - &ring_db->paddr, - GFP_KERNEL); + ring_db->vaddr = dma_alloc_coherent(dev, SEC_Q_DB_SIZE, + &ring_db->paddr, GFP_KERNEL); if (!ring_db->vaddr) { ret = -ENOMEM; goto err_free_ring_cq; diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index 19fba998b86b..1b0d156bb9be 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -260,9 +260,9 @@ static int setup_crypt_desc(void) { struct device *dev = &pdev->dev; BUILD_BUG_ON(sizeof(struct crypt_ctl) != 64); - crypt_virt = dma_zalloc_coherent(dev, - NPE_QLEN * sizeof(struct crypt_ctl), - &crypt_phys, GFP_ATOMIC); + crypt_virt = dma_alloc_coherent(dev, + NPE_QLEN * sizeof(struct crypt_ctl), + &crypt_phys, GFP_ATOMIC); if (!crypt_virt) return -ENOMEM; return 0; diff --git a/drivers/crypto/mediatek/mtk-platform.c b/drivers/crypto/mediatek/mtk-platform.c index ee0404e27a0f..5660e5e5e022 100644 --- a/drivers/crypto/mediatek/mtk-platform.c +++ b/drivers/crypto/mediatek/mtk-platform.c @@ -453,17 +453,17 @@ static int mtk_desc_ring_alloc(struct mtk_cryp *cryp) if (!ring[i]) goto err_cleanup; - ring[i]->cmd_base = dma_zalloc_coherent(cryp->dev, - MTK_DESC_RING_SZ, - &ring[i]->cmd_dma, - GFP_KERNEL); + ring[i]->cmd_base = dma_alloc_coherent(cryp->dev, + MTK_DESC_RING_SZ, + &ring[i]->cmd_dma, + GFP_KERNEL); if (!ring[i]->cmd_base) goto err_cleanup; - ring[i]->res_base = dma_zalloc_coherent(cryp->dev, - MTK_DESC_RING_SZ, - &ring[i]->res_dma, - GFP_KERNEL); + ring[i]->res_base = dma_alloc_coherent(cryp->dev, + MTK_DESC_RING_SZ, + &ring[i]->res_dma, + GFP_KERNEL); if (!ring[i]->res_base) goto err_cleanup; diff --git a/drivers/crypto/qat/qat_common/adf_admin.c b/drivers/crypto/qat/qat_common/adf_admin.c index 3744b22f0c46..d28cba34773e 100644 --- a/drivers/crypto/qat/qat_common/adf_admin.c +++ b/drivers/crypto/qat/qat_common/adf_admin.c @@ -244,18 +244,18 @@ int adf_init_admin_comms(struct adf_accel_dev *accel_dev) dev_to_node(&GET_DEV(accel_dev))); if (!admin) return -ENOMEM; - admin->virt_addr = dma_zalloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE, - &admin->phy_addr, GFP_KERNEL); + admin->virt_addr = dma_alloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE, + &admin->phy_addr, GFP_KERNEL); if (!admin->virt_addr) { dev_err(&GET_DEV(accel_dev), "Failed to allocate dma buff\n"); kfree(admin); return -ENOMEM; } - admin->virt_tbl_addr = dma_zalloc_coherent(&GET_DEV(accel_dev), - PAGE_SIZE, - &admin->const_tbl_addr, - GFP_KERNEL); + admin->virt_tbl_addr = dma_alloc_coherent(&GET_DEV(accel_dev), + PAGE_SIZE, + &admin->const_tbl_addr, + GFP_KERNEL); if (!admin->virt_tbl_addr) { dev_err(&GET_DEV(accel_dev), "Failed to allocate const_tbl\n"); dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE, diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c index d2698299896f..975c75198f56 100644 --- a/drivers/crypto/qat/qat_common/qat_algs.c +++ b/drivers/crypto/qat/qat_common/qat_algs.c @@ -601,15 +601,15 @@ static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key, dev = &GET_DEV(inst->accel_dev); ctx->inst = inst; - ctx->enc_cd = dma_zalloc_coherent(dev, sizeof(*ctx->enc_cd), - &ctx->enc_cd_paddr, - GFP_ATOMIC); + ctx->enc_cd = dma_alloc_coherent(dev, sizeof(*ctx->enc_cd), + &ctx->enc_cd_paddr, + GFP_ATOMIC); if (!ctx->enc_cd) { return -ENOMEM; } - ctx->dec_cd = dma_zalloc_coherent(dev, sizeof(*ctx->dec_cd), - &ctx->dec_cd_paddr, - GFP_ATOMIC); + ctx->dec_cd = dma_alloc_coherent(dev, sizeof(*ctx->dec_cd), + &ctx->dec_cd_paddr, + GFP_ATOMIC); if (!ctx->dec_cd) { goto out_free_enc; } @@ -933,16 +933,16 @@ static int qat_alg_ablkcipher_setkey(struct crypto_ablkcipher *tfm, dev = &GET_DEV(inst->accel_dev); ctx->inst = inst; - ctx->enc_cd = dma_zalloc_coherent(dev, sizeof(*ctx->enc_cd), - &ctx->enc_cd_paddr, - GFP_ATOMIC); + ctx->enc_cd = dma_alloc_coherent(dev, sizeof(*ctx->enc_cd), + &ctx->enc_cd_paddr, + GFP_ATOMIC); if (!ctx->enc_cd) { spin_unlock(&ctx->lock); return -ENOMEM; } - ctx->dec_cd = dma_zalloc_coherent(dev, sizeof(*ctx->dec_cd), - &ctx->dec_cd_paddr, - GFP_ATOMIC); + ctx->dec_cd = dma_alloc_coherent(dev, sizeof(*ctx->dec_cd), + &ctx->dec_cd_paddr, + GFP_ATOMIC); if (!ctx->dec_cd) { spin_unlock(&ctx->lock); goto out_free_enc; diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c index 320e7854b4ee..c9f324730d71 100644 --- a/drivers/crypto/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c @@ -332,10 +332,10 @@ static int qat_dh_compute_value(struct kpp_request *req) } else { int shift = ctx->p_size - req->src_len; - qat_req->src_align = dma_zalloc_coherent(dev, - ctx->p_size, - &qat_req->in.dh.in.b, - GFP_KERNEL); + qat_req->src_align = dma_alloc_coherent(dev, + ctx->p_size, + &qat_req->in.dh.in.b, + GFP_KERNEL); if (unlikely(!qat_req->src_align)) return ret; @@ -360,9 +360,9 @@ static int qat_dh_compute_value(struct kpp_request *req) goto unmap_src; } else { - qat_req->dst_align = dma_zalloc_coherent(dev, ctx->p_size, - &qat_req->out.dh.r, - GFP_KERNEL); + qat_req->dst_align = dma_alloc_coherent(dev, ctx->p_size, + &qat_req->out.dh.r, + GFP_KERNEL); if (unlikely(!qat_req->dst_align)) goto unmap_src; } @@ -447,7 +447,7 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params) return -EINVAL; ctx->p_size = params->p_size; - ctx->p = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_p, GFP_KERNEL); + ctx->p = dma_alloc_coherent(dev, ctx->p_size, &ctx->dma_p, GFP_KERNEL); if (!ctx->p) return -ENOMEM; memcpy(ctx->p, params->p, ctx->p_size); @@ -458,7 +458,7 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params) return 0; } - ctx->g = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_g, GFP_KERNEL); + ctx->g = dma_alloc_coherent(dev, ctx->p_size, &ctx->dma_g, GFP_KERNEL); if (!ctx->g) return -ENOMEM; memcpy(ctx->g + (ctx->p_size - params->g_size), params->g, @@ -503,8 +503,8 @@ static int qat_dh_set_secret(struct crypto_kpp *tfm, const void *buf, if (ret < 0) goto err_clear_ctx; - ctx->xa = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_xa, - GFP_KERNEL); + ctx->xa = dma_alloc_coherent(dev, ctx->p_size, &ctx->dma_xa, + GFP_KERNEL); if (!ctx->xa) { ret = -ENOMEM; goto err_clear_ctx; @@ -737,9 +737,9 @@ static int qat_rsa_enc(struct akcipher_request *req) } else { int shift = ctx->key_sz - req->src_len; - qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz, - &qat_req->in.rsa.enc.m, - GFP_KERNEL); + qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz, + &qat_req->in.rsa.enc.m, + GFP_KERNEL); if (unlikely(!qat_req->src_align)) return ret; @@ -756,9 +756,9 @@ static int qat_rsa_enc(struct akcipher_request *req) goto unmap_src; } else { - qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz, - &qat_req->out.rsa.enc.c, - GFP_KERNEL); + qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz, + &qat_req->out.rsa.enc.c, + GFP_KERNEL); if (unlikely(!qat_req->dst_align)) goto unmap_src; @@ -881,9 +881,9 @@ static int qat_rsa_dec(struct akcipher_request *req) } else { int shift = ctx->key_sz - req->src_len; - qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz, - &qat_req->in.rsa.dec.c, - GFP_KERNEL); + qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz, + &qat_req->in.rsa.dec.c, + GFP_KERNEL); if (unlikely(!qat_req->src_align)) return ret; @@ -900,9 +900,9 @@ static int qat_rsa_dec(struct akcipher_request *req) goto unmap_src; } else { - qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz, - &qat_req->out.rsa.dec.m, - GFP_KERNEL); + qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz, + &qat_req->out.rsa.dec.m, + GFP_KERNEL); if (unlikely(!qat_req->dst_align)) goto unmap_src; @@ -989,7 +989,7 @@ static int qat_rsa_set_n(struct qat_rsa_ctx *ctx, const char *value, goto err; ret = -ENOMEM; - ctx->n = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_n, GFP_KERNEL); + ctx->n = dma_alloc_coherent(dev, ctx->key_sz, &ctx->dma_n, GFP_KERNEL); if (!ctx->n) goto err; @@ -1018,7 +1018,7 @@ static int qat_rsa_set_e(struct qat_rsa_ctx *ctx, const char *value, return -EINVAL; } - ctx->e = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_e, GFP_KERNEL); + ctx->e = dma_alloc_coherent(dev, ctx->key_sz, &ctx->dma_e, GFP_KERNEL); if (!ctx->e) return -ENOMEM; @@ -1044,7 +1044,7 @@ static int qat_rsa_set_d(struct qat_rsa_ctx *ctx, const char *value, goto err; ret = -ENOMEM; - ctx->d = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL); + ctx->d = dma_alloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL); if (!ctx->d) goto err; @@ -1077,7 +1077,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key) qat_rsa_drop_leading_zeros(&ptr, &len); if (!len) goto err; - ctx->p = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_p, GFP_KERNEL); + ctx->p = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_p, GFP_KERNEL); if (!ctx->p) goto err; memcpy(ctx->p + (half_key_sz - len), ptr, len); @@ -1088,7 +1088,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key) qat_rsa_drop_leading_zeros(&ptr, &len); if (!len) goto free_p; - ctx->q = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_q, GFP_KERNEL); + ctx->q = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_q, GFP_KERNEL); if (!ctx->q) goto free_p; memcpy(ctx->q + (half_key_sz - len), ptr, len); @@ -1099,8 +1099,8 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key) qat_rsa_drop_leading_zeros(&ptr, &len); if (!len) goto free_q; - ctx->dp = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_dp, - GFP_KERNEL); + ctx->dp = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dp, + GFP_KERNEL); if (!ctx->dp) goto free_q; memcpy(ctx->dp + (half_key_sz - len), ptr, len); @@ -1111,8 +1111,8 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key) qat_rsa_drop_leading_zeros(&ptr, &len); if (!len) goto free_dp; - ctx->dq = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_dq, - GFP_KERNEL); + ctx->dq = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dq, + GFP_KERNEL); if (!ctx->dq) goto free_dp; memcpy(ctx->dq + (half_key_sz - len), ptr, len); @@ -1123,8 +1123,8 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key) qat_rsa_drop_leading_zeros(&ptr, &len); if (!len) goto free_dq; - ctx->qinv = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_qinv, - GFP_KERNEL); + ctx->qinv = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_qinv, + GFP_KERNEL); if (!ctx->qinv) goto free_dq; memcpy(ctx->qinv + (half_key_sz - len), ptr, len); diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 45e20707cef8..f8e2c5c3f4eb 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -1361,23 +1361,18 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, struct talitos_private *priv = dev_get_drvdata(dev); bool is_sec1 = has_ftr_sec1(priv); int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN; - void *err; if (cryptlen + authsize > max_len) { dev_err(dev, "length exceeds h/w max limit\n"); return ERR_PTR(-EINVAL); } - if (ivsize) - iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE); - if (!dst || dst == src) { src_len = assoclen + cryptlen + authsize; src_nents = sg_nents_for_len(src, src_len); if (src_nents < 0) { dev_err(dev, "Invalid number of src SG.\n"); - err = ERR_PTR(-EINVAL); - goto error_sg; + return ERR_PTR(-EINVAL); } src_nents = (src_nents == 1) ? 0 : src_nents; dst_nents = dst ? src_nents : 0; @@ -1387,16 +1382,14 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, src_nents = sg_nents_for_len(src, src_len); if (src_nents < 0) { dev_err(dev, "Invalid number of src SG.\n"); - err = ERR_PTR(-EINVAL); - goto error_sg; + return ERR_PTR(-EINVAL); } src_nents = (src_nents == 1) ? 0 : src_nents; dst_len = assoclen + cryptlen + (encrypt ? authsize : 0); dst_nents = sg_nents_for_len(dst, dst_len); if (dst_nents < 0) { dev_err(dev, "Invalid number of dst SG.\n"); - err = ERR_PTR(-EINVAL); - goto error_sg; + return ERR_PTR(-EINVAL); } dst_nents = (dst_nents == 1) ? 0 : dst_nents; } @@ -1423,11 +1416,14 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, /* if its a ahash, add space for a second desc next to the first one */ if (is_sec1 && !dst) alloc_len += sizeof(struct talitos_desc); + alloc_len += ivsize; edesc = kmalloc(alloc_len, GFP_DMA | flags); - if (!edesc) { - err = ERR_PTR(-ENOMEM); - goto error_sg; + if (!edesc) + return ERR_PTR(-ENOMEM); + if (ivsize) { + iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize); + iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE); } memset(&edesc->desc, 0, sizeof(edesc->desc)); @@ -1445,10 +1441,6 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, DMA_BIDIRECTIONAL); } return edesc; -error_sg: - if (iv_dma) - dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE); - return err; } static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv, diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index 4e557684f792..fe69dccfa0c0 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -203,6 +203,7 @@ struct at_xdmac_chan { u32 save_cim; u32 save_cnda; u32 save_cndc; + u32 irq_status; unsigned long status; struct tasklet_struct tasklet; struct dma_slave_config sconfig; @@ -1580,8 +1581,8 @@ static void at_xdmac_tasklet(unsigned long data) struct at_xdmac_desc *desc; u32 error_mask; - dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08lx\n", - __func__, atchan->status); + dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08x\n", + __func__, atchan->irq_status); error_mask = AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS @@ -1589,15 +1590,15 @@ static void at_xdmac_tasklet(unsigned long data) if (at_xdmac_chan_is_cyclic(atchan)) { at_xdmac_handle_cyclic(atchan); - } else if ((atchan->status & AT_XDMAC_CIS_LIS) - || (atchan->status & error_mask)) { + } else if ((atchan->irq_status & AT_XDMAC_CIS_LIS) + || (atchan->irq_status & error_mask)) { struct dma_async_tx_descriptor *txd; - if (atchan->status & AT_XDMAC_CIS_RBEIS) + if (atchan->irq_status & AT_XDMAC_CIS_RBEIS) dev_err(chan2dev(&atchan->chan), "read bus error!!!"); - if (atchan->status & AT_XDMAC_CIS_WBEIS) + if (atchan->irq_status & AT_XDMAC_CIS_WBEIS) dev_err(chan2dev(&atchan->chan), "write bus error!!!"); - if (atchan->status & AT_XDMAC_CIS_ROIS) + if (atchan->irq_status & AT_XDMAC_CIS_ROIS) dev_err(chan2dev(&atchan->chan), "request overflow error!!!"); spin_lock(&atchan->lock); @@ -1652,7 +1653,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id) atchan = &atxdmac->chan[i]; chan_imr = at_xdmac_chan_read(atchan, AT_XDMAC_CIM); chan_status = at_xdmac_chan_read(atchan, AT_XDMAC_CIS); - atchan->status = chan_status & chan_imr; + atchan->irq_status = chan_status & chan_imr; dev_vdbg(atxdmac->dma.dev, "%s: chan%d: imr=0x%x, status=0x%x\n", __func__, i, chan_imr, chan_status); @@ -1666,7 +1667,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id) at_xdmac_chan_read(atchan, AT_XDMAC_CDA), at_xdmac_chan_read(atchan, AT_XDMAC_CUBC)); - if (atchan->status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS)) + if (atchan->irq_status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS)) at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask); tasklet_schedule(&atchan->tasklet); diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 1a44c8086d77..ae10f5614f95 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -406,38 +406,32 @@ static void bcm2835_dma_fill_cb_chain_with_sg( } } -static int bcm2835_dma_abort(void __iomem *chan_base) +static int bcm2835_dma_abort(struct bcm2835_chan *c) { - unsigned long cs; + void __iomem *chan_base = c->chan_base; long int timeout = 10000; - cs = readl(chan_base + BCM2835_DMA_CS); - if (!(cs & BCM2835_DMA_ACTIVE)) + /* + * A zero control block address means the channel is idle. + * (The ACTIVE flag in the CS register is not a reliable indicator.) + */ + if (!readl(chan_base + BCM2835_DMA_ADDR)) return 0; /* Write 0 to the active bit - Pause the DMA */ writel(0, chan_base + BCM2835_DMA_CS); /* Wait for any current AXI transfer to complete */ - while ((cs & BCM2835_DMA_ISPAUSED) && --timeout) { + while ((readl(chan_base + BCM2835_DMA_CS) & + BCM2835_DMA_WAITING_FOR_WRITES) && --timeout) cpu_relax(); - cs = readl(chan_base + BCM2835_DMA_CS); - } - /* We'll un-pause when we set of our next DMA */ + /* Peripheral might be stuck and fail to signal AXI write responses */ if (!timeout) - return -ETIMEDOUT; - - if (!(cs & BCM2835_DMA_ACTIVE)) - return 0; - - /* Terminate the control block chain */ - writel(0, chan_base + BCM2835_DMA_NEXTCB); - - /* Abort the whole DMA */ - writel(BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE, - chan_base + BCM2835_DMA_CS); + dev_err(c->vc.chan.device->dev, + "failed to complete outstanding writes\n"); + writel(BCM2835_DMA_RESET, chan_base + BCM2835_DMA_CS); return 0; } @@ -476,8 +470,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) spin_lock_irqsave(&c->vc.lock, flags); - /* Acknowledge interrupt */ - writel(BCM2835_DMA_INT, c->chan_base + BCM2835_DMA_CS); + /* + * Clear the INT flag to receive further interrupts. Keep the channel + * active in case the descriptor is cyclic or in case the client has + * already terminated the descriptor and issued a new one. (May happen + * if this IRQ handler is threaded.) If the channel is finished, it + * will remain idle despite the ACTIVE flag being set. + */ + writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE, + c->chan_base + BCM2835_DMA_CS); d = c->desc; @@ -485,11 +486,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) if (d->cyclic) { /* call the cyclic callback */ vchan_cyclic_callback(&d->vd); - - /* Keep the DMA engine running */ - writel(BCM2835_DMA_ACTIVE, - c->chan_base + BCM2835_DMA_CS); - } else { + } else if (!readl(c->chan_base + BCM2835_DMA_ADDR)) { vchan_cookie_complete(&c->desc->vd); bcm2835_dma_start_desc(c); } @@ -779,7 +776,6 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan) struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device); unsigned long flags; - int timeout = 10000; LIST_HEAD(head); spin_lock_irqsave(&c->vc.lock, flags); @@ -789,27 +785,11 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan) list_del_init(&c->node); spin_unlock(&d->lock); - /* - * Stop DMA activity: we assume the callback will not be called - * after bcm_dma_abort() returns (even if it does, it will see - * c->desc is NULL and exit.) - */ + /* stop DMA activity */ if (c->desc) { vchan_terminate_vdesc(&c->desc->vd); c->desc = NULL; - bcm2835_dma_abort(c->chan_base); - - /* Wait for stopping */ - while (--timeout) { - if (!(readl(c->chan_base + BCM2835_DMA_CS) & - BCM2835_DMA_ACTIVE)) - break; - - cpu_relax(); - } - - if (!timeout) - dev_err(d->ddev.dev, "DMA transfer could not be terminated\n"); + bcm2835_dma_abort(c); } vchan_get_all_descriptors(&c->vc, &head); diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 2eea4ef72915..6511928b4cdf 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -711,11 +711,9 @@ static int dmatest_func(void *data) srcs[i] = um->addr[i] + src_off; ret = dma_mapping_error(dev->dev, um->addr[i]); if (ret) { - dmaengine_unmap_put(um); result("src mapping error", total_tests, src_off, dst_off, len, ret); - failed_tests++; - continue; + goto error_unmap_continue; } um->to_cnt++; } @@ -730,11 +728,9 @@ static int dmatest_func(void *data) DMA_BIDIRECTIONAL); ret = dma_mapping_error(dev->dev, dsts[i]); if (ret) { - dmaengine_unmap_put(um); result("dst mapping error", total_tests, src_off, dst_off, len, ret); - failed_tests++; - continue; + goto error_unmap_continue; } um->bidi_cnt++; } @@ -762,12 +758,10 @@ static int dmatest_func(void *data) } if (!tx) { - dmaengine_unmap_put(um); result("prep error", total_tests, src_off, dst_off, len, ret); msleep(100); - failed_tests++; - continue; + goto error_unmap_continue; } done->done = false; @@ -776,12 +770,10 @@ static int dmatest_func(void *data) cookie = tx->tx_submit(tx); if (dma_submit_error(cookie)) { - dmaengine_unmap_put(um); result("submit error", total_tests, src_off, dst_off, len, ret); msleep(100); - failed_tests++; - continue; + goto error_unmap_continue; } dma_async_issue_pending(chan); @@ -790,22 +782,20 @@ static int dmatest_func(void *data) status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); - dmaengine_unmap_put(um); - if (!done->done) { result("test timed out", total_tests, src_off, dst_off, len, 0); - failed_tests++; - continue; + goto error_unmap_continue; } else if (status != DMA_COMPLETE) { result(status == DMA_ERROR ? "completion error status" : "completion busy status", total_tests, src_off, dst_off, len, ret); - failed_tests++; - continue; + goto error_unmap_continue; } + dmaengine_unmap_put(um); + if (params->noverify) { verbose_result("test passed", total_tests, src_off, dst_off, len, 0); @@ -846,6 +836,12 @@ static int dmatest_func(void *data) verbose_result("test passed", total_tests, src_off, dst_off, len, 0); } + + continue; + +error_unmap_continue: + dmaengine_unmap_put(um); + failed_tests++; } ktime = ktime_sub(ktime_get(), ktime); ktime = ktime_sub(ktime, comparetime); diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index c2fff3f6c9ca..4a09af3cd546 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -618,7 +618,7 @@ static void imxdma_tasklet(unsigned long data) { struct imxdma_channel *imxdmac = (void *)data; struct imxdma_engine *imxdma = imxdmac->imxdma; - struct imxdma_desc *desc; + struct imxdma_desc *desc, *next_desc; unsigned long flags; spin_lock_irqsave(&imxdma->lock, flags); @@ -648,10 +648,10 @@ static void imxdma_tasklet(unsigned long data) list_move_tail(imxdmac->ld_active.next, &imxdmac->ld_free); if (!list_empty(&imxdmac->ld_queue)) { - desc = list_first_entry(&imxdmac->ld_queue, struct imxdma_desc, - node); + next_desc = list_first_entry(&imxdmac->ld_queue, + struct imxdma_desc, node); list_move_tail(imxdmac->ld_queue.next, &imxdmac->ld_active); - if (imxdma_xfer_desc(desc) < 0) + if (imxdma_xfer_desc(next_desc) < 0) dev_warn(imxdma->dev, "%s: channel: %d couldn't xfer desc\n", __func__, imxdmac->channel); } diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index a2b0a0e71168..86708fb9bda1 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1182,8 +1182,8 @@ static int sdma_request_channel0(struct sdma_engine *sdma) { int ret = -EBUSY; - sdma->bd0 = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdma->bd0_phys, - GFP_NOWAIT); + sdma->bd0 = dma_alloc_coherent(NULL, PAGE_SIZE, &sdma->bd0_phys, + GFP_NOWAIT); if (!sdma->bd0) { ret = -ENOMEM; goto out; @@ -1205,8 +1205,8 @@ static int sdma_alloc_bd(struct sdma_desc *desc) u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor); int ret = 0; - desc->bd = dma_zalloc_coherent(NULL, bd_size, &desc->bd_phys, - GFP_NOWAIT); + desc->bd = dma_alloc_coherent(NULL, bd_size, &desc->bd_phys, + GFP_NOWAIT); if (!desc->bd) { ret = -ENOMEM; goto out; diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c index b7ec56ae02a6..1a2028e1c29e 100644 --- a/drivers/dma/mediatek/mtk-hsdma.c +++ b/drivers/dma/mediatek/mtk-hsdma.c @@ -325,8 +325,8 @@ static int mtk_hsdma_alloc_pchan(struct mtk_hsdma_device *hsdma, * and [MTK_DMA_SIZE ... 2 * MTK_DMA_SIZE - 1] is for RX ring. */ pc->sz_ring = 2 * MTK_DMA_SIZE * sizeof(*ring->txd); - ring->txd = dma_zalloc_coherent(hsdma2dev(hsdma), pc->sz_ring, - &ring->tphys, GFP_NOWAIT); + ring->txd = dma_alloc_coherent(hsdma2dev(hsdma), pc->sz_ring, + &ring->tphys, GFP_NOWAIT); if (!ring->txd) return -ENOMEM; diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index 35193b31a9e0..22cc7f68ef6e 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -416,9 +416,9 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan) struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; int ret; - mxs_chan->ccw = dma_zalloc_coherent(mxs_dma->dma_device.dev, - CCW_BLOCK_SIZE, - &mxs_chan->ccw_phys, GFP_KERNEL); + mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev, + CCW_BLOCK_SIZE, + &mxs_chan->ccw_phys, GFP_KERNEL); if (!mxs_chan->ccw) { ret = -ENOMEM; goto err_alloc; diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c index 1d5988849aa6..eafd6c4b90fe 100644 --- a/drivers/dma/xgene-dma.c +++ b/drivers/dma/xgene-dma.c @@ -1208,8 +1208,8 @@ static int xgene_dma_create_ring_one(struct xgene_dma_chan *chan, ring->size = ret; /* Allocate memory for DMA ring descriptor */ - ring->desc_vaddr = dma_zalloc_coherent(chan->dev, ring->size, - &ring->desc_paddr, GFP_KERNEL); + ring->desc_vaddr = dma_alloc_coherent(chan->dev, ring->size, + &ring->desc_paddr, GFP_KERNEL); if (!ring->desc_vaddr) { chan_err(chan, "Failed to allocate ring desc\n"); return -ENOMEM; diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index 02880963092f..cb20b411493e 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -879,10 +879,9 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan) */ if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) { /* Allocate the buffer descriptors. */ - chan->seg_v = dma_zalloc_coherent(chan->dev, - sizeof(*chan->seg_v) * - XILINX_DMA_NUM_DESCS, - &chan->seg_p, GFP_KERNEL); + chan->seg_v = dma_alloc_coherent(chan->dev, + sizeof(*chan->seg_v) * XILINX_DMA_NUM_DESCS, + &chan->seg_p, GFP_KERNEL); if (!chan->seg_v) { dev_err(chan->dev, "unable to allocate channel %d descriptors\n", @@ -895,9 +894,10 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan) * so allocating a desc segment during channel allocation for * programming tail descriptor. */ - chan->cyclic_seg_v = dma_zalloc_coherent(chan->dev, - sizeof(*chan->cyclic_seg_v), - &chan->cyclic_seg_p, GFP_KERNEL); + chan->cyclic_seg_v = dma_alloc_coherent(chan->dev, + sizeof(*chan->cyclic_seg_v), + &chan->cyclic_seg_p, + GFP_KERNEL); if (!chan->cyclic_seg_v) { dev_err(chan->dev, "unable to allocate desc segment for cyclic DMA\n"); diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index 8db51750ce93..4478787a247f 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -490,9 +490,9 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan) list_add_tail(&desc->node, &chan->free_list); } - chan->desc_pool_v = dma_zalloc_coherent(chan->dev, - (2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS), - &chan->desc_pool_p, GFP_KERNEL); + chan->desc_pool_v = dma_alloc_coherent(chan->dev, + (2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS), + &chan->desc_pool_p, GFP_KERNEL); if (!chan->desc_pool_v) return -ENOMEM; diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h index 4213cb0bb2a7..f8664bac9fa8 100644 --- a/drivers/edac/altera_edac.h +++ b/drivers/edac/altera_edac.h @@ -295,8 +295,8 @@ struct altr_sdram_mc_data { #define S10_SYSMGR_ECC_INTSTAT_DERR_OFST 0xA0 /* Sticky registers for Uncorrected Errors */ -#define S10_SYSMGR_UE_VAL_OFST 0x120 -#define S10_SYSMGR_UE_ADDR_OFST 0x124 +#define S10_SYSMGR_UE_VAL_OFST 0x220 +#define S10_SYSMGR_UE_ADDR_OFST 0x224 #define S10_DDR0_IRQ_MASK BIT(16) diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 09b845e90114..a785ffd5af89 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -1144,10 +1144,6 @@ static int sbp2_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) if (device->is_local) return -ENODEV; - if (dma_get_max_seg_size(device->card->device) > SBP2_MAX_SEG_SIZE) - WARN_ON(dma_set_max_seg_size(device->card->device, - SBP2_MAX_SEG_SIZE)); - shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt)); if (shost == NULL) return -ENOMEM; @@ -1610,6 +1606,7 @@ static struct scsi_host_template scsi_driver_template = { .eh_abort_handler = sbp2_scsi_abort, .this_id = -1, .sg_tablesize = SG_ALL, + .max_segment_size = SBP2_MAX_SEG_SIZE, .can_queue = 1, .sdev_attrs = sbp2_scsi_sysfs_attrs, }; diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index 472c88ae1c0f..92f843eaf1e0 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -119,6 +119,11 @@ void scmi_driver_unregister(struct scmi_driver *driver) } EXPORT_SYMBOL_GPL(scmi_driver_unregister); +static void scmi_device_release(struct device *dev) +{ + kfree(to_scmi_dev(dev)); +} + struct scmi_device * scmi_device_create(struct device_node *np, struct device *parent, int protocol) { @@ -138,6 +143,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol) scmi_dev->dev.parent = parent; scmi_dev->dev.of_node = np; scmi_dev->dev.bus = &scmi_bus_type; + scmi_dev->dev.release = scmi_device_release; dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id); retval = device_register(&scmi_dev->dev); @@ -156,9 +162,8 @@ free_mem: void scmi_device_destroy(struct scmi_device *scmi_dev) { scmi_handle_put(scmi_dev->handle); - device_unregister(&scmi_dev->dev); ida_simple_remove(&scmi_bus_id, scmi_dev->id); - kfree(scmi_dev); + device_unregister(&scmi_dev->dev); } void scmi_set_handle(struct scmi_device *scmi_dev) diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 23ea1ed409d1..352bd2473162 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -37,8 +37,9 @@ extern u64 efi_system_table; static struct ptdump_info efi_ptdump_info = { .mm = &efi_mm, .markers = (struct addr_marker[]){ - { 0, "UEFI runtime start" }, - { DEFAULT_MAP_WINDOW_64, "UEFI runtime end" } + { 0, "UEFI runtime start" }, + { DEFAULT_MAP_WINDOW_64, "UEFI runtime end" }, + { -1, NULL } }, .base_addr = 0, }; diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 4c46ff6f2242..55b77c576c42 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -592,11 +592,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, early_memunmap(tbl, sizeof(*tbl)); } - return 0; -} -int __init efi_apply_persistent_mem_reservations(void) -{ if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) { unsigned long prsv = efi.mem_reserve; diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index eee42d5e25ee..c037c6c5d0b7 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -75,9 +75,6 @@ void install_memreserve_table(efi_system_table_t *sys_table_arg) efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID; efi_status_t status; - if (IS_ENABLED(CONFIG_ARM)) - return; - status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv), (void **)&rsv); if (status != EFI_SUCCESS) { diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index 8903b9ccfc2b..e2abfdb5cee6 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -147,6 +147,13 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call) static DEFINE_SEMAPHORE(efi_runtime_lock); /* + * Expose the EFI runtime lock to the UV platform + */ +#ifdef CONFIG_X86_UV +extern struct semaphore __efi_uv_runtime_lock __alias(efi_runtime_lock); +#endif + +/* * Calls the appropriate efi_runtime_service() with the appropriate * arguments. * diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c index a1a09e04fab8..13851b3d1c56 100644 --- a/drivers/fpga/stratix10-soc.c +++ b/drivers/fpga/stratix10-soc.c @@ -508,14 +508,11 @@ static int __init s10_init(void) return -ENODEV; np = of_find_matching_node(fw_np, s10_of_match); - if (!np) { - of_node_put(fw_np); + if (!np) return -ENODEV; - } of_node_put(np); ret = of_platform_populate(fw_np, s10_of_match, NULL, NULL); - of_node_put(fw_np); if (ret) return ret; diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c index 6b11f1314248..7f9e0304b510 100644 --- a/drivers/gpio/gpio-altera-a10sr.c +++ b/drivers/gpio/gpio-altera-a10sr.c @@ -66,8 +66,10 @@ static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc, static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc, unsigned int nr, int value) { - if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) + if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) { + altr_a10sr_gpio_set(gc, nr, value); return 0; + } return -EINVAL; } diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index e0d6a0a7bc69..e41223c05f6e 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -180,7 +180,18 @@ static void sprd_eic_free(struct gpio_chip *chip, unsigned int offset) static int sprd_eic_get(struct gpio_chip *chip, unsigned int offset) { - return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA); + struct sprd_eic *sprd_eic = gpiochip_get_data(chip); + + switch (sprd_eic->type) { + case SPRD_EIC_DEBOUNCE: + return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA); + case SPRD_EIC_ASYNC: + return sprd_eic_read(chip, offset, SPRD_EIC_ASYNC_DATA); + case SPRD_EIC_SYNC: + return sprd_eic_read(chip, offset, SPRD_EIC_SYNC_DATA); + default: + return -ENOTSUPP; + } } static int sprd_eic_direction_input(struct gpio_chip *chip, unsigned int offset) @@ -368,6 +379,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) irq_set_handler_locked(data, handle_edge_irq); break; case IRQ_TYPE_EDGE_BOTH: + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0); sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1); irq_set_handler_locked(data, handle_edge_irq); break; diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c index 00e954f22bc9..74401e0adb29 100644 --- a/drivers/gpio/gpio-mt7621.c +++ b/drivers/gpio/gpio-mt7621.c @@ -30,6 +30,7 @@ #define GPIO_REG_EDGE 0xA0 struct mtk_gc { + struct irq_chip irq_chip; struct gpio_chip chip; spinlock_t lock; int bank; @@ -189,13 +190,6 @@ mediatek_gpio_irq_type(struct irq_data *d, unsigned int type) return 0; } -static struct irq_chip mediatek_gpio_irq_chip = { - .irq_unmask = mediatek_gpio_irq_unmask, - .irq_mask = mediatek_gpio_irq_mask, - .irq_mask_ack = mediatek_gpio_irq_mask, - .irq_set_type = mediatek_gpio_irq_type, -}; - static int mediatek_gpio_xlate(struct gpio_chip *chip, const struct of_phandle_args *spec, u32 *flags) @@ -254,6 +248,13 @@ mediatek_gpio_bank_probe(struct device *dev, return ret; } + rg->irq_chip.name = dev_name(dev); + rg->irq_chip.parent_device = dev; + rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask; + rg->irq_chip.irq_mask = mediatek_gpio_irq_mask; + rg->irq_chip.irq_mask_ack = mediatek_gpio_irq_mask; + rg->irq_chip.irq_set_type = mediatek_gpio_irq_type; + if (mtk->gpio_irq) { /* * Manually request the irq here instead of passing @@ -270,14 +271,14 @@ mediatek_gpio_bank_probe(struct device *dev, return ret; } - ret = gpiochip_irqchip_add(&rg->chip, &mediatek_gpio_irq_chip, + ret = gpiochip_irqchip_add(&rg->chip, &rg->irq_chip, 0, handle_simple_irq, IRQ_TYPE_NONE); if (ret) { dev_err(dev, "failed to add gpiochip_irqchip\n"); return ret; } - gpiochip_set_chained_irqchip(&rg->chip, &mediatek_gpio_irq_chip, + gpiochip_set_chained_irqchip(&rg->chip, &rg->irq_chip, mtk->gpio_irq, NULL); } @@ -310,7 +311,6 @@ mediatek_gpio_probe(struct platform_device *pdev) mtk->gpio_irq = irq_of_parse_and_map(np, 0); mtk->dev = dev; platform_set_drvdata(pdev, mtk); - mediatek_gpio_irq_chip.name = dev_name(dev); for (i = 0; i < MTK_BANK_CNT; i++) { ret = mediatek_gpio_bank_probe(dev, np, i); diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 83617fdc661d..0dc96419efe3 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -289,7 +289,7 @@ static bool pca953x_volatile_register(struct device *dev, unsigned int reg) return pca953x_check_register(chip, reg, bank); } -const struct regmap_config pca953x_i2c_regmap = { +static const struct regmap_config pca953x_i2c_regmap = { .reg_bits = 8, .val_bits = 8, diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index adf72dda25a2..68a35b65925a 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -84,6 +84,7 @@ MODULE_DEVICE_TABLE(of, pcf857x_of_table); */ struct pcf857x { struct gpio_chip chip; + struct irq_chip irqchip; struct i2c_client *client; struct mutex lock; /* protect 'out' */ unsigned out; /* software latch */ @@ -252,18 +253,6 @@ static void pcf857x_irq_bus_sync_unlock(struct irq_data *data) mutex_unlock(&gpio->lock); } -static struct irq_chip pcf857x_irq_chip = { - .name = "pcf857x", - .irq_enable = pcf857x_irq_enable, - .irq_disable = pcf857x_irq_disable, - .irq_ack = noop, - .irq_mask = noop, - .irq_unmask = noop, - .irq_set_wake = pcf857x_irq_set_wake, - .irq_bus_lock = pcf857x_irq_bus_lock, - .irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock, -}; - /*-------------------------------------------------------------------------*/ static int pcf857x_probe(struct i2c_client *client, @@ -376,8 +365,17 @@ static int pcf857x_probe(struct i2c_client *client, /* Enable irqchip if we have an interrupt */ if (client->irq) { + gpio->irqchip.name = "pcf857x", + gpio->irqchip.irq_enable = pcf857x_irq_enable, + gpio->irqchip.irq_disable = pcf857x_irq_disable, + gpio->irqchip.irq_ack = noop, + gpio->irqchip.irq_mask = noop, + gpio->irqchip.irq_unmask = noop, + gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake, + gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock, + gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock, status = gpiochip_irqchip_add_nested(&gpio->chip, - &pcf857x_irq_chip, + &gpio->irqchip, 0, handle_level_irq, IRQ_TYPE_NONE); if (status) { @@ -392,7 +390,7 @@ static int pcf857x_probe(struct i2c_client *client, if (status) goto fail; - gpiochip_set_nested_irqchip(&gpio->chip, &pcf857x_irq_chip, + gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip, client->irq); gpio->irq_parent = client->irq; } diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index e9600b556f39..bcc6be4a5cb2 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -245,6 +245,7 @@ static bool pxa_gpio_has_pinctrl(void) { switch (gpio_type) { case PXA3XX_GPIO: + case MMP2_GPIO: return false; default: diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 1b79ebcfce3e..541fa6ac399d 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -253,6 +253,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) struct vf610_gpio_port *port; struct resource *iores; struct gpio_chip *gc; + int i; int ret; port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL); @@ -319,6 +320,10 @@ static int vf610_gpio_probe(struct platform_device *pdev) if (ret < 0) return ret; + /* Mask all GPIO interrupts */ + for (i = 0; i < gc->ngpio; i++) + vf610_gpio_writel(0, port->base + PORT_PCR(i)); + /* Clear the interrupt status register for all GPIO's */ vf610_gpio_writel(~0, port->base + PORT_ISFR); diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 48534bda73d3..259cf6ab969b 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -357,8 +357,6 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) mutex_unlock(&acpi_gpio_deferred_req_irqs_lock); list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) { - struct gpio_desc *desc; - if (event->irq_requested) { if (event->irq_is_wake) disable_irq_wake(event->irq); @@ -366,11 +364,8 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) free_irq(event->irq, event); } - desc = event->desc; - if (WARN_ON(IS_ERR(desc))) - continue; gpiochip_unlock_as_irq(chip, event->pin); - gpiochip_free_own_desc(desc); + gpiochip_free_own_desc(event->desc); list_del(&event->node); kfree(event); } diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index a6e1891217e2..c34eb9d9c59a 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -125,7 +125,7 @@ static void of_gpio_flags_quirks(struct device_node *np, for_each_child_of_node(np, child) { ret = of_property_read_u32(child, "reg", &cs); - if (!ret) + if (ret) continue; if (cs == index) { /* diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1651d7f0a303..d1adfdf50fb3 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -828,7 +828,14 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) /* Do not leak kernel stack to userspace */ memset(&ge, 0, sizeof(ge)); - ge.timestamp = le->timestamp; + /* + * We may be running from a nested threaded interrupt in which case + * we didn't get the timestamp from lineevent_irq_handler(). + */ + if (!le->timestamp) + ge.timestamp = ktime_get_real_ns(); + else + ge.timestamp = le->timestamp; if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c index a028661d9e20..92b11de19581 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c @@ -576,6 +576,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = { { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX }, { 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX }, { 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX }, + { 0x1002, 0x6900, 0x17AA, 0x3806, AMDGPU_PX_QUIRK_FORCE_ATPX }, { 0, 0, 0, 0, 0 }, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 8a078f4ae73d..7ff3a28fc903 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1701,8 +1701,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) amdgpu_xgmi_add_device(adev); amdgpu_amdkfd_device_init(adev); - if (amdgpu_sriov_vf(adev)) + if (amdgpu_sriov_vf(adev)) { + amdgpu_virt_init_data_exchange(adev); amdgpu_virt_release_full_gpu(adev, true); + } return 0; } @@ -2632,9 +2634,6 @@ fence_driver_init: goto failed; } - if (amdgpu_sriov_vf(adev)) - amdgpu_virt_init_data_exchange(adev); - amdgpu_fbdev_init(adev); r = amdgpu_pm_sysfs_init(adev); @@ -2798,7 +2797,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon) struct drm_framebuffer *fb = crtc->primary->fb; struct amdgpu_bo *robj; - if (amdgpu_crtc->cursor_bo) { + if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) { struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); r = amdgpu_bo_reserve(aobj, true); if (r == 0) { @@ -2906,7 +2905,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - if (amdgpu_crtc->cursor_bo) { + if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) { struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); r = amdgpu_bo_reserve(aobj, true); if (r == 0) { @@ -3226,6 +3225,7 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev, r = amdgpu_ib_ring_tests(adev); error: + amdgpu_virt_init_data_exchange(adev); amdgpu_virt_release_full_gpu(adev, true); if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) { atomic_inc(&adev->vram_lost_counter); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 15ce7e681d67..b083b219b1a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -188,10 +188,12 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc, goto cleanup; } - r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev)); - if (unlikely(r != 0)) { - DRM_ERROR("failed to pin new abo buffer before flip\n"); - goto unreserve; + if (!adev->enable_virtual_display) { + r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev)); + if (unlikely(r != 0)) { + DRM_ERROR("failed to pin new abo buffer before flip\n"); + goto unreserve; + } } r = amdgpu_ttm_alloc_gart(&new_abo->tbo); @@ -211,7 +213,8 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc, amdgpu_bo_get_tiling_flags(new_abo, &tiling_flags); amdgpu_bo_unreserve(new_abo); - work->base = amdgpu_bo_gpu_offset(new_abo); + if (!adev->enable_virtual_display) + work->base = amdgpu_bo_gpu_offset(new_abo); work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) + amdgpu_get_vblank_counter_kms(dev, work->crtc_id); @@ -242,9 +245,10 @@ pflip_cleanup: goto cleanup; } unpin: - if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) { - DRM_ERROR("failed to unpin new abo in error path\n"); - } + if (!adev->enable_virtual_display) + if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) + DRM_ERROR("failed to unpin new abo in error path\n"); + unreserve: amdgpu_bo_unreserve(new_abo); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index bc62bf41b7e9..5dc349173e4f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -212,6 +212,7 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags) } if (amdgpu_device_is_px(dev)) { + dev_pm_set_driver_flags(dev->dev, DPM_FLAG_NEVER_SKIP); pm_runtime_use_autosuspend(dev->dev); pm_runtime_set_autosuspend_delay(dev->dev, 5000); pm_runtime_set_active(dev->dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index aadd0fa42e43..3aa42c64484a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -405,6 +405,7 @@ struct amdgpu_crtc { struct amdgpu_flip_work *pflip_works; enum amdgpu_flip_status pflip_status; int deferred_flip_completion; + u64 last_flip_vblank; /* pll sharing */ struct amdgpu_atom_ss ss; bool ss_enabled; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 1f61ed95727c..0ed41a9d2d77 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1686,7 +1686,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, effective_mode &= ~S_IWUSR; if ((adev->flags & AMD_IS_APU) && - (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || + (attr == &sensor_dev_attr_power1_average.dev_attr.attr || + attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr|| attr == &sensor_dev_attr_power1_cap.dev_attr.attr)) return 0; @@ -2008,6 +2009,7 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev) int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) { + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; int ret; if (adev->pm.sysfs_initialized) @@ -2091,12 +2093,14 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) "pp_power_profile_mode\n"); return ret; } - ret = device_create_file(adev->dev, - &dev_attr_pp_od_clk_voltage); - if (ret) { - DRM_ERROR("failed to create device file " - "pp_od_clk_voltage\n"); - return ret; + if (hwmgr->od_enabled) { + ret = device_create_file(adev->dev, + &dev_attr_pp_od_clk_voltage); + if (ret) { + DRM_ERROR("failed to create device file " + "pp_od_clk_voltage\n"); + return ret; + } } ret = device_create_file(adev->dev, &dev_attr_gpu_busy_percent); @@ -2118,6 +2122,8 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) { + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + if (adev->pm.dpm_enabled == 0) return; @@ -2138,8 +2144,9 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) device_remove_file(adev->dev, &dev_attr_pp_mclk_od); device_remove_file(adev->dev, &dev_attr_pp_power_profile_mode); - device_remove_file(adev->dev, - &dev_attr_pp_od_clk_voltage); + if (hwmgr->od_enabled) + device_remove_file(adev->dev, + &dev_attr_pp_od_clk_voltage); device_remove_file(adev->dev, &dev_attr_gpu_busy_percent); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c index 71913a18d142..a38e0fb4a6fe 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c @@ -38,6 +38,7 @@ #include "amdgpu_gem.h" #include <drm/amdgpu_drm.h> #include <linux/dma-buf.h> +#include <linux/dma-fence-array.h> /** * amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table @@ -187,6 +188,48 @@ error: return ERR_PTR(ret); } +static int +__reservation_object_make_exclusive(struct reservation_object *obj) +{ + struct dma_fence **fences; + unsigned int count; + int r; + + if (!reservation_object_get_list(obj)) /* no shared fences to convert */ + return 0; + + r = reservation_object_get_fences_rcu(obj, NULL, &count, &fences); + if (r) + return r; + + if (count == 0) { + /* Now that was unexpected. */ + } else if (count == 1) { + reservation_object_add_excl_fence(obj, fences[0]); + dma_fence_put(fences[0]); + kfree(fences); + } else { + struct dma_fence_array *array; + + array = dma_fence_array_create(count, fences, + dma_fence_context_alloc(1), 0, + false); + if (!array) + goto err_fences_put; + + reservation_object_add_excl_fence(obj, &array->base); + dma_fence_put(&array->base); + } + + return 0; + +err_fences_put: + while (count--) + dma_fence_put(fences[count]); + kfree(fences); + return -ENOMEM; +} + /** * amdgpu_gem_map_attach - &dma_buf_ops.attach implementation * @dma_buf: Shared DMA buffer @@ -218,16 +261,16 @@ static int amdgpu_gem_map_attach(struct dma_buf *dma_buf, if (attach->dev->driver != adev->dev->driver) { /* - * Wait for all shared fences to complete before we switch to future - * use of exclusive fence on this prime shared bo. + * We only create shared fences for internal use, but importers + * of the dmabuf rely on exclusive fences for implicitly + * tracking write hazards. As any of the current fences may + * correspond to a write, we need to convert all existing + * fences on the reservation object into a single exclusive + * fence. */ - r = reservation_object_wait_timeout_rcu(bo->tbo.resv, - true, false, - MAX_SCHEDULE_TIMEOUT); - if (unlikely(r < 0)) { - DRM_DEBUG_PRIME("Fence wait failed: %li\n", r); + r = __reservation_object_make_exclusive(bo->tbo.resv); + if (r) goto error_unreserve; - } } /* pin buffer into GTT */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 8fab0d637ee5..3a9b48b227ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -90,8 +90,10 @@ static int psp_sw_fini(void *handle) adev->psp.sos_fw = NULL; release_firmware(adev->psp.asd_fw); adev->psp.asd_fw = NULL; - release_firmware(adev->psp.ta_fw); - adev->psp.ta_fw = NULL; + if (adev->psp.ta_fw) { + release_firmware(adev->psp.ta_fw); + adev->psp.ta_fw = NULL; + } return 0; } @@ -435,6 +437,9 @@ static int psp_xgmi_initialize(struct psp_context *psp) struct ta_xgmi_shared_memory *xgmi_cmd; int ret; + if (!psp->adev->psp.ta_fw) + return -ENOENT; + if (!psp->xgmi_context.initialized) { ret = psp_xgmi_init_shared_buf(psp); if (ret) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index e73d152659a2..698bcb8ce61d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -638,12 +638,14 @@ void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev, struct ttm_bo_global *glob = adev->mman.bdev.glob; struct amdgpu_vm_bo_base *bo_base; +#if 0 if (vm->bulk_moveable) { spin_lock(&glob->lru_lock); ttm_bo_bulk_move_lru_tail(&vm->lru_bulk_move); spin_unlock(&glob->lru_lock); return; } +#endif memset(&vm->lru_bulk_move, 0, sizeof(vm->lru_bulk_move)); @@ -847,9 +849,6 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm, bp->size = amdgpu_vm_bo_size(adev, level); bp->byte_align = AMDGPU_GPU_PAGE_SIZE; bp->domain = AMDGPU_GEM_DOMAIN_VRAM; - if (bp->size <= PAGE_SIZE && adev->asic_type >= CHIP_VEGA10 && - adev->flags & AMD_IS_APU) - bp->domain |= AMDGPU_GEM_DOMAIN_GTT; bp->domain = amdgpu_bo_get_preferred_pin_domain(adev, bp->domain); bp->flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS | AMDGPU_GEM_CREATE_CPU_GTT_USWC; @@ -3366,14 +3365,15 @@ void amdgpu_vm_get_task_info(struct amdgpu_device *adev, unsigned int pasid, struct amdgpu_task_info *task_info) { struct amdgpu_vm *vm; + unsigned long flags; - spin_lock(&adev->vm_manager.pasid_lock); + spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); vm = idr_find(&adev->vm_manager.pasid_idr, pasid); if (vm) *task_info = vm->task_info; - spin_unlock(&adev->vm_manager.pasid_lock); + spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index fdace004544d..e4cc1d48eaab 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -167,19 +167,6 @@ static void dce_virtual_crtc_disable(struct drm_crtc *crtc) struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); - if (crtc->primary->fb) { - int r; - struct amdgpu_bo *abo; - - abo = gem_to_amdgpu_bo(crtc->primary->fb->obj[0]); - r = amdgpu_bo_reserve(abo, true); - if (unlikely(r)) - DRM_ERROR("failed to reserve abo before unpin\n"); - else { - amdgpu_bo_unpin(abo); - amdgpu_bo_unreserve(abo); - } - } amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; amdgpu_crtc->encoder = NULL; @@ -692,7 +679,9 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev, spin_unlock_irqrestore(&adev->ddev->event_lock, flags); drm_crtc_vblank_put(&amdgpu_crtc->base); - schedule_work(&works->unpin_work); + amdgpu_bo_unref(&works->old_abo); + kfree(works->shared); + kfree(works); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 381f593b0cda..57cb3a51bda7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4233,7 +4233,6 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev) u32 tmp; u32 rb_bufsz; u64 rb_addr, rptr_addr, wptr_gpu_addr; - int r; /* Set the write pointer delay */ WREG32(mmCP_RB_WPTR_DELAY, 0); @@ -4278,9 +4277,8 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev) amdgpu_ring_clear_ring(ring); gfx_v8_0_cp_gfx_start(adev); ring->sched.ready = true; - r = amdgpu_ring_test_helper(ring); - return r; + return 0; } static void gfx_v8_0_cp_compute_enable(struct amdgpu_device *adev, bool enable) @@ -4369,10 +4367,9 @@ static int gfx_v8_0_kiq_kcq_enable(struct amdgpu_device *adev) amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr)); } - r = amdgpu_ring_test_helper(kiq_ring); - if (r) - DRM_ERROR("KCQ enable failed\n"); - return r; + amdgpu_ring_commit(kiq_ring); + + return 0; } static int gfx_v8_0_deactivate_hqd(struct amdgpu_device *adev, u32 req) @@ -4709,16 +4706,32 @@ static int gfx_v8_0_kcq_resume(struct amdgpu_device *adev) if (r) goto done; - /* Test KCQs - reversing the order of rings seems to fix ring test failure - * after GPU reset - */ - for (i = adev->gfx.num_compute_rings - 1; i >= 0; i--) { +done: + return r; +} + +static int gfx_v8_0_cp_test_all_rings(struct amdgpu_device *adev) +{ + int r, i; + struct amdgpu_ring *ring; + + /* collect all the ring_tests here, gfx, kiq, compute */ + ring = &adev->gfx.gfx_ring[0]; + r = amdgpu_ring_test_helper(ring); + if (r) + return r; + + ring = &adev->gfx.kiq.ring; + r = amdgpu_ring_test_helper(ring); + if (r) + return r; + + for (i = 0; i < adev->gfx.num_compute_rings; i++) { ring = &adev->gfx.compute_ring[i]; - r = amdgpu_ring_test_helper(ring); + amdgpu_ring_test_helper(ring); } -done: - return r; + return 0; } static int gfx_v8_0_cp_resume(struct amdgpu_device *adev) @@ -4739,6 +4752,11 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev) r = gfx_v8_0_kcq_resume(adev); if (r) return r; + + r = gfx_v8_0_cp_test_all_rings(adev); + if (r) + return r; + gfx_v8_0_enable_gui_idle_interrupt(adev, true); return 0; @@ -5086,6 +5104,8 @@ static int gfx_v8_0_post_soft_reset(void *handle) REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_GFX)) gfx_v8_0_cp_gfx_resume(adev); + gfx_v8_0_cp_test_all_rings(adev); + adev->gfx.rlc.funcs->start(adev); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 7556716038d3..fbca0494f871 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -113,7 +113,10 @@ static const struct soc15_reg_golden golden_settings_gc_9_0[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, 0xffffffff, 0x4a2c0e68), SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0xffffffff, 0xb5d3f197), SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, 0x3fff3af3, 0x19200000), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff) + SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000) }; static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] = @@ -135,10 +138,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_UTCL1_CNTL2, 0x00030000, 0x00020000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x0000000f, 0x01000107), SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x00001800, 0x00000800), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000) + SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080) }; static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] = @@ -3587,6 +3587,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev { uint32_t data, def; + amdgpu_gfx_rlc_enter_safe_mode(adev); + /* It is disabled by HW by default */ if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) { /* 1 - RLC_CGTT_MGCG_OVERRIDE */ @@ -3651,6 +3653,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data); } } + + amdgpu_gfx_rlc_exit_safe_mode(adev); } static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index 8cbb4655896a..b11a1c17a7f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -174,7 +174,7 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev, return r; } /* Retrieve checksum from mailbox2 */ - if (req == IDH_REQ_GPU_INIT_ACCESS) { + if (req == IDH_REQ_GPU_INIT_ACCESS || req == IDH_REQ_GPU_RESET_ACCESS) { adev->virt.fw_reserve.checksum_key = RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_MAILBOX_MSGBUF_RCV_DW2)); diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c index 4cd31a276dcd..186db182f924 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c @@ -93,7 +93,20 @@ static void nbio_v7_4_enable_doorbell_aperture(struct amdgpu_device *adev, static void nbio_v7_4_enable_doorbell_selfring_aperture(struct amdgpu_device *adev, bool enable) { + u32 tmp = 0; + if (enable) { + tmp = REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_EN, 1) | + REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_MODE, 1) | + REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_SIZE, 0); + + WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_BASE_LOW, + lower_32_bits(adev->doorbell.base)); + WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_BASE_HIGH, + upper_32_bits(adev->doorbell.base)); + } + + WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_CNTL, tmp); } static void nbio_v7_4_ih_doorbell_range(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c index 0c6e7f9b143f..189fcb004579 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c @@ -152,18 +152,22 @@ static int psp_v11_0_init_microcode(struct psp_context *psp) snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name); err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev); - if (err) - goto out2; - - err = amdgpu_ucode_validate(adev->psp.ta_fw); - if (err) - goto out2; - - ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data; - adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version); - adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes); - adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr + - le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); + if (err) { + release_firmware(adev->psp.ta_fw); + adev->psp.ta_fw = NULL; + dev_info(adev->dev, + "psp v11.0: Failed to load firmware \"%s\"\n", fw_name); + } else { + err = amdgpu_ucode_validate(adev->psp.ta_fw); + if (err) + goto out2; + + ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data; + adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version); + adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes); + adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr + + le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); + } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index fd0bfe140ee0..aa2f71cc1eba 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -78,7 +78,6 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = { SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000), - SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_IB_CNTL, 0x800f0100, 0x00000100), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000), @@ -96,6 +95,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = { static const struct soc15_reg_golden golden_settings_sdma_vg10[] = { SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104002), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002), + SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104002), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002) }; @@ -103,6 +103,7 @@ static const struct soc15_reg_golden golden_settings_sdma_vg10[] = { static const struct soc15_reg_golden golden_settings_sdma_vg12[] = { SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104001), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001), + SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104001), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001) }; @@ -127,7 +128,7 @@ static const struct soc15_reg_golden golden_settings_sdma0_4_2_init[] = { static const struct soc15_reg_golden golden_settings_sdma0_4_2[] = { - SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831d07), + SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831f07), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CLK_CTRL, 0xffffffff, 0x3f000100), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0000773f, 0x00004002), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002), @@ -157,7 +158,7 @@ static const struct soc15_reg_golden golden_settings_sdma0_4_2[] = }; static const struct soc15_reg_golden golden_settings_sdma1_4_2[] = { - SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07), + SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0000773f, 0x00004002), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002), diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 8849b74078d6..9b639974c70c 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -729,11 +729,13 @@ static int soc15_common_early_init(void *handle) case CHIP_RAVEN: adev->asic_funcs = &soc15_asic_funcs; if (adev->rev_id >= 0x8) - adev->external_rev_id = adev->rev_id + 0x81; + adev->external_rev_id = adev->rev_id + 0x79; else if (adev->pdev->device == 0x15d8) adev->external_rev_id = adev->rev_id + 0x41; + else if (adev->rev_id == 1) + adev->external_rev_id = adev->rev_id + 0x20; else - adev->external_rev_id = 0x1; + adev->external_rev_id = adev->rev_id + 0x01; if (adev->rev_id >= 0x8) { adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | diff --git a/drivers/gpu/drm/amd/amdkfd/Kconfig b/drivers/gpu/drm/amd/amdkfd/Kconfig index fbf0ee5201c3..c3613604a4f8 100644 --- a/drivers/gpu/drm/amd/amdkfd/Kconfig +++ b/drivers/gpu/drm/amd/amdkfd/Kconfig @@ -4,8 +4,8 @@ config HSA_AMD bool "HSA kernel driver for AMD GPU devices" - depends on DRM_AMDGPU && X86_64 - imply AMD_IOMMU_V2 + depends on DRM_AMDGPU && (X86_64 || ARM64) + imply AMD_IOMMU_V2 if X86_64 select MMU_NOTIFIER help Enable this if you want to use HSA features on AMD GPU devices. diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index b7bc7d7d048f..2e7c44955f43 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -863,6 +863,7 @@ static int kfd_fill_mem_info_for_cpu(int numa_node_id, int *avail_size, return 0; } +#ifdef CONFIG_X86_64 static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size, uint32_t *num_entries, struct crat_subtype_iolink *sub_type_hdr) @@ -905,6 +906,7 @@ static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size, return 0; } +#endif /* kfd_create_vcrat_image_cpu - Create Virtual CRAT for CPU * @@ -920,7 +922,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size) struct crat_subtype_generic *sub_type_hdr; int avail_size = *size; int numa_node_id; +#ifdef CONFIG_X86_64 uint32_t entries = 0; +#endif int ret = 0; if (!pcrat_image || avail_size < VCRAT_SIZE_FOR_CPU) @@ -982,6 +986,7 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size) sub_type_hdr->length); /* Fill in Subtype: IO Link */ +#ifdef CONFIG_X86_64 ret = kfd_fill_iolink_info_for_cpu(numa_node_id, &avail_size, &entries, (struct crat_subtype_iolink *)sub_type_hdr); @@ -992,6 +997,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size) sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr + sub_type_hdr->length * entries); +#else + pr_info("IO link not available for non x86 platforms\n"); +#endif crat_table->num_domains++; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 5f5b2acedbac..09da91644f9f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -1093,8 +1093,6 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu) * the GPU device is not already present in the topology device * list then return NULL. This means a new topology device has to * be created for this GPU. - * TODO: Rather than assiging @gpu to first topology device withtout - * gpu attached, it will better to have more stringent check. */ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu) { @@ -1102,12 +1100,20 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu) struct kfd_topology_device *out_dev = NULL; down_write(&topology_lock); - list_for_each_entry(dev, &topology_device_list, list) + list_for_each_entry(dev, &topology_device_list, list) { + /* Discrete GPUs need their own topology device list + * entries. Don't assign them to CPU/APU nodes. + */ + if (!gpu->device_info->needs_iommu_device && + dev->node_props.cpu_cores_count) + continue; + if (!dev->gpu && (dev->node_props.simd_count > 0)) { dev->gpu = gpu; out_dev = dev; break; } + } up_write(&topology_lock); return out_dev; } @@ -1392,7 +1398,6 @@ int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev) static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask) { - const struct cpuinfo_x86 *cpuinfo; int first_cpu_of_numa_node; if (!cpumask || cpumask == cpu_none_mask) @@ -1400,9 +1405,11 @@ static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask) first_cpu_of_numa_node = cpumask_first(cpumask); if (first_cpu_of_numa_node >= nr_cpu_ids) return -1; - cpuinfo = &cpu_data(first_cpu_of_numa_node); - - return cpuinfo->apicid; +#ifdef CONFIG_X86_64 + return cpu_data(first_cpu_of_numa_node).apicid; +#else + return first_cpu_of_numa_node; +#endif } /* kfd_numa_node_to_apic_id - Returns the APIC ID of the first logical processor diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a9a28dbc3e24..636d14a60952 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -303,12 +303,11 @@ static void dm_pflip_high_irq(void *interrupt_params) return; } + /* Update to correct count(s) if racing with vblank irq */ + amdgpu_crtc->last_flip_vblank = drm_crtc_accurate_vblank_count(&amdgpu_crtc->base); /* wake up userspace */ if (amdgpu_crtc->event) { - /* Update to correct count(s) if racing with vblank irq */ - drm_crtc_accurate_vblank_count(&amdgpu_crtc->base); - drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event); /* page flip completed. clean up */ @@ -699,22 +698,36 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend) { struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; + struct drm_dp_mst_topology_mgr *mgr; + int ret; + bool need_hotplug = false; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_dm_connector(connector); - if (aconnector->dc_link->type == dc_connection_mst_branch && - !aconnector->mst_port) { + list_for_each_entry(connector, &dev->mode_config.connector_list, + head) { + aconnector = to_amdgpu_dm_connector(connector); + if (aconnector->dc_link->type != dc_connection_mst_branch || + aconnector->mst_port) + continue; + + mgr = &aconnector->mst_mgr; - if (suspend) - drm_dp_mst_topology_mgr_suspend(&aconnector->mst_mgr); - else - drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr); - } + if (suspend) { + drm_dp_mst_topology_mgr_suspend(mgr); + } else { + ret = drm_dp_mst_topology_mgr_resume(mgr); + if (ret < 0) { + drm_dp_mst_topology_mgr_set_mst(mgr, false); + need_hotplug = true; + } + } } drm_modeset_unlock(&dev->mode_config.connection_mutex); + + if (need_hotplug) + drm_kms_helper_hotplug_event(dev); } /** @@ -772,12 +785,13 @@ static int dm_suspend(void *handle) struct amdgpu_display_manager *dm = &adev->dm; int ret = 0; + WARN_ON(adev->dm.cached_state); + adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); + s3_handle_mst(adev->ddev, true); amdgpu_dm_irq_suspend(adev); - WARN_ON(adev->dm.cached_state); - adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); @@ -898,7 +912,6 @@ static int dm_resume(void *handle) struct drm_plane_state *new_plane_state; struct dm_plane_state *dm_new_plane_state; enum dc_connection_type new_connection_type = dc_connection_none; - int ret; int i; /* power on hardware */ @@ -971,13 +984,13 @@ static int dm_resume(void *handle) } } - ret = drm_atomic_helper_resume(ddev, dm->cached_state); + drm_atomic_helper_resume(ddev, dm->cached_state); dm->cached_state = NULL; amdgpu_dm_irq_resume_late(adev); - return ret; + return 0; } /** @@ -1759,7 +1772,7 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) + caps.min_input_signal * 0x101; if (dc_link_set_backlight_level(dm->backlight_link, - brightness, 0, 0)) + brightness, 0)) return 0; else return 1; @@ -4069,7 +4082,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, } if (connector_type == DRM_MODE_CONNECTOR_HDMIA || - connector_type == DRM_MODE_CONNECTOR_DisplayPort) { + connector_type == DRM_MODE_CONNECTOR_DisplayPort || + connector_type == DRM_MODE_CONNECTOR_eDP) { drm_connector_attach_vrr_capable_property( &aconnector->base); } @@ -4813,6 +4827,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc)); int planes_count = 0; unsigned long flags; + u64 last_flip_vblank; + bool vrr_active = acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE; /* update planes when needed */ for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { @@ -4844,6 +4860,16 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, /* In commit tail framework this cannot happen */ WARN_ON(1); } + + /* For variable refresh rate mode only: + * Get vblank of last completed flip to avoid > 1 vrr flips per + * video frame by use of throttling, but allow flip programming + * anywhere in the possibly large variable vrr vblank interval + * for fine-grained flip timing control and more opportunity to + * avoid stutter on late submission of amdgpu_dm_do_flip() calls. + */ + last_flip_vblank = acrtc_attach->last_flip_vblank; + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); if (!pflip_needed || plane->type == DRM_PLANE_TYPE_OVERLAY) { @@ -4867,10 +4893,18 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, if (plane->type == DRM_PLANE_TYPE_PRIMARY) drm_crtc_vblank_get(crtc); + /* Use old throttling in non-vrr fixed refresh rate mode + * to keep flip scheduling based on target vblank counts + * working in a backwards compatible way, e.g., clients + * using GLX_OML_sync_control extension. + */ + if (!vrr_active) + last_flip_vblank = drm_crtc_vblank_count(crtc); + amdgpu_dm_do_flip( crtc, fb, - (uint32_t)drm_crtc_vblank_count(crtc) + *wait_for_vblank, + (uint32_t) last_flip_vblank + *wait_for_vblank, dc_state); } @@ -5920,7 +5954,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (!drm_atomic_crtc_needs_modeset(new_crtc_state) && !new_crtc_state->color_mgmt_changed && - !new_crtc_state->vrr_enabled) + old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled) continue; if (!new_crtc_state->enable) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 9a7ac58eb18e..ddd75a4d8ba5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -671,6 +671,25 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __us return bytes_from_user; } +/* + * Returns the min and max vrr vfreq through the connector's debugfs file. + * Example usage: cat /sys/kernel/debug/dri/0/DP-1/vrr_range + */ +static int vrr_range_show(struct seq_file *m, void *data) +{ + struct drm_connector *connector = m->private; + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + + if (connector->status != connector_status_connected) + return -ENODEV; + + seq_printf(m, "Min: %u\n", (unsigned int)aconnector->min_vfreq); + seq_printf(m, "Max: %u\n", (unsigned int)aconnector->max_vfreq); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(vrr_range); + static const struct file_operations dp_link_settings_debugfs_fops = { .owner = THIS_MODULE, .read = dp_link_settings_read, @@ -697,7 +716,8 @@ static const struct { } dp_debugfs_entries[] = { {"link_settings", &dp_link_settings_debugfs_fops}, {"phy_settings", &dp_phy_settings_debugfs_fop}, - {"test_pattern", &dp_phy_test_pattern_fops} + {"test_pattern", &dp_phy_test_pattern_fops}, + {"vrr_range", &vrr_range_fops} }; int connector_debugfs_init(struct amdgpu_dm_connector *connector) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 52deacf39841..b0265dbebd4c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2190,8 +2190,7 @@ int dc_link_get_backlight_level(const struct dc_link *link) bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t backlight_pwm_u16_16, - uint32_t frame_ramp, - const struct dc_stream_state *stream) + uint32_t frame_ramp) { struct dc *core_dc = link->ctx->dc; struct abm *abm = core_dc->res_pool->abm; @@ -2206,10 +2205,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link, (abm->funcs->set_backlight_level_pwm == NULL)) return false; - if (stream) - ((struct dc_stream_state *)stream)->bl_pwm_level = - backlight_pwm_u16_16; - use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu); DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n", @@ -2637,11 +2632,6 @@ void core_link_enable_stream( if (dc_is_dp_signal(pipe_ctx->stream->signal)) enable_stream_features(pipe_ctx); - - dc_link_set_backlight_level(pipe_ctx->stream->sink->link, - pipe_ctx->stream->bl_pwm_level, - 0, - pipe_ctx->stream); } } diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 29f19d57ff7a..b2243e0dad1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -146,8 +146,7 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_ */ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t backlight_pwm_u16_16, - uint32_t frame_ramp, - const struct dc_stream_state *stream); + uint32_t frame_ramp); int dc_link_get_backlight_level(const struct dc_link *dc_link); diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index be34d638e15d..d70c9e1cda3d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -91,7 +91,6 @@ struct dc_stream_state { /* DMCU info */ unsigned int abm_level; - unsigned int bl_pwm_level; /* from core_stream struct */ struct dc_context *ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c index afd287f08bc9..7a72ee46f14b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c @@ -591,7 +591,15 @@ static void dce11_pplib_apply_display_requirements( dc, context->bw.dce.sclk_khz); - pp_display_cfg->min_dcfclock_khz = pp_display_cfg->min_engine_clock_khz; + /* + * As workaround for >4x4K lightup set dcfclock to min_engine_clock value. + * This is not required for less than 5 displays, + * thus don't request decfclk in dc to avoid impact + * on power saving. + * + */ + pp_display_cfg->min_dcfclock_khz = (context->stream_count > 4)? + pp_display_cfg->min_engine_clock_khz : 0; pp_display_cfg->min_engine_clock_deep_sleep_khz = context->bw.dce.sclk_deep_sleep_khz; @@ -654,6 +662,11 @@ static void dce11_update_clocks(struct clk_mgr *clk_mgr, { struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); struct dm_pp_power_level_change_request level_change_req; + int patched_disp_clk = context->bw.dce.dispclk_khz; + + /*TODO: W/A for dal3 linux, investigate why this works */ + if (!clk_mgr_dce->dfs_bypass_active) + patched_disp_clk = patched_disp_clk * 115 / 100; level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context); /* get max clock state from PPLIB */ @@ -663,9 +676,9 @@ static void dce11_update_clocks(struct clk_mgr *clk_mgr, clk_mgr_dce->cur_min_clks_state = level_change_req.power_level; } - if (should_set_clock(safe_to_lower, context->bw.dce.dispclk_khz, clk_mgr->clks.dispclk_khz)) { - context->bw.dce.dispclk_khz = dce_set_clock(clk_mgr, context->bw.dce.dispclk_khz); - clk_mgr->clks.dispclk_khz = context->bw.dce.dispclk_khz; + if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) { + context->bw.dce.dispclk_khz = dce_set_clock(clk_mgr, patched_disp_clk); + clk_mgr->clks.dispclk_khz = patched_disp_clk; } dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h index acd418515346..a6b80fdaa666 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -37,6 +37,10 @@ void dce100_prepare_bandwidth( struct dc *dc, struct dc_state *context); +void dce100_optimize_bandwidth( + struct dc *dc, + struct dc_state *context); + bool dce100_enable_display_power_gating(struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 4bf24758217f..8f09b8625c5d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1000,7 +1000,7 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); - if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) + if (num_audio >= 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ pp_smu->set_pme_wa_enable(&pp_smu->pp_smu); /* un-mute audio */ @@ -1017,6 +1017,8 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( pipe_ctx->stream_res.stream_enc, true); if (pipe_ctx->stream_res.audio) { + struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; + if (option != KEEP_ACQUIRED_RESOURCE || !dc->debug.az_endpoint_mute_only) { /*only disalbe az_endpoint if power down or free*/ @@ -1036,6 +1038,9 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false); pipe_ctx->stream_res.audio = NULL; } + if (pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) + /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ + pp_smu->set_pme_wa_enable(&pp_smu->pp_smu); /* TODO: notify audio driver for if audio modes list changed * add audio mode list change flag */ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c index a60a90e68d91..c4543178ba20 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -77,6 +77,6 @@ void dce80_hw_sequencer_construct(struct dc *dc) dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; dc->hwss.pipe_control_lock = dce_pipe_control_lock; dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth; - dc->hwss.optimize_bandwidth = dce100_prepare_bandwidth; + dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth; } diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index cdd1d6b7b9f2..4e9ea50141bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -790,9 +790,22 @@ bool dce80_validate_bandwidth( struct dc *dc, struct dc_state *context) { - /* TODO implement when needed but for now hardcode max value*/ - context->bw.dce.dispclk_khz = 681000; - context->bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ; + int i; + bool at_least_one_pipe = false; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].stream) + at_least_one_pipe = true; + } + + if (at_least_one_pipe) { + /* TODO implement when needed but for now hardcode max value*/ + context->bw.dce.dispclk_khz = 681000; + context->bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ; + } else { + context->bw.dce.dispclk_khz = 0; + context->bw.dce.yclk_khz = 0; + } return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index dcb3c5530236..cd1ebe57ed59 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -463,7 +463,7 @@ void dpp1_set_cursor_position( if (src_y_offset >= (int)param->viewport.height) cur_en = 0; /* not visible beyond bottom edge*/ - if (src_y_offset < 0) + if (src_y_offset + (int)height <= 0) cur_en = 0; /* not visible beyond top edge*/ REG_UPDATE(CURSOR0_CONTROL, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index 345af015d061..d1acd7165bc8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -1140,7 +1140,7 @@ void hubp1_cursor_set_position( if (src_y_offset >= (int)param->viewport.height) cur_en = 0; /* not visible beyond bottom edge*/ - if (src_y_offset < 0) //+ (int)hubp->curs_attr.height + if (src_y_offset + (int)hubp->curs_attr.height <= 0) cur_en = 0; /* not visible beyond top edge*/ if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 91e015e14355..41883c981789 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2355,29 +2355,22 @@ static void dcn10_apply_ctx_for_surface( top_pipe_to_program->plane_state->update_flags.bits.full_update) for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - + tg = pipe_ctx->stream_res.tg; /* Skip inactive pipes and ones already updated */ if (!pipe_ctx->stream || pipe_ctx->stream == stream - || !pipe_ctx->plane_state) + || !pipe_ctx->plane_state + || !tg->funcs->is_tg_enabled(tg)) continue; - pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); + tg->funcs->lock(tg); pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent( pipe_ctx->plane_res.hubp, &pipe_ctx->dlg_regs, &pipe_ctx->ttu_regs); - } - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (!pipe_ctx->stream || pipe_ctx->stream == stream - || !pipe_ctx->plane_state) - continue; - - dcn10_pipe_control_lock(dc, pipe_ctx, false); - } + tg->funcs->unlock(tg); + } if (num_planes == 0) false_optc_underflow_wa(dc, stream, tg); @@ -2665,8 +2658,8 @@ static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) .mirror = pipe_ctx->plane_state->horizontal_mirror }; - pos_cpy.x -= pipe_ctx->plane_state->dst_rect.x; - pos_cpy.y -= pipe_ctx->plane_state->dst_rect.y; + pos_cpy.x_hotspot += pipe_ctx->plane_state->dst_rect.x; + pos_cpy.y_hotspot += pipe_ctx->plane_state->dst_rect.y; if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c index 00f63b7dd32f..c11a443dcbc8 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c @@ -57,6 +57,7 @@ static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_le #define NUM_POWER_FN_SEGS 8 #define NUM_BL_CURVE_SEGS 16 +#pragma pack(push, 1) /* NOTE: iRAM is 256B in size */ struct iram_table_v_2 { /* flags */ @@ -100,6 +101,7 @@ struct iram_table_v_2 { uint8_t dummy8; /* 0xfe */ uint8_t dummy9; /* 0xff */ }; +#pragma pack(pop) static uint16_t backlight_8_to_16(unsigned int backlight_8bit) { diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 1479ea1dc3e7..789c4f288485 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -127,12 +127,13 @@ enum amd_pp_task { }; enum PP_SMC_POWER_PROFILE { - PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x0, - PP_SMC_POWER_PROFILE_POWERSAVING = 0x1, - PP_SMC_POWER_PROFILE_VIDEO = 0x2, - PP_SMC_POWER_PROFILE_VR = 0x3, - PP_SMC_POWER_PROFILE_COMPUTE = 0x4, - PP_SMC_POWER_PROFILE_CUSTOM = 0x5, + PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT = 0x0, + PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x1, + PP_SMC_POWER_PROFILE_POWERSAVING = 0x2, + PP_SMC_POWER_PROFILE_VIDEO = 0x3, + PP_SMC_POWER_PROFILE_VR = 0x4, + PP_SMC_POWER_PROFILE_COMPUTE = 0x5, + PP_SMC_POWER_PROFILE_CUSTOM = 0x6, }; enum { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 0173d0480024..310b102a9292 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -64,17 +64,19 @@ static int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr); static void hwmgr_init_workload_prority(struct pp_hwmgr *hwmgr) { - hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 2; - hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 0; - hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 1; - hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 3; - hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 4; - - hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_POWERSAVING; - hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_VIDEO; - hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_FULLSCREEN3D; - hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VR; - hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_COMPUTE; + hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0; + hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1; + hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2; + hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3; + hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4; + hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5; + + hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D; + hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING; + hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO; + hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_VR; + hwmgr->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE; } int hwmgr_early_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c index f95c5f50eb0f..5273de3c5b98 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c @@ -1033,6 +1033,7 @@ static int smu10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, break; case amd_pp_dpp_clock: pclk_vol_table = pinfo->vdd_dep_on_dppclk; + break; default: return -EINVAL; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index d91390459326..c8f5c00dd1e7 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -77,8 +77,9 @@ #define PCIE_BUS_CLK 10000 #define TCLK (PCIE_BUS_CLK / 10) -static const struct profile_mode_setting smu7_profiling[6] = - {{1, 0, 100, 30, 1, 0, 100, 10}, +static const struct profile_mode_setting smu7_profiling[7] = + {{0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 100, 30, 1, 0, 100, 10}, {1, 10, 0, 30, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 10, 16, 31}, {1, 0, 11, 50, 1, 0, 100, 10}, @@ -4889,7 +4890,8 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) uint32_t i, size = 0; uint32_t len; - static const char *profile_name[6] = {"3D_FULL_SCREEN", + static const char *profile_name[7] = {"BOOTUP_DEFAULT", + "3D_FULL_SCREEN", "POWER_SAVING", "VIDEO", "VR", diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 79c86247d0ac..91e3bbe6d61d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -804,9 +804,9 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) hwmgr->backend = data; - hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO]; - hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO; - hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO; + hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; + hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; vega10_set_default_registry_data(hwmgr); data->disable_dpm_mask = 0xff; @@ -4668,13 +4668,15 @@ static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) { struct vega10_hwmgr *data = hwmgr->backend; uint32_t i, size = 0; - static const uint8_t profile_mode_setting[5][4] = {{70, 60, 1, 3,}, + static const uint8_t profile_mode_setting[6][4] = {{70, 60, 0, 0,}, + {70, 60, 1, 3,}, {90, 60, 0, 0,}, {70, 60, 0, 0,}, {70, 90, 0, 0,}, {30, 60, 0, 6,}, }; - static const char *profile_name[6] = {"3D_FULL_SCREEN", + static const char *profile_name[7] = {"BOOTUP_DEFAULT", + "3D_FULL_SCREEN", "POWER_SAVING", "VIDEO", "VR", diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c index b8747a5c9204..99d596dc0e89 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c @@ -32,6 +32,7 @@ #include "vega10_pptable.h" #define NUM_DSPCLK_LEVELS 8 +#define VEGA10_ENGINECLOCK_HARDMAX 198000 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, enum phm_platform_caps cap) @@ -258,7 +259,26 @@ static int init_over_drive_limits( struct pp_hwmgr *hwmgr, const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) { - hwmgr->platform_descriptor.overdriveLimit.engineClock = + const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = + (const ATOM_Vega10_GFXCLK_Dependency_Table *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); + bool is_acg_enabled = false; + ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2; + + if (gfxclk_dep_table->ucRevId == 1) { + patom_record_v2 = + (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries; + is_acg_enabled = + (bool)patom_record_v2[gfxclk_dep_table->ucNumEntries-1].ucACGEnable; + } + + if (powerplay_table->ulMaxODEngineClock > VEGA10_ENGINECLOCK_HARDMAX && + !is_acg_enabled) + hwmgr->platform_descriptor.overdriveLimit.engineClock = + VEGA10_ENGINECLOCK_HARDMAX; + else + hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(powerplay_table->ulMaxODEngineClock); hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(powerplay_table->ulMaxODMemoryClock); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c index 54364444ecd1..0c8212902275 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c @@ -753,6 +753,22 @@ static int vega12_init_smc_table(struct pp_hwmgr *hwmgr) return 0; } +static int vega12_run_acg_btc(struct pp_hwmgr *hwmgr) +{ + uint32_t result; + + PP_ASSERT_WITH_CODE( + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc) == 0, + "[Run_ACG_BTC] Attempt to run ACG BTC failed!", + return -EINVAL); + + result = smum_get_argument(hwmgr); + PP_ASSERT_WITH_CODE(result == 1, + "Failed to run ACG BTC!", return -EINVAL); + + return 0; +} + static int vega12_set_allowed_featuresmask(struct pp_hwmgr *hwmgr) { struct vega12_hwmgr *data = @@ -931,6 +947,11 @@ static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr) "Failed to initialize SMC table!", result = tmp_result); + tmp_result = vega12_run_acg_btc(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to run ACG BTC!", + result = tmp_result); + result = vega12_enable_all_smu_features(hwmgr); PP_ASSERT_WITH_CODE(!result, "Failed to enable all smu features!", diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index 26154f9b2178..82935a3bd950 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -390,9 +390,9 @@ static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr) hwmgr->backend = data; - hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO]; - hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO; - hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO; + hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; + hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; vega20_set_default_registry_data(hwmgr); @@ -980,6 +980,9 @@ static int vega20_od8_set_feature_capabilities( pp_table->FanZeroRpmEnable) od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL; + if (!od_settings->overdrive8_capabilities) + hwmgr->od_enabled = false; + return 0; } @@ -1689,13 +1692,6 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_ (PPCLK_UCLK << 16) | (min_freq & 0xffff))), "Failed to set soft min memclk !", return ret); - - min_freq = data->dpm_table.mem_table.dpm_state.hard_min_level; - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetHardMinByFreq, - (PPCLK_UCLK << 16) | (min_freq & 0xffff))), - "Failed to set hard min memclk !", - return ret); } if (data->smu_features[GNLD_DPM_UVD].enabled && @@ -2248,6 +2244,13 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr, soft_min_level = mask ? (ffs(mask) - 1) : 0; soft_max_level = mask ? (fls(mask) - 1) : 0; + if (soft_max_level >= data->dpm_table.gfx_table.count) { + pr_err("Clock level specified %d is over max allowed %d\n", + soft_max_level, + data->dpm_table.gfx_table.count - 1); + return -EINVAL; + } + data->dpm_table.gfx_table.dpm_state.soft_min_level = data->dpm_table.gfx_table.dpm_levels[soft_min_level].value; data->dpm_table.gfx_table.dpm_state.soft_max_level = @@ -2268,6 +2271,13 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr, soft_min_level = mask ? (ffs(mask) - 1) : 0; soft_max_level = mask ? (fls(mask) - 1) : 0; + if (soft_max_level >= data->dpm_table.mem_table.count) { + pr_err("Clock level specified %d is over max allowed %d\n", + soft_max_level, + data->dpm_table.mem_table.count - 1); + return -EINVAL; + } + data->dpm_table.mem_table.dpm_state.soft_min_level = data->dpm_table.mem_table.dpm_levels[soft_min_level].value; data->dpm_table.mem_table.dpm_state.soft_max_level = @@ -3261,6 +3271,9 @@ static int conv_power_profile_to_pplib_workload(int power_profile) int pplib_workload = 0; switch (power_profile) { + case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT: + pplib_workload = WORKLOAD_DEFAULT_BIT; + break; case PP_SMC_POWER_PROFILE_FULLSCREEN3D: pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT; break; @@ -3290,6 +3303,7 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) uint32_t i, size = 0; uint16_t workload_type = 0; static const char *profile_name[] = { + "BOOTUP_DEFAULT", "3D_FULL_SCREEN", "POWER_SAVING", "VIDEO", diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 0d298a0409f5..8cb831b6a016 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -705,7 +705,7 @@ enum PP_TABLE_VERSION { /** * The main hardware manager structure. */ -#define Workload_Policy_Max 5 +#define Workload_Policy_Max 6 struct pp_hwmgr { void *adev; diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index f3dd66ae990a..aa35007262cd 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c @@ -154,6 +154,10 @@ static int bochs_pci_probe(struct pci_dev *pdev, if (IS_ERR(dev)) return PTR_ERR(dev); + ret = pci_enable_device(pdev); + if (ret) + goto err_free_dev; + dev->pdev = pdev; pci_set_drvdata(pdev, dev); diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 8e28e738cb52..e6403b9549f1 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -98,6 +98,8 @@ #define DP0_STARTVAL 0x064c #define DP0_ACTIVEVAL 0x0650 #define DP0_SYNCVAL 0x0654 +#define SYNCVAL_HS_POL_ACTIVE_LOW (1 << 15) +#define SYNCVAL_VS_POL_ACTIVE_LOW (1 << 31) #define DP0_MISC 0x0658 #define TU_SIZE_RECOMMENDED (63) /* LSCLK cycles per TU */ #define BPC_6 (0 << 5) @@ -142,6 +144,8 @@ #define DP0_LTLOOPCTRL 0x06d8 #define DP0_SNKLTCTRL 0x06e4 +#define DP1_SRCCTRL 0x07a0 + /* PHY */ #define DP_PHY_CTRL 0x0800 #define DP_PHY_RST BIT(28) /* DP PHY Global Soft Reset */ @@ -150,6 +154,7 @@ #define PHY_M1_RST BIT(12) /* Reset PHY1 Main Channel */ #define PHY_RDY BIT(16) /* PHY Main Channels Ready */ #define PHY_M0_RST BIT(8) /* Reset PHY0 Main Channel */ +#define PHY_2LANE BIT(2) /* PHY Enable 2 lanes */ #define PHY_A0_EN BIT(1) /* PHY Aux Channel0 Enable */ #define PHY_M0_EN BIT(0) /* PHY Main Channel0 Enable */ @@ -540,6 +545,7 @@ static int tc_aux_link_setup(struct tc_data *tc) unsigned long rate; u32 value; int ret; + u32 dp_phy_ctrl; rate = clk_get_rate(tc->refclk); switch (rate) { @@ -564,7 +570,10 @@ static int tc_aux_link_setup(struct tc_data *tc) value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2; tc_write(SYS_PLLPARAM, value); - tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN); + dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN; + if (tc->link.base.num_lanes == 2) + dp_phy_ctrl |= PHY_2LANE; + tc_write(DP_PHY_CTRL, dp_phy_ctrl); /* * Initially PLLs are in bypass. Force PLL parameter update, @@ -719,7 +728,9 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode) tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay)); - tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0)); + tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0) | + ((mode->flags & DRM_MODE_FLAG_NHSYNC) ? SYNCVAL_HS_POL_ACTIVE_LOW : 0) | + ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? SYNCVAL_VS_POL_ACTIVE_LOW : 0)); tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW | DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888); @@ -829,12 +840,11 @@ static int tc_main_link_setup(struct tc_data *tc) if (!tc->mode) return -EINVAL; - /* from excel file - DP0_SrcCtrl */ - tc_write(DP0_SRCCTRL, DP0_SRCCTRL_SCRMBLDIS | DP0_SRCCTRL_EN810B | - DP0_SRCCTRL_LANESKEW | DP0_SRCCTRL_LANES_2 | - DP0_SRCCTRL_BW27 | DP0_SRCCTRL_AUTOCORRECT); - /* from excel file - DP1_SrcCtrl */ - tc_write(0x07a0, 0x00003083); + tc_write(DP0_SRCCTRL, tc_srcctrl(tc)); + /* SSCG and BW27 on DP1 must be set to the same as on DP0 */ + tc_write(DP1_SRCCTRL, + (tc->link.spread ? DP0_SRCCTRL_SSCG : 0) | + ((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0)); rate = clk_get_rate(tc->refclk); switch (rate) { @@ -855,8 +865,11 @@ static int tc_main_link_setup(struct tc_data *tc) } value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2; tc_write(SYS_PLLPARAM, value); + /* Setup Main Link */ - dp_phy_ctrl = BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN | PHY_M0_EN; + dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN; + if (tc->link.base.num_lanes == 2) + dp_phy_ctrl |= PHY_2LANE; tc_write(DP_PHY_CTRL, dp_phy_ctrl); msleep(100); @@ -1105,10 +1118,20 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge, static enum drm_mode_status tc_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { + struct tc_data *tc = connector_to_tc(connector); + u32 req, avail; + u32 bits_per_pixel = 24; + /* DPI interface clock limitation: upto 154 MHz */ if (mode->clock > 154000) return MODE_CLOCK_HIGH; + req = mode->clock * bits_per_pixel / 8; + avail = tc->link.base.num_lanes * tc->link.base.rate; + + if (req > avail) + return MODE_BAD; + return MODE_OK; } @@ -1186,7 +1209,8 @@ static int tc_bridge_attach(struct drm_bridge *bridge) /* Create eDP connector */ drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs); ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs, - DRM_MODE_CONNECTOR_eDP); + tc->panel ? DRM_MODE_CONNECTOR_eDP : + DRM_MODE_CONNECTOR_DisplayPort); if (ret) return ret; @@ -1195,6 +1219,10 @@ static int tc_bridge_attach(struct drm_bridge *bridge) drm_display_info_set_bus_formats(&tc->connector.display_info, &bus_format, 1); + tc->connector.display_info.bus_flags = + DRM_BUS_FLAG_DE_HIGH | + DRM_BUS_FLAG_PIXDATA_NEGEDGE | + DRM_BUS_FLAG_SYNC_NEGEDGE; drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder); return 0; diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 54e2ae614dcc..f4290f6b0c38 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1602,6 +1602,15 @@ int drm_atomic_helper_async_check(struct drm_device *dev, old_plane_state->crtc != new_plane_state->crtc) return -EINVAL; + /* + * FIXME: Since prepare_fb and cleanup_fb are always called on + * the new_plane_state for async updates we need to block framebuffer + * changes. This prevents use of a fb that's been cleaned up and + * double cleanups from occuring. + */ + if (old_plane_state->fb != new_plane_state->fb) + return -EINVAL; + funcs = plane->helper_private; if (!funcs->atomic_async_update) return -EINVAL; diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index c40889888a16..9a1f41adfc67 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1296,12 +1296,11 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, (arg->flags & DRM_MODE_PAGE_FLIP_EVENT)) return -EINVAL; - drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); - state = drm_atomic_state_alloc(dev); if (!state) return -ENOMEM; + drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); state->acquire_ctx = &ctx; state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET); diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 2d6c491a0542..516e82d0ed50 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -1273,6 +1273,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = { { OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_CONSTANT_N) }, /* LG LP140WF6-SPM1 eDP panel */ { OUI(0x00, 0x22, 0xb9), DEVICE_ID('s', 'i', 'v', 'a', 'r', 'T'), false, BIT(DP_DPCD_QUIRK_CONSTANT_N) }, + /* Apple panels need some additional handling to support PSR */ + { OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_NO_PSR) } }; #undef OUI diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index d3af098b0922..d73703a695e8 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1621,6 +1621,64 @@ static bool drm_fb_pixel_format_equal(const struct fb_var_screeninfo *var_1, var_1->transp.msb_right == var_2->transp.msb_right; } +static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var, + u8 depth) +{ + switch (depth) { + case 8: + var->red.offset = 0; + var->green.offset = 0; + var->blue.offset = 0; + var->red.length = 8; /* 8bit DAC */ + var->green.length = 8; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 15: + var->red.offset = 10; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; + var->transp.offset = 15; + var->transp.length = 1; + break; + case 16: + var->red.offset = 11; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; + var->transp.offset = 0; + break; + case 24: + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 32: + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.offset = 24; + var->transp.length = 8; + break; + default: + break; + } +} + /** * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var * @var: screeninfo to check @@ -1632,9 +1690,14 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, struct drm_fb_helper *fb_helper = info->par; struct drm_framebuffer *fb = fb_helper->fb; - if (var->pixclock != 0 || in_dbg_master()) + if (in_dbg_master()) return -EINVAL; + if (var->pixclock != 0) { + DRM_DEBUG("fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n"); + var->pixclock = 0; + } + if ((drm_format_info_block_width(fb->format, 0) > 1) || (drm_format_info_block_height(fb->format, 0) > 1)) return -EINVAL; @@ -1655,6 +1718,20 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, } /* + * Workaround for SDL 1.2, which is known to be setting all pixel format + * fields values to zero in some cases. We treat this situation as a + * kind of "use some reasonable autodetected values". + */ + if (!var->red.offset && !var->green.offset && + !var->blue.offset && !var->transp.offset && + !var->red.length && !var->green.length && + !var->blue.length && !var->transp.length && + !var->red.msb_right && !var->green.msb_right && + !var->blue.msb_right && !var->transp.msb_right) { + drm_fb_helper_fill_pixel_fmt(var, fb->format->depth); + } + + /* * drm fbdev emulation doesn't support changing the pixel format at all, * so reject all pixel format changing requests. */ @@ -1967,59 +2044,7 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe info->var.yoffset = 0; info->var.activate = FB_ACTIVATE_NOW; - switch (fb->format->depth) { - case 8: - info->var.red.offset = 0; - info->var.green.offset = 0; - info->var.blue.offset = 0; - info->var.red.length = 8; /* 8bit DAC */ - info->var.green.length = 8; - info->var.blue.length = 8; - info->var.transp.offset = 0; - info->var.transp.length = 0; - break; - case 15: - info->var.red.offset = 10; - info->var.green.offset = 5; - info->var.blue.offset = 0; - info->var.red.length = 5; - info->var.green.length = 5; - info->var.blue.length = 5; - info->var.transp.offset = 15; - info->var.transp.length = 1; - break; - case 16: - info->var.red.offset = 11; - info->var.green.offset = 5; - info->var.blue.offset = 0; - info->var.red.length = 5; - info->var.green.length = 6; - info->var.blue.length = 5; - info->var.transp.offset = 0; - break; - case 24: - info->var.red.offset = 16; - info->var.green.offset = 8; - info->var.blue.offset = 0; - info->var.red.length = 8; - info->var.green.length = 8; - info->var.blue.length = 8; - info->var.transp.offset = 0; - info->var.transp.length = 0; - break; - case 32: - info->var.red.offset = 16; - info->var.green.offset = 8; - info->var.blue.offset = 0; - info->var.red.length = 8; - info->var.green.length = 8; - info->var.blue.length = 8; - info->var.transp.offset = 24; - info->var.transp.length = 8; - break; - default: - break; - } + drm_fb_helper_fill_pixel_fmt(&info->var, fb->format->depth); info->var.xres = fb_width; info->var.yres = fb_height; diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c index 99cba8ea5d82..5df1256618cc 100644 --- a/drivers/gpu/drm/drm_lease.c +++ b/drivers/gpu/drm/drm_lease.c @@ -528,7 +528,8 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev, object_count = cl->object_count; - object_ids = memdup_user(u64_to_user_ptr(cl->object_ids), object_count * sizeof(__u32)); + object_ids = memdup_user(u64_to_user_ptr(cl->object_ids), + array_size(object_count, sizeof(__u32))); if (IS_ERR(object_ids)) return PTR_ERR(object_ids); diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index cd9bc0ce9be0..004191d01772 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -459,11 +459,11 @@ static int set_property_atomic(struct drm_mode_object *obj, struct drm_modeset_acquire_ctx ctx; int ret; - drm_modeset_acquire_init(&ctx, 0); - state = drm_atomic_state_alloc(dev); if (!state) return -ENOMEM; + + drm_modeset_acquire_init(&ctx, 0); state->acquire_ctx = &ctx; retry: if (prop == state->dev->mode_config.dpms_property) { diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 24a750436559..f91e02c87fd8 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -758,7 +758,7 @@ int drm_mode_hsync(const struct drm_display_mode *mode) if (mode->hsync) return mode->hsync; - if (mode->htotal < 0) + if (mode->htotal <= 0) return 0; calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */ diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index a9d9df6c85ad..693748ad8b88 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -61,8 +61,9 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali return NULL; dmah->size = size; - dmah->vaddr = dma_zalloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, - GFP_KERNEL | __GFP_COMP); + dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, + &dmah->busaddr, + GFP_KERNEL | __GFP_COMP); if (dmah->vaddr == NULL) { kfree(dmah); diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index b5475c91e2ef..e9f343b124b0 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -2799,6 +2799,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt) MMIO_DFH(_MMIO(0xe2a0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(_MMIO(0xe2b0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(_MMIO(0xe2c0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); + MMIO_DFH(_MMIO(0x21f0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); return 0; } diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h index 5af11cf1b482..e1675a00df12 100644 --- a/drivers/gpu/drm/i915/gvt/hypercall.h +++ b/drivers/gpu/drm/i915/gvt/hypercall.h @@ -41,7 +41,7 @@ struct intel_gvt_mpt { int (*host_init)(struct device *dev, void *gvt, const void *ops); void (*host_exit)(struct device *dev, void *gvt); int (*attach_vgpu)(void *vgpu, unsigned long *handle); - void (*detach_vgpu)(unsigned long handle); + void (*detach_vgpu)(void *vgpu); int (*inject_msi)(unsigned long handle, u32 addr, u16 data); unsigned long (*from_virt_to_mfn)(void *p); int (*enable_page_track)(unsigned long handle, u64 gfn); diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index c1072143da1d..dd3dfd00f4e6 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -996,7 +996,7 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma) { unsigned int index; u64 virtaddr; - unsigned long req_size, pgoff = 0; + unsigned long req_size, pgoff, req_start; pgprot_t pg_prot; struct intel_vgpu *vgpu = mdev_get_drvdata(mdev); @@ -1014,7 +1014,17 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma) pg_prot = vma->vm_page_prot; virtaddr = vma->vm_start; req_size = vma->vm_end - vma->vm_start; - pgoff = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT; + pgoff = vma->vm_pgoff & + ((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1); + req_start = pgoff << PAGE_SHIFT; + + if (!intel_vgpu_in_aperture(vgpu, req_start)) + return -EINVAL; + if (req_start + req_size > + vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu)) + return -EINVAL; + + pgoff = (gvt_aperture_pa_base(vgpu->gvt) >> PAGE_SHIFT) + pgoff; return remap_pfn_range(vma, virtaddr, pgoff, req_size, pg_prot); } @@ -1662,9 +1672,21 @@ static int kvmgt_attach_vgpu(void *vgpu, unsigned long *handle) return 0; } -static void kvmgt_detach_vgpu(unsigned long handle) +static void kvmgt_detach_vgpu(void *p_vgpu) { - /* nothing to do here */ + int i; + struct intel_vgpu *vgpu = (struct intel_vgpu *)p_vgpu; + + if (!vgpu->vdev.region) + return; + + for (i = 0; i < vgpu->vdev.num_regions; i++) + if (vgpu->vdev.region[i].ops->release) + vgpu->vdev.region[i].ops->release(vgpu, + &vgpu->vdev.region[i]); + vgpu->vdev.num_regions = 0; + kfree(vgpu->vdev.region); + vgpu->vdev.region = NULL; } static int kvmgt_inject_msi(unsigned long handle, u32 addr, u16 data) diff --git a/drivers/gpu/drm/i915/gvt/mpt.h b/drivers/gpu/drm/i915/gvt/mpt.h index 67f19992b226..3ed34123d8d1 100644 --- a/drivers/gpu/drm/i915/gvt/mpt.h +++ b/drivers/gpu/drm/i915/gvt/mpt.h @@ -101,7 +101,7 @@ static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu) if (!intel_gvt_host.mpt->detach_vgpu) return; - intel_gvt_host.mpt->detach_vgpu(vgpu->handle); + intel_gvt_host.mpt->detach_vgpu(vgpu); } #define MSI_CAP_CONTROL(offset) (offset + 2) diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 1ad8c5e1455d..55bb7885e228 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -332,6 +332,9 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj); i915_gem_object_put(wa_ctx->indirect_ctx.obj); + + wa_ctx->indirect_ctx.obj = NULL; + wa_ctx->indirect_ctx.shadow_va = NULL; } static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload, @@ -356,6 +359,33 @@ static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload, return 0; } +static int +intel_gvt_workload_req_alloc(struct intel_vgpu_workload *workload) +{ + struct intel_vgpu *vgpu = workload->vgpu; + struct intel_vgpu_submission *s = &vgpu->submission; + struct i915_gem_context *shadow_ctx = s->shadow_ctx; + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + struct intel_engine_cs *engine = dev_priv->engine[workload->ring_id]; + struct i915_request *rq; + int ret = 0; + + lockdep_assert_held(&dev_priv->drm.struct_mutex); + + if (workload->req) + goto out; + + rq = i915_request_alloc(engine, shadow_ctx); + if (IS_ERR(rq)) { + gvt_vgpu_err("fail to allocate gem request\n"); + ret = PTR_ERR(rq); + goto out; + } + workload->req = i915_request_get(rq); +out: + return ret; +} + /** * intel_gvt_scan_and_shadow_workload - audit the workload by scanning and * shadow it as well, include ringbuffer,wa_ctx and ctx. @@ -372,12 +402,11 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; struct intel_engine_cs *engine = dev_priv->engine[workload->ring_id]; struct intel_context *ce; - struct i915_request *rq; int ret; lockdep_assert_held(&dev_priv->drm.struct_mutex); - if (workload->req) + if (workload->shadow) return 0; ret = set_context_ppgtt_from_shadow(workload, shadow_ctx); @@ -417,22 +446,8 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) goto err_shadow; } - rq = i915_request_alloc(engine, shadow_ctx); - if (IS_ERR(rq)) { - gvt_vgpu_err("fail to allocate gem request\n"); - ret = PTR_ERR(rq); - goto err_shadow; - } - workload->req = i915_request_get(rq); - - ret = populate_shadow_context(workload); - if (ret) - goto err_req; - + workload->shadow = true; return 0; -err_req: - rq = fetch_and_zero(&workload->req); - i915_request_put(rq); err_shadow: release_shadow_wa_ctx(&workload->wa_ctx); err_unpin: @@ -671,23 +686,31 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) mutex_lock(&vgpu->vgpu_lock); mutex_lock(&dev_priv->drm.struct_mutex); + ret = intel_gvt_workload_req_alloc(workload); + if (ret) + goto err_req; + ret = intel_gvt_scan_and_shadow_workload(workload); if (ret) goto out; - ret = prepare_workload(workload); + ret = populate_shadow_context(workload); + if (ret) { + release_shadow_wa_ctx(&workload->wa_ctx); + goto out; + } + ret = prepare_workload(workload); out: - if (ret) - workload->status = ret; - if (!IS_ERR_OR_NULL(workload->req)) { gvt_dbg_sched("ring id %d submit workload to i915 %p\n", ring_id, workload->req); i915_request_add(workload->req); workload->dispatched = true; } - +err_req: + if (ret) + workload->status = ret; mutex_unlock(&dev_priv->drm.struct_mutex); mutex_unlock(&vgpu->vgpu_lock); return ret; @@ -891,11 +914,6 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id) list_del_init(&workload->list); - if (!workload->status) { - release_shadow_batch_buffer(workload); - release_shadow_wa_ctx(&workload->wa_ctx); - } - if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) { /* if workload->status is not successful means HW GPU * has occurred GPU hang or something wrong with i915/GVT, @@ -1263,6 +1281,9 @@ void intel_vgpu_destroy_workload(struct intel_vgpu_workload *workload) { struct intel_vgpu_submission *s = &workload->vgpu->submission; + release_shadow_batch_buffer(workload); + release_shadow_wa_ctx(&workload->wa_ctx); + if (workload->shadow_mm) intel_vgpu_mm_put(workload->shadow_mm); diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index ca5529d0e48e..2065cba59aab 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.h +++ b/drivers/gpu/drm/i915/gvt/scheduler.h @@ -83,6 +83,7 @@ struct intel_vgpu_workload { struct i915_request *req; /* if this workload has been dispatched to i915? */ bool dispatched; + bool shadow; /* if workload has done shadow of guest request */ int status; struct intel_vgpu_mm *shadow_mm; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 38dcee1ca062..40a61ef9aac1 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -984,8 +984,8 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file) intel_runtime_pm_get(i915); gpu = i915_capture_gpu_state(i915); intel_runtime_pm_put(i915); - if (!gpu) - return -ENOMEM; + if (IS_ERR(gpu)) + return PTR_ERR(gpu); file->private_data = gpu; return 0; @@ -1018,7 +1018,13 @@ i915_error_state_write(struct file *filp, static int i915_error_state_open(struct inode *inode, struct file *file) { - file->private_data = i915_first_error_state(inode->i_private); + struct i915_gpu_state *error; + + error = i915_first_error_state(inode->i_private); + if (IS_ERR(error)) + return PTR_ERR(error); + + file->private_data = error; return 0; } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 216f52b744a6..c882ea94172c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1824,6 +1824,16 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, return 0; } +static inline bool +__vma_matches(struct vm_area_struct *vma, struct file *filp, + unsigned long addr, unsigned long size) +{ + if (vma->vm_file != filp) + return false; + + return vma->vm_start == addr && (vma->vm_end - vma->vm_start) == size; +} + /** * i915_gem_mmap_ioctl - Maps the contents of an object, returning the address * it is mapped to. @@ -1882,7 +1892,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, return -EINTR; } vma = find_vma(mm, addr); - if (vma) + if (vma && __vma_matches(vma, obj->base.filp, addr, args->size)) vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); else diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index add1fe7aeb93..bd17dd1f5da5 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2075,6 +2075,7 @@ static struct i915_vma *pd_vma_create(struct gen6_hw_ppgtt *ppgtt, int size) int gen6_ppgtt_pin(struct i915_hw_ppgtt *base) { struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base); + int err; /* * Workaround the limited maximum vma->pin_count and the aliasing_ppgtt @@ -2090,9 +2091,17 @@ int gen6_ppgtt_pin(struct i915_hw_ppgtt *base) * allocator works in address space sizes, so it's multiplied by page * size. We allocate at the top of the GTT to avoid fragmentation. */ - return i915_vma_pin(ppgtt->vma, - 0, GEN6_PD_ALIGN, - PIN_GLOBAL | PIN_HIGH); + err = i915_vma_pin(ppgtt->vma, + 0, GEN6_PD_ALIGN, + PIN_GLOBAL | PIN_HIGH); + if (err) + goto unpin; + + return 0; + +unpin: + ppgtt->pin_count = 0; + return err; } void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 07465123c166..3f9ce403c755 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1907,9 +1907,16 @@ i915_capture_gpu_state(struct drm_i915_private *i915) { struct i915_gpu_state *error; + /* Check if GPU capture has been disabled */ + error = READ_ONCE(i915->gpu_error.first_error); + if (IS_ERR(error)) + return error; + error = kzalloc(sizeof(*error), GFP_ATOMIC); - if (!error) - return NULL; + if (!error) { + i915_disable_error_state(i915, -ENOMEM); + return ERR_PTR(-ENOMEM); + } kref_init(&error->ref); error->i915 = i915; @@ -1945,11 +1952,8 @@ void i915_capture_error_state(struct drm_i915_private *i915, return; error = i915_capture_gpu_state(i915); - if (!error) { - DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); - i915_disable_error_state(i915, -ENOMEM); + if (IS_ERR(error)) return; - } i915_error_capture_msg(i915, error, engine_mask, error_msg); DRM_INFO("%s\n", error->error_msg); @@ -1987,7 +1991,7 @@ i915_first_error_state(struct drm_i915_private *i915) spin_lock_irq(&i915->gpu_error.lock); error = i915->gpu_error.first_error; - if (error) + if (!IS_ERR_OR_NULL(error)) i915_gpu_state_get(error); spin_unlock_irq(&i915->gpu_error.lock); @@ -2000,10 +2004,11 @@ void i915_reset_error_state(struct drm_i915_private *i915) spin_lock_irq(&i915->gpu_error.lock); error = i915->gpu_error.first_error; - i915->gpu_error.first_error = NULL; + if (error != ERR_PTR(-ENODEV)) /* if disabled, always disabled */ + i915->gpu_error.first_error = NULL; spin_unlock_irq(&i915->gpu_error.lock); - if (!IS_ERR(error)) + if (!IS_ERR_OR_NULL(error)) i915_gpu_state_put(error); } diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index d6c8f8fdfda5..017fc602a10e 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -594,7 +594,8 @@ static void i915_pmu_enable(struct perf_event *event) * Update the bitmask of enabled events and increment * the event reference counter. */ - GEM_BUG_ON(bit >= I915_PMU_MASK_BITS); + BUILD_BUG_ON(ARRAY_SIZE(i915->pmu.enable_count) != I915_PMU_MASK_BITS); + GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count)); GEM_BUG_ON(i915->pmu.enable_count[bit] == ~0); i915->pmu.enable |= BIT_ULL(bit); i915->pmu.enable_count[bit]++; @@ -615,11 +616,16 @@ static void i915_pmu_enable(struct perf_event *event) engine = intel_engine_lookup_user(i915, engine_event_class(event), engine_event_instance(event)); - GEM_BUG_ON(!engine); - engine->pmu.enable |= BIT(sample); - GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS); + BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.enable_count) != + I915_ENGINE_SAMPLE_COUNT); + BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.sample) != + I915_ENGINE_SAMPLE_COUNT); + GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count)); + GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample)); GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0); + + engine->pmu.enable |= BIT(sample); engine->pmu.enable_count[sample]++; } @@ -649,9 +655,11 @@ static void i915_pmu_disable(struct perf_event *event) engine = intel_engine_lookup_user(i915, engine_event_class(event), engine_event_instance(event)); - GEM_BUG_ON(!engine); - GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS); + + GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count)); + GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample)); GEM_BUG_ON(engine->pmu.enable_count[sample] == 0); + /* * Decrement the reference count and clear the enabled * bitmask when the last listener on an event goes away. @@ -660,7 +668,7 @@ static void i915_pmu_disable(struct perf_event *event) engine->pmu.enable &= ~BIT(sample); } - GEM_BUG_ON(bit >= I915_PMU_MASK_BITS); + GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count)); GEM_BUG_ON(i915->pmu.enable_count[bit] == 0); /* * Decrement the reference count and clear the enabled diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h index 7f164ca3db12..b3728c5f13e7 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h @@ -31,6 +31,8 @@ enum { ((1 << I915_PMU_SAMPLE_BITS) + \ (I915_PMU_LAST + 1 - __I915_PMU_OTHER(0))) +#define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1) + struct i915_pmu_sample { u64 cur; }; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0a7d60509ca7..067054cf4a86 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1790,7 +1790,7 @@ enum i915_power_well_id { #define _CNL_PORT_TX_C_LN0_OFFSET 0x162C40 #define _CNL_PORT_TX_D_LN0_OFFSET 0x162E40 #define _CNL_PORT_TX_F_LN0_OFFSET 0x162840 -#define _CNL_PORT_TX_DW_GRP(port, dw) (_PICK((port), \ +#define _CNL_PORT_TX_DW_GRP(dw, port) (_PICK((port), \ _CNL_PORT_TX_AE_GRP_OFFSET, \ _CNL_PORT_TX_B_GRP_OFFSET, \ _CNL_PORT_TX_B_GRP_OFFSET, \ @@ -1798,7 +1798,7 @@ enum i915_power_well_id { _CNL_PORT_TX_AE_GRP_OFFSET, \ _CNL_PORT_TX_F_GRP_OFFSET) + \ 4 * (dw)) -#define _CNL_PORT_TX_DW_LN0(port, dw) (_PICK((port), \ +#define _CNL_PORT_TX_DW_LN0(dw, port) (_PICK((port), \ _CNL_PORT_TX_AE_LN0_OFFSET, \ _CNL_PORT_TX_B_LN0_OFFSET, \ _CNL_PORT_TX_B_LN0_OFFSET, \ @@ -1834,9 +1834,9 @@ enum i915_power_well_id { #define _CNL_PORT_TX_DW4_LN0_AE 0x162450 #define _CNL_PORT_TX_DW4_LN1_AE 0x1624D0 -#define CNL_PORT_TX_DW4_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 4)) -#define CNL_PORT_TX_DW4_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 4)) -#define CNL_PORT_TX_DW4_LN(port, ln) _MMIO(_CNL_PORT_TX_DW_LN0((port), 4) + \ +#define CNL_PORT_TX_DW4_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP(4, (port))) +#define CNL_PORT_TX_DW4_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0(4, (port))) +#define CNL_PORT_TX_DW4_LN(port, ln) _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)) + \ ((ln) * (_CNL_PORT_TX_DW4_LN1_AE - \ _CNL_PORT_TX_DW4_LN0_AE))) #define ICL_PORT_TX_DW4_AUX(port) _MMIO(_ICL_PORT_TX_DW_AUX(4, port)) @@ -1864,8 +1864,12 @@ enum i915_power_well_id { #define RTERM_SELECT(x) ((x) << 3) #define RTERM_SELECT_MASK (0x7 << 3) -#define CNL_PORT_TX_DW7_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 7)) -#define CNL_PORT_TX_DW7_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 7)) +#define CNL_PORT_TX_DW7_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP(7, (port))) +#define CNL_PORT_TX_DW7_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0(7, (port))) +#define ICL_PORT_TX_DW7_AUX(port) _MMIO(_ICL_PORT_TX_DW_AUX(7, port)) +#define ICL_PORT_TX_DW7_GRP(port) _MMIO(_ICL_PORT_TX_DW_GRP(7, port)) +#define ICL_PORT_TX_DW7_LN0(port) _MMIO(_ICL_PORT_TX_DW_LN(7, 0, port)) +#define ICL_PORT_TX_DW7_LN(port, ln) _MMIO(_ICL_PORT_TX_DW_LN(7, ln, port)) #define N_SCALAR(x) ((x) << 24) #define N_SCALAR_MASK (0x7F << 24) diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 535caebd9813..c0cfe7ae2ba5 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -521,7 +521,9 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj, ssize_t ret; gpu = i915_first_error_state(i915); - if (gpu) { + if (IS_ERR(gpu)) { + ret = PTR_ERR(gpu); + } else if (gpu) { ret = i915_gpu_state_copy_to_buffer(gpu, buf, off, count); i915_gpu_state_put(gpu); } else { diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index f3e1d6a0b7dd..7edce1b7b348 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -494,103 +494,58 @@ static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_1_05V[] = { { 0x2, 0x7F, 0x3F, 0x00, 0x00 }, /* 400 400 0.0 */ }; -struct icl_combo_phy_ddi_buf_trans { - u32 dw2_swing_select; - u32 dw2_swing_scalar; - u32 dw4_scaling; -}; - -/* Voltage Swing Programming for VccIO 0.85V for DP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_85V[] = { - /* Voltage mV db */ - { 0x2, 0x98, 0x0018 }, /* 400 0.0 */ - { 0x2, 0x98, 0x3015 }, /* 400 3.5 */ - { 0x2, 0x98, 0x6012 }, /* 400 6.0 */ - { 0x2, 0x98, 0x900F }, /* 400 9.5 */ - { 0xB, 0x70, 0x0018 }, /* 600 0.0 */ - { 0xB, 0x70, 0x3015 }, /* 600 3.5 */ - { 0xB, 0x70, 0x6012 }, /* 600 6.0 */ - { 0x5, 0x00, 0x0018 }, /* 800 0.0 */ - { 0x5, 0x00, 0x3015 }, /* 800 3.5 */ - { 0x6, 0x98, 0x0018 }, /* 1200 0.0 */ -}; - -/* FIXME - After table is updated in Bspec */ -/* Voltage Swing Programming for VccIO 0.85V for eDP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_85V[] = { - /* Voltage mV db */ - { 0x0, 0x00, 0x00 }, /* 200 0.0 */ - { 0x0, 0x00, 0x00 }, /* 200 1.5 */ - { 0x0, 0x00, 0x00 }, /* 200 4.0 */ - { 0x0, 0x00, 0x00 }, /* 200 6.0 */ - { 0x0, 0x00, 0x00 }, /* 250 0.0 */ - { 0x0, 0x00, 0x00 }, /* 250 1.5 */ - { 0x0, 0x00, 0x00 }, /* 250 4.0 */ - { 0x0, 0x00, 0x00 }, /* 300 0.0 */ - { 0x0, 0x00, 0x00 }, /* 300 1.5 */ - { 0x0, 0x00, 0x00 }, /* 350 0.0 */ -}; - -/* Voltage Swing Programming for VccIO 0.95V for DP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_95V[] = { - /* Voltage mV db */ - { 0x2, 0x98, 0x0018 }, /* 400 0.0 */ - { 0x2, 0x98, 0x3015 }, /* 400 3.5 */ - { 0x2, 0x98, 0x6012 }, /* 400 6.0 */ - { 0x2, 0x98, 0x900F }, /* 400 9.5 */ - { 0x4, 0x98, 0x0018 }, /* 600 0.0 */ - { 0x4, 0x98, 0x3015 }, /* 600 3.5 */ - { 0x4, 0x98, 0x6012 }, /* 600 6.0 */ - { 0x5, 0x76, 0x0018 }, /* 800 0.0 */ - { 0x5, 0x76, 0x3015 }, /* 800 3.5 */ - { 0x6, 0x98, 0x0018 }, /* 1200 0.0 */ +/* icl_combo_phy_ddi_translations */ +static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hbr2[] = { + /* NT mV Trans mV db */ + { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */ + { 0xA, 0x4F, 0x37, 0x00, 0x08 }, /* 350 500 3.1 */ + { 0xC, 0x71, 0x2F, 0x00, 0x10 }, /* 350 700 6.0 */ + { 0x6, 0x7F, 0x2B, 0x00, 0x14 }, /* 350 900 8.2 */ + { 0xA, 0x4C, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */ + { 0xC, 0x73, 0x34, 0x00, 0x0B }, /* 500 700 2.9 */ + { 0x6, 0x7F, 0x2F, 0x00, 0x10 }, /* 500 900 5.1 */ + { 0xC, 0x6C, 0x3C, 0x00, 0x03 }, /* 650 700 0.6 */ + { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 900 3.5 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */ }; -/* FIXME - After table is updated in Bspec */ -/* Voltage Swing Programming for VccIO 0.95V for eDP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_95V[] = { - /* Voltage mV db */ - { 0x0, 0x00, 0x00 }, /* 200 0.0 */ - { 0x0, 0x00, 0x00 }, /* 200 1.5 */ - { 0x0, 0x00, 0x00 }, /* 200 4.0 */ - { 0x0, 0x00, 0x00 }, /* 200 6.0 */ - { 0x0, 0x00, 0x00 }, /* 250 0.0 */ - { 0x0, 0x00, 0x00 }, /* 250 1.5 */ - { 0x0, 0x00, 0x00 }, /* 250 4.0 */ - { 0x0, 0x00, 0x00 }, /* 300 0.0 */ - { 0x0, 0x00, 0x00 }, /* 300 1.5 */ - { 0x0, 0x00, 0x00 }, /* 350 0.0 */ +static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr2[] = { + /* NT mV Trans mV db */ + { 0x0, 0x7F, 0x3F, 0x00, 0x00 }, /* 200 200 0.0 */ + { 0x8, 0x7F, 0x38, 0x00, 0x07 }, /* 200 250 1.9 */ + { 0x1, 0x7F, 0x33, 0x00, 0x0C }, /* 200 300 3.5 */ + { 0x9, 0x7F, 0x31, 0x00, 0x0E }, /* 200 350 4.9 */ + { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 250 250 0.0 */ + { 0x1, 0x7F, 0x38, 0x00, 0x07 }, /* 250 300 1.6 */ + { 0x9, 0x7F, 0x35, 0x00, 0x0A }, /* 250 350 2.9 */ + { 0x1, 0x7F, 0x3F, 0x00, 0x00 }, /* 300 300 0.0 */ + { 0x9, 0x7F, 0x38, 0x00, 0x07 }, /* 300 350 1.3 */ + { 0x9, 0x7F, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */ }; -/* Voltage Swing Programming for VccIO 1.05V for DP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_1_05V[] = { - /* Voltage mV db */ - { 0x2, 0x98, 0x0018 }, /* 400 0.0 */ - { 0x2, 0x98, 0x3015 }, /* 400 3.5 */ - { 0x2, 0x98, 0x6012 }, /* 400 6.0 */ - { 0x2, 0x98, 0x900F }, /* 400 9.5 */ - { 0x4, 0x98, 0x0018 }, /* 600 0.0 */ - { 0x4, 0x98, 0x3015 }, /* 600 3.5 */ - { 0x4, 0x98, 0x6012 }, /* 600 6.0 */ - { 0x5, 0x71, 0x0018 }, /* 800 0.0 */ - { 0x5, 0x71, 0x3015 }, /* 800 3.5 */ - { 0x6, 0x98, 0x0018 }, /* 1200 0.0 */ +static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr3[] = { + /* NT mV Trans mV db */ + { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */ + { 0xA, 0x4F, 0x37, 0x00, 0x08 }, /* 350 500 3.1 */ + { 0xC, 0x71, 0x2F, 0x00, 0x10 }, /* 350 700 6.0 */ + { 0x6, 0x7F, 0x2B, 0x00, 0x14 }, /* 350 900 8.2 */ + { 0xA, 0x4C, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */ + { 0xC, 0x73, 0x34, 0x00, 0x0B }, /* 500 700 2.9 */ + { 0x6, 0x7F, 0x2F, 0x00, 0x10 }, /* 500 900 5.1 */ + { 0xC, 0x6C, 0x3C, 0x00, 0x03 }, /* 650 700 0.6 */ + { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 900 3.5 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */ }; -/* FIXME - After table is updated in Bspec */ -/* Voltage Swing Programming for VccIO 1.05V for eDP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_1_05V[] = { - /* Voltage mV db */ - { 0x0, 0x00, 0x00 }, /* 200 0.0 */ - { 0x0, 0x00, 0x00 }, /* 200 1.5 */ - { 0x0, 0x00, 0x00 }, /* 200 4.0 */ - { 0x0, 0x00, 0x00 }, /* 200 6.0 */ - { 0x0, 0x00, 0x00 }, /* 250 0.0 */ - { 0x0, 0x00, 0x00 }, /* 250 1.5 */ - { 0x0, 0x00, 0x00 }, /* 250 4.0 */ - { 0x0, 0x00, 0x00 }, /* 300 0.0 */ - { 0x0, 0x00, 0x00 }, /* 300 1.5 */ - { 0x0, 0x00, 0x00 }, /* 350 0.0 */ +static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_hdmi[] = { + /* NT mV Trans mV db */ + { 0xA, 0x60, 0x3F, 0x00, 0x00 }, /* 450 450 0.0 */ + { 0xB, 0x73, 0x36, 0x00, 0x09 }, /* 450 650 3.2 */ + { 0x6, 0x7F, 0x31, 0x00, 0x0E }, /* 450 850 5.5 */ + { 0xB, 0x73, 0x3F, 0x00, 0x00 }, /* 650 650 0.0 ALS */ + { 0x6, 0x7F, 0x37, 0x00, 0x08 }, /* 650 850 2.3 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 850 850 0.0 */ + { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 850 3.0 */ }; struct icl_mg_phy_ddi_buf_trans { @@ -871,43 +826,23 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) } } -static const struct icl_combo_phy_ddi_buf_trans * +static const struct cnl_ddi_buf_trans * icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, enum port port, - int type, int *n_entries) + int type, int rate, int *n_entries) { - u32 voltage = I915_READ(ICL_PORT_COMP_DW3(port)) & VOLTAGE_INFO_MASK; - - if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) { - switch (voltage) { - case VOLTAGE_INFO_0_85V: - *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_85V); - return icl_combo_phy_ddi_translations_edp_0_85V; - case VOLTAGE_INFO_0_95V: - *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_95V); - return icl_combo_phy_ddi_translations_edp_0_95V; - case VOLTAGE_INFO_1_05V: - *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_1_05V); - return icl_combo_phy_ddi_translations_edp_1_05V; - default: - MISSING_CASE(voltage); - return NULL; - } - } else { - switch (voltage) { - case VOLTAGE_INFO_0_85V: - *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_85V); - return icl_combo_phy_ddi_translations_dp_hdmi_0_85V; - case VOLTAGE_INFO_0_95V: - *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_95V); - return icl_combo_phy_ddi_translations_dp_hdmi_0_95V; - case VOLTAGE_INFO_1_05V: - *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V); - return icl_combo_phy_ddi_translations_dp_hdmi_1_05V; - default: - MISSING_CASE(voltage); - return NULL; - } + if (type == INTEL_OUTPUT_HDMI) { + *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi); + return icl_combo_phy_ddi_translations_hdmi; + } else if (rate > 540000 && type == INTEL_OUTPUT_EDP) { + *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr3); + return icl_combo_phy_ddi_translations_edp_hbr3; + } else if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) { + *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2); + return icl_combo_phy_ddi_translations_edp_hbr2; } + + *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hbr2); + return icl_combo_phy_ddi_translations_dp_hbr2; } static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port) @@ -918,8 +853,8 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por if (IS_ICELAKE(dev_priv)) { if (intel_port_is_combophy(dev_priv, port)) - icl_get_combo_buf_trans(dev_priv, port, - INTEL_OUTPUT_HDMI, &n_entries); + icl_get_combo_buf_trans(dev_priv, port, INTEL_OUTPUT_HDMI, + 0, &n_entries); else n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations); default_entry = n_entries - 1; @@ -1086,7 +1021,7 @@ static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder, return DDI_CLK_SEL_TBT_810; default: MISSING_CASE(clock); - break; + return DDI_CLK_SEL_NONE; } case DPLL_ID_ICL_MGPLL1: case DPLL_ID_ICL_MGPLL2: @@ -2275,13 +2210,14 @@ static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder, u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); enum port port = encoder->port; int n_entries; if (IS_ICELAKE(dev_priv)) { if (intel_port_is_combophy(dev_priv, port)) icl_get_combo_buf_trans(dev_priv, port, encoder->type, - &n_entries); + intel_dp->link_rate, &n_entries); else n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations); } else if (IS_CANNONLAKE(dev_priv)) { @@ -2462,14 +2398,15 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder, } static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv, - u32 level, enum port port, int type) + u32 level, enum port port, int type, + int rate) { - const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL; + const struct cnl_ddi_buf_trans *ddi_translations = NULL; u32 n_entries, val; int ln; ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type, - &n_entries); + rate, &n_entries); if (!ddi_translations) return; @@ -2478,34 +2415,23 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv, level = n_entries - 1; } - /* Set PORT_TX_DW5 Rterm Sel to 110b. */ + /* Set PORT_TX_DW5 */ val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); - val &= ~RTERM_SELECT_MASK; + val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK | + TAP2_DISABLE | TAP3_DISABLE); + val |= SCALING_MODE_SEL(0x2); val |= RTERM_SELECT(0x6); - I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val); - - /* Program PORT_TX_DW5 */ - val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); - /* Set DisableTap2 and DisableTap3 if MIPI DSI - * Clear DisableTap2 and DisableTap3 for all other Ports - */ - if (type == INTEL_OUTPUT_DSI) { - val |= TAP2_DISABLE; - val |= TAP3_DISABLE; - } else { - val &= ~TAP2_DISABLE; - val &= ~TAP3_DISABLE; - } + val |= TAP3_DISABLE; I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val); /* Program PORT_TX_DW2 */ val = I915_READ(ICL_PORT_TX_DW2_LN0(port)); val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK | RCOMP_SCALAR_MASK); - val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select); - val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select); + val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_sel); + val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_sel); /* Program Rcomp scalar for every table entry */ - val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar); + val |= RCOMP_SCALAR(0x98); I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val); /* Program PORT_TX_DW4 */ @@ -2514,9 +2440,17 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv, val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln)); val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK | CURSOR_COEFF_MASK); - val |= ddi_translations[level].dw4_scaling; + val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1); + val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2); + val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff); I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val); } + + /* Program PORT_TX_DW7 */ + val = I915_READ(ICL_PORT_TX_DW7_LN0(port)); + val &= ~N_SCALAR_MASK; + val |= N_SCALAR(ddi_translations[level].dw7_n_scalar); + I915_WRITE(ICL_PORT_TX_DW7_GRP(port), val); } static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder, @@ -2581,7 +2515,7 @@ static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder, I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val); /* 5. Program swing and de-emphasis */ - icl_ddi_combo_vswing_program(dev_priv, level, port, type); + icl_ddi_combo_vswing_program(dev_priv, level, port, type, rate); /* 6. Set training enable to trigger update */ val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3da9c0f9e948..248128126422 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15415,16 +15415,45 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, } } +static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + + /* + * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram + * the hardware when a high res displays plugged in. DPLL P + * divider is zero, and the pipe timings are bonkers. We'll + * try to disable everything in that case. + * + * FIXME would be nice to be able to sanitize this state + * without several WARNs, but for now let's take the easy + * road. + */ + return IS_GEN6(dev_priv) && + crtc_state->base.active && + crtc_state->shared_dpll && + crtc_state->port_clock == 0; +} + static void intel_sanitize_encoder(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_connector *connector; + struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); + struct intel_crtc_state *crtc_state = crtc ? + to_intel_crtc_state(crtc->base.state) : NULL; /* We need to check both for a crtc link (meaning that the * encoder is active and trying to read from a pipe) and the * pipe itself being active. */ - bool has_active_crtc = encoder->base.crtc && - to_intel_crtc(encoder->base.crtc)->active; + bool has_active_crtc = crtc_state && + crtc_state->base.active; + + if (crtc_state && has_bogus_dpll_config(crtc_state)) { + DRM_DEBUG_KMS("BIOS has misprogrammed the hardware. Disabling pipe %c\n", + pipe_name(crtc->pipe)); + has_active_crtc = false; + } connector = intel_encoder_find_connector(encoder); if (connector && !has_active_crtc) { @@ -15435,16 +15464,25 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) /* Connector is active, but has no active pipe. This is * fallout from our resume register restoring. Disable * the encoder manually again. */ - if (encoder->base.crtc) { - struct drm_crtc_state *crtc_state = encoder->base.crtc->state; + if (crtc_state) { + struct drm_encoder *best_encoder; DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n", encoder->base.base.id, encoder->base.name); + + /* avoid oopsing in case the hooks consult best_encoder */ + best_encoder = connector->base.state->best_encoder; + connector->base.state->best_encoder = &encoder->base; + if (encoder->disable) - encoder->disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state); + encoder->disable(encoder, crtc_state, + connector->base.state); if (encoder->post_disable) - encoder->post_disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state); + encoder->post_disable(encoder, crtc_state, + connector->base.state); + + connector->base.state->best_encoder = best_encoder; } encoder->base.crtc = NULL; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index fdd2cbc56fa3..22a74608c6e4 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -304,9 +304,11 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp) static int icl_max_source_rate(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); enum port port = dig_port->base.port; - if (port == PORT_B) + if (intel_port_is_combophy(dev_priv, port) && + !intel_dp_is_edp(intel_dp)) return 540000; return 810000; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f94a04b4ad87..e9ddeaf05a14 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -209,6 +209,16 @@ struct intel_fbdev { unsigned long vma_flags; async_cookie_t cookie; int preferred_bpp; + + /* Whether or not fbdev hpd processing is temporarily suspended */ + bool hpd_suspended : 1; + /* Set when a hotplug was received while HPD processing was + * suspended + */ + bool hpd_waiting : 1; + + /* Protects hpd_suspended */ + struct mutex hpd_lock; }; struct intel_encoder { diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index fb5bb5b32a60..4ee16b264dbe 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -336,8 +336,8 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, bool *enabled, int width, int height) { struct drm_i915_private *dev_priv = to_i915(fb_helper->dev); - unsigned long conn_configured, conn_seq, mask; unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG); + unsigned long conn_configured, conn_seq; int i, j; bool *save_enabled; bool fallback = true, ret = true; @@ -355,10 +355,9 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, drm_modeset_backoff(&ctx); memcpy(save_enabled, enabled, count); - mask = GENMASK(count - 1, 0); + conn_seq = GENMASK(count - 1, 0); conn_configured = 0; retry: - conn_seq = conn_configured; for (i = 0; i < count; i++) { struct drm_fb_helper_connector *fb_conn; struct drm_connector *connector; @@ -371,7 +370,8 @@ retry: if (conn_configured & BIT(i)) continue; - if (conn_seq == 0 && !connector->has_tile) + /* First pass, only consider tiled connectors */ + if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile) continue; if (connector->status == connector_status_connected) @@ -475,8 +475,10 @@ retry: conn_configured |= BIT(i); } - if ((conn_configured & mask) != mask && conn_configured != conn_seq) + if (conn_configured != conn_seq) { /* repeat until no more are found */ + conn_seq = conn_configured; goto retry; + } /* * If the BIOS didn't enable everything it could, fall back to have the @@ -679,6 +681,7 @@ int intel_fbdev_init(struct drm_device *dev) if (ifbdev == NULL) return -ENOMEM; + mutex_init(&ifbdev->hpd_lock); drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs); if (!intel_fbdev_init_bios(dev, ifbdev)) @@ -752,6 +755,26 @@ void intel_fbdev_fini(struct drm_i915_private *dev_priv) intel_fbdev_destroy(ifbdev); } +/* Suspends/resumes fbdev processing of incoming HPD events. When resuming HPD + * processing, fbdev will perform a full connector reprobe if a hotplug event + * was received while HPD was suspended. + */ +static void intel_fbdev_hpd_set_suspend(struct intel_fbdev *ifbdev, int state) +{ + bool send_hpd = false; + + mutex_lock(&ifbdev->hpd_lock); + ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED; + send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting; + ifbdev->hpd_waiting = false; + mutex_unlock(&ifbdev->hpd_lock); + + if (send_hpd) { + DRM_DEBUG_KMS("Handling delayed fbcon HPD event\n"); + drm_fb_helper_hotplug_event(&ifbdev->helper); + } +} + void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -773,6 +796,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous */ if (state != FBINFO_STATE_RUNNING) flush_work(&dev_priv->fbdev_suspend_work); + console_lock(); } else { /* @@ -800,17 +824,26 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous drm_fb_helper_set_suspend(&ifbdev->helper, state); console_unlock(); + + intel_fbdev_hpd_set_suspend(ifbdev, state); } void intel_fbdev_output_poll_changed(struct drm_device *dev) { struct intel_fbdev *ifbdev = to_i915(dev)->fbdev; + bool send_hpd; if (!ifbdev) return; intel_fbdev_sync(ifbdev); - if (ifbdev->vma || ifbdev->helper.deferred_setup) + + mutex_lock(&ifbdev->hpd_lock); + send_hpd = !ifbdev->hpd_suspended; + ifbdev->hpd_waiting = true; + mutex_unlock(&ifbdev->hpd_lock); + + if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup)) drm_fb_helper_hotplug_event(&ifbdev->helper); } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 4be167dcd209..eab9341a5152 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -303,6 +303,7 @@ static void __unwind_incomplete_requests(struct intel_engine_cs *engine) */ if (!(prio & I915_PRIORITY_NEWCLIENT)) { prio |= I915_PRIORITY_NEWCLIENT; + active->sched.attr.priority = prio; list_move_tail(&active->sched.link, i915_sched_lookup_priolist(engine, prio)); } @@ -645,6 +646,9 @@ static void execlists_dequeue(struct intel_engine_cs *engine) int i; priolist_for_each_request_consume(rq, rn, p, i) { + GEM_BUG_ON(last && + need_preempt(engine, last, rq_prio(rq))); + /* * Can we combine this request with the current port? * It has to be the same context/ringbuffer and not @@ -2244,6 +2248,8 @@ static int logical_ring_init(struct intel_engine_cs *engine) if (ret) return ret; + intel_engine_init_workarounds(engine); + if (HAS_LOGICAL_RING_ELSQ(i915)) { execlists->submit_reg = i915->regs + i915_mmio_reg_offset(RING_EXECLIST_SQ_CONTENTS(engine)); @@ -2310,7 +2316,6 @@ int logical_render_ring_init(struct intel_engine_cs *engine) } intel_engine_init_whitelist(engine); - intel_engine_init_workarounds(engine); return 0; } diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index b8f106d9ecf8..3ac20153705a 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -55,7 +55,12 @@ struct opregion_header { u8 signature[16]; u32 size; - u32 opregion_ver; + struct { + u8 rsvd; + u8 revision; + u8 minor; + u8 major; + } __packed over; u8 bios_ver[32]; u8 vbios_ver[16]; u8 driver_ver[16]; @@ -119,7 +124,8 @@ struct opregion_asle { u64 fdss; u32 fdsp; u32 stat; - u64 rvda; /* Physical address of raw vbt data */ + u64 rvda; /* Physical (2.0) or relative from opregion (2.1+) + * address of raw VBT data. */ u32 rvds; /* Size of raw vbt data */ u8 rsvd[58]; } __packed; @@ -925,6 +931,11 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) opregion->header = base; opregion->lid_state = base + ACPI_CLID; + DRM_DEBUG_DRIVER("ACPI OpRegion version %u.%u.%u\n", + opregion->header->over.major, + opregion->header->over.minor, + opregion->header->over.revision); + mboxes = opregion->header->mboxes; if (mboxes & MBOX_ACPI) { DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); @@ -953,11 +964,26 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) if (dmi_check_system(intel_no_opregion_vbt)) goto out; - if (opregion->header->opregion_ver >= 2 && opregion->asle && + if (opregion->header->over.major >= 2 && opregion->asle && opregion->asle->rvda && opregion->asle->rvds) { - opregion->rvda = memremap(opregion->asle->rvda, - opregion->asle->rvds, + resource_size_t rvda = opregion->asle->rvda; + + /* + * opregion 2.0: rvda is the physical VBT address. + * + * opregion 2.1+: rvda is unsigned, relative offset from + * opregion base, and should never point within opregion. + */ + if (opregion->header->over.major > 2 || + opregion->header->over.minor >= 1) { + WARN_ON(rvda < OPREGION_SIZE); + + rvda += asls; + } + + opregion->rvda = memremap(rvda, opregion->asle->rvds, MEMREMAP_WB); + vbt = opregion->rvda; vbt_size = opregion->asle->rvds; if (intel_bios_is_valid_vbt(vbt, vbt_size)) { @@ -967,6 +993,8 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) goto out; } else { DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n"); + memunmap(opregion->rvda); + opregion->rvda = NULL; } } diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 419e56342523..f71970df9936 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -274,10 +274,16 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) DRM_DEBUG_KMS("eDP panel supports PSR version %x\n", intel_dp->psr_dpcd[0]); + if (drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_PSR)) { + DRM_DEBUG_KMS("PSR support not currently available for this panel\n"); + return; + } + if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) { DRM_DEBUG_KMS("Panel lacks power state control, PSR cannot be enabled\n"); return; } + dev_priv->psr.sink_support = true; dev_priv->psr.sink_sync_latency = intel_dp_get_sink_sync_latency(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 72edaa7ff411..a1a7cc29fdd1 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -415,16 +415,17 @@ struct intel_engine_cs { /** * @enable_count: Reference count for the enabled samplers. * - * Index number corresponds to the bit number from @enable. + * Index number corresponds to @enum drm_i915_pmu_engine_sample. */ - unsigned int enable_count[I915_PMU_SAMPLE_BITS]; + unsigned int enable_count[I915_ENGINE_SAMPLE_COUNT]; /** * @sample: Counter values for sampling events. * * Our internal timer stores the current counters in this field. + * + * Index number corresponds to @enum drm_i915_pmu_engine_sample. */ -#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_SEMA + 1) - struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX]; + struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_COUNT]; } pmu; /* diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index d2e003d8f3db..5170a0f5fe7b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -494,7 +494,7 @@ skl_program_plane(struct intel_plane *plane, keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha); - keymsk = key->channel_mask & 0x3ffffff; + keymsk = key->channel_mask & 0x7ffffff; if (alpha < 0xff) keymsk |= PLANE_KEYMSK_ALPHA_ENABLE; diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 2c5bbe317353..e31e263cf86b 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -643,8 +643,10 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) int bus_format; ret = of_property_read_u32(child, "reg", &i); - if (ret || i < 0 || i > 1) - return -EINVAL; + if (ret || i < 0 || i > 1) { + ret = -EINVAL; + goto free_child; + } if (!of_device_is_available(child)) continue; @@ -657,7 +659,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) channel = &imx_ldb->channel[i]; channel->ldb = imx_ldb; channel->chno = i; - channel->child = child; /* * The output port is port@4 with an external 4-port mux or @@ -667,13 +668,13 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) imx_ldb->lvds_mux ? 4 : 2, 0, &channel->panel, &channel->bridge); if (ret && ret != -ENODEV) - return ret; + goto free_child; /* panel ddc only if there is no bridge */ if (!channel->bridge) { ret = imx_ldb_panel_ddc(dev, channel, child); if (ret) - return ret; + goto free_child; } bus_format = of_get_bus_format(dev, child); @@ -689,18 +690,26 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) if (bus_format < 0) { dev_err(dev, "could not determine data mapping: %d\n", bus_format); - return bus_format; + ret = bus_format; + goto free_child; } channel->bus_format = bus_format; + channel->child = child; ret = imx_ldb_register(drm, channel); - if (ret) - return ret; + if (ret) { + channel->child = NULL; + goto free_child; + } } dev_set_drvdata(dev, imx_ldb); return 0; + +free_child: + of_node_put(child); + return ret; } static void imx_ldb_unbind(struct device *dev, struct device *master, diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index c390924de93d..21e964f6ab5c 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -370,9 +370,9 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, if (ret) return ret; - /* CRTC should be enabled */ + /* nothing to check when disabling or disabled */ if (!crtc_state->enable) - return -EINVAL; + return 0; switch (plane->type) { case DRM_PLANE_TYPE_PRIMARY: diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c index 75d97f1b2e8f..4f5c67f70c4d 100644 --- a/drivers/gpu/drm/meson/meson_crtc.c +++ b/drivers/gpu/drm/meson/meson_crtc.c @@ -46,7 +46,6 @@ struct meson_crtc { struct drm_crtc base; struct drm_pending_vblank_event *event; struct meson_drm *priv; - bool enabled; }; #define to_meson_crtc(x) container_of(x, struct meson_crtc, base) @@ -82,7 +81,8 @@ static const struct drm_crtc_funcs meson_crtc_funcs = { }; -static void meson_crtc_enable(struct drm_crtc *crtc) +static void meson_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct meson_crtc *meson_crtc = to_meson_crtc(crtc); struct drm_crtc_state *crtc_state = crtc->state; @@ -108,20 +108,6 @@ static void meson_crtc_enable(struct drm_crtc *crtc) drm_crtc_vblank_on(crtc); - meson_crtc->enabled = true; -} - -static void meson_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) -{ - struct meson_crtc *meson_crtc = to_meson_crtc(crtc); - struct meson_drm *priv = meson_crtc->priv; - - DRM_DEBUG_DRIVER("\n"); - - if (!meson_crtc->enabled) - meson_crtc_enable(crtc); - priv->viu.osd1_enabled = true; } @@ -153,8 +139,6 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc, crtc->state->event = NULL; } - - meson_crtc->enabled = false; } static void meson_crtc_atomic_begin(struct drm_crtc *crtc, @@ -163,9 +147,6 @@ static void meson_crtc_atomic_begin(struct drm_crtc *crtc, struct meson_crtc *meson_crtc = to_meson_crtc(crtc); unsigned long flags; - if (crtc->state->enable && !meson_crtc->enabled) - meson_crtc_enable(crtc); - if (crtc->state->event) { WARN_ON(drm_crtc_vblank_get(crtc) != 0); diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 3ee4d4a4ecba..12ff47b13668 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -75,6 +75,10 @@ static const struct drm_mode_config_funcs meson_mode_config_funcs = { .fb_create = drm_gem_fb_create, }; +static const struct drm_mode_config_helper_funcs meson_mode_config_helpers = { + .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, +}; + static irqreturn_t meson_irq(int irq, void *arg) { struct drm_device *dev = arg; @@ -266,6 +270,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components) drm->mode_config.max_width = 3840; drm->mode_config.max_height = 2160; drm->mode_config.funcs = &meson_mode_config_funcs; + drm->mode_config.helper_private = &meson_mode_config_helpers; /* Hardware Initialization */ @@ -388,8 +393,10 @@ static int meson_probe_remote(struct platform_device *pdev, remote_node = of_graph_get_remote_port_parent(ep); if (!remote_node || remote_node == parent || /* Ignore parent endpoint */ - !of_device_is_available(remote_node)) + !of_device_is_available(remote_node)) { + of_node_put(remote_node); continue; + } count += meson_probe_remote(pdev, match, remote, remote_node); @@ -408,10 +415,13 @@ static int meson_drv_probe(struct platform_device *pdev) for_each_endpoint_of_node(np, ep) { remote = of_graph_get_remote_port_parent(ep); - if (!remote || !of_device_is_available(remote)) + if (!remote || !of_device_is_available(remote)) { + of_node_put(remote); continue; + } count += meson_probe_remote(pdev, &match, np, remote); + of_node_put(remote); } if (count && !match) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 5beb83d1cf87..ce1b3cc4bf6d 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -944,7 +944,7 @@ static u32 a6xx_gmu_get_arc_level(struct device *dev, unsigned long freq) np = dev_pm_opp_get_of_node(opp); if (np) { - of_property_read_u32(np, "qcom,level", &val); + of_property_read_u32(np, "opp-level", &val); of_node_put(np); } diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 2e4372ef17a3..2cfee1a4fe0b 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -765,7 +765,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, adreno_gpu->rev = config->rev; adreno_gpu_config.ioname = "kgsl_3d0_reg_memory"; - adreno_gpu_config.irqname = "kgsl_3d0_irq"; adreno_gpu_config.va_start = SZ_16M; adreno_gpu_config.va_end = 0xffffffff; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index fd75870eb17f..6aefcd6db46b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -365,19 +365,6 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane, &pdpu->pipe_qos_cfg); } -static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) -{ - struct dpu_plane *pdpu = to_dpu_plane(plane); - struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); - - if (!pdpu->is_rt_pipe) - return; - - pm_runtime_get_sync(&dpu_kms->pdev->dev); - _dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL); - pm_runtime_put_sync(&dpu_kms->pdev->dev); -} - /** * _dpu_plane_set_ot_limit - set OT limit for the given plane * @plane: Pointer to drm plane @@ -1248,6 +1235,19 @@ static void dpu_plane_reset(struct drm_plane *plane) } #ifdef CONFIG_DEBUG_FS +static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) +{ + struct dpu_plane *pdpu = to_dpu_plane(plane); + struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); + + if (!pdpu->is_rt_pipe) + return; + + pm_runtime_get_sync(&dpu_kms->pdev->dev); + _dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL); + pm_runtime_put_sync(&dpu_kms->pdev->dev); +} + static ssize_t _dpu_plane_danger_read(struct file *file, char __user *buff, size_t count, loff_t *ppos) { diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 9cd6a96c6bf2..927e5d86f7c1 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -250,7 +250,8 @@ void msm_gem_purge_vma(struct msm_gem_address_space *aspace, void msm_gem_unmap_vma(struct msm_gem_address_space *aspace, struct msm_gem_vma *vma); int msm_gem_map_vma(struct msm_gem_address_space *aspace, - struct msm_gem_vma *vma, struct sg_table *sgt, int npages); + struct msm_gem_vma *vma, int prot, + struct sg_table *sgt, int npages); void msm_gem_close_vma(struct msm_gem_address_space *aspace, struct msm_gem_vma *vma); @@ -333,6 +334,7 @@ void msm_gem_kernel_put(struct drm_gem_object *bo, struct drm_gem_object *msm_gem_import(struct drm_device *dev, struct dma_buf *dmabuf, struct sg_table *sgt); +__printf(2, 3) void msm_gem_object_set_name(struct drm_gem_object *bo, const char *fmt, ...); int msm_framebuffer_prepare(struct drm_framebuffer *fb, @@ -396,12 +398,14 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m); int msm_debugfs_late_init(struct drm_device *dev); int msm_rd_debugfs_init(struct drm_minor *minor); void msm_rd_debugfs_cleanup(struct msm_drm_private *priv); +__printf(3, 4) void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit, const char *fmt, ...); int msm_perf_debugfs_init(struct drm_minor *minor); void msm_perf_debugfs_cleanup(struct msm_drm_private *priv); #else static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; } +__printf(3, 4) static inline void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit, const char *fmt, ...) {} static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {} diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 51a95da694d8..c8886d3071fa 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -391,6 +391,10 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj, struct msm_gem_object *msm_obj = to_msm_bo(obj); struct msm_gem_vma *vma; struct page **pages; + int prot = IOMMU_READ; + + if (!(msm_obj->flags & MSM_BO_GPU_READONLY)) + prot |= IOMMU_WRITE; WARN_ON(!mutex_is_locked(&msm_obj->lock)); @@ -405,8 +409,8 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj, if (IS_ERR(pages)) return PTR_ERR(pages); - return msm_gem_map_vma(aspace, vma, msm_obj->sgt, - obj->size >> PAGE_SHIFT); + return msm_gem_map_vma(aspace, vma, prot, + msm_obj->sgt, obj->size >> PAGE_SHIFT); } /* get iova and pin it. Should have a matching put */ diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 557360788084..49c04829cf34 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -68,7 +68,8 @@ void msm_gem_unmap_vma(struct msm_gem_address_space *aspace, int msm_gem_map_vma(struct msm_gem_address_space *aspace, - struct msm_gem_vma *vma, struct sg_table *sgt, int npages) + struct msm_gem_vma *vma, int prot, + struct sg_table *sgt, int npages) { unsigned size = npages << PAGE_SHIFT; int ret = 0; @@ -86,7 +87,7 @@ msm_gem_map_vma(struct msm_gem_address_space *aspace, if (aspace->mmu) ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt, - size, IOMMU_READ | IOMMU_WRITE); + size, prot); if (ret) vma->mapped = false; diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 5f3eff304355..10babd18e286 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -900,7 +900,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, } /* Get Interrupt: */ - gpu->irq = platform_get_irq_byname(pdev, config->irqname); + gpu->irq = platform_get_irq(pdev, 0); if (gpu->irq < 0) { ret = gpu->irq; DRM_DEV_ERROR(drm->dev, "failed to get irq: %d\n", ret); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index efb49bb64191..ca17086f72c9 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -31,7 +31,6 @@ struct msm_gpu_state; struct msm_gpu_config { const char *ioname; - const char *irqname; uint64_t va_start; uint64_t va_end; unsigned int nr_rings; @@ -63,7 +62,7 @@ struct msm_gpu_funcs { struct msm_ringbuffer *(*active_ring)(struct msm_gpu *gpu); void (*recover)(struct msm_gpu *gpu); void (*destroy)(struct msm_gpu *gpu); -#ifdef CONFIG_DEBUG_FS +#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) /* show GPU status in debugfs: */ void (*show)(struct msm_gpu *gpu, struct msm_gpu_state *state, struct drm_printer *p); diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c index 90e9d0a48dc0..d21172933d92 100644 --- a/drivers/gpu/drm/msm/msm_rd.c +++ b/drivers/gpu/drm/msm/msm_rd.c @@ -115,7 +115,9 @@ static void rd_write(struct msm_rd_state *rd, const void *buf, int sz) char *fptr = &fifo->buf[fifo->head]; int n; - wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0); + wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0 || !rd->open); + if (!rd->open) + return; /* Note that smp_load_acquire() is not strictly required * as CIRC_SPACE_TO_END() does not access the tail more @@ -213,7 +215,10 @@ out: static int rd_release(struct inode *inode, struct file *file) { struct msm_rd_state *rd = inode->i_private; + rd->open = false; + wake_up_all(&rd->fifo_event); + return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 5f5be6368aed..c7a94c94dbf3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -253,6 +253,9 @@ nouveau_backlight_init(struct drm_connector *connector) case NV_DEVICE_INFO_V0_FERMI: case NV_DEVICE_INFO_V0_KEPLER: case NV_DEVICE_INFO_V0_MAXWELL: + case NV_DEVICE_INFO_V0_PASCAL: + case NV_DEVICE_INFO_V0_VOLTA: + case NV_DEVICE_INFO_V0_TURING: ret = nv50_backlight_init(nv_encoder, &props, &ops); break; default: diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index bfbc9341e0c2..d9edb5785813 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2435,6 +2435,38 @@ nv140_chipset = { }; static const struct nvkm_device_chip +nv162_chipset = { + .name = "TU102", + .bar = tu104_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .devinit = tu104_devinit_new, + .fault = tu104_fault_new, + .fb = gv100_fb_new, + .fuse = gm107_fuse_new, + .gpio = gk104_gpio_new, + .i2c = gm200_i2c_new, + .ibus = gm200_ibus_new, + .imem = nv50_instmem_new, + .ltc = gp102_ltc_new, + .mc = tu104_mc_new, + .mmu = tu104_mmu_new, + .pci = gp100_pci_new, + .pmu = gp102_pmu_new, + .therm = gp100_therm_new, + .timer = gk20a_timer_new, + .top = gk104_top_new, + .ce[0] = tu104_ce_new, + .ce[1] = tu104_ce_new, + .ce[2] = tu104_ce_new, + .ce[3] = tu104_ce_new, + .ce[4] = tu104_ce_new, + .disp = tu104_disp_new, + .dma = gv100_dma_new, + .fifo = tu104_fifo_new, +}; + +static const struct nvkm_device_chip nv164_chipset = { .name = "TU104", .bar = tu104_bar_new, @@ -2950,6 +2982,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, case 0x138: device->chip = &nv138_chipset; break; case 0x13b: device->chip = &nv13b_chipset; break; case 0x140: device->chip = &nv140_chipset; break; + case 0x162: device->chip = &nv162_chipset; break; case 0x164: device->chip = &nv164_chipset; break; case 0x166: device->chip = &nv166_chipset; break; default: diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c index 816ccaedfc73..8675613e142b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c @@ -22,6 +22,7 @@ #include <engine/falcon.h> #include <core/gpuobj.h> +#include <subdev/mc.h> #include <subdev/timer.h> #include <engine/fifo.h> @@ -107,8 +108,10 @@ nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend) } } - nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000); - nvkm_wr32(device, base + 0x014, 0xffffffff); + if (nvkm_mc_enabled(device, engine->subdev.index)) { + nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000); + nvkm_wr32(device, base + 0x014, 0xffffffff); + } return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index 3695cde669f8..07914e36939e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c @@ -132,11 +132,12 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode) duty = nvkm_therm_update_linear(therm); break; case NVBIOS_THERM_FAN_OTHER: - if (therm->cstate) + if (therm->cstate) { duty = therm->cstate; - else + poll = false; + } else { duty = nvkm_therm_update_linear_fallback(therm); - poll = false; + } break; } immd = false; diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 00a9c2ab9e6c..64fb788b6647 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -1406,7 +1406,7 @@ static void dsi_pll_disable(struct dss_pll *pll) static int dsi_dump_dsi_clocks(struct seq_file *s, void *p) { - struct dsi_data *dsi = p; + struct dsi_data *dsi = s->private; struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo; enum dss_clk_source dispc_clk_src, dsi_clk_src; int dsi_module = dsi->module_id; @@ -1467,7 +1467,7 @@ static int dsi_dump_dsi_clocks(struct seq_file *s, void *p) #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS static int dsi_dump_dsi_irqs(struct seq_file *s, void *p) { - struct dsi_data *dsi = p; + struct dsi_data *dsi = s->private; unsigned long flags; struct dsi_irq_stats stats; @@ -1558,7 +1558,7 @@ static int dsi_dump_dsi_irqs(struct seq_file *s, void *p) static int dsi_dump_dsi_regs(struct seq_file *s, void *p) { - struct dsi_data *dsi = p; + struct dsi_data *dsi = s->private; if (dsi_runtime_get(dsi)) return 0; @@ -4751,6 +4751,17 @@ static int dsi_set_config(struct omap_dss_device *dssdev, dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH; dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH; + /* + * HACK: These flags should be handled through the omap_dss_device bus + * flags, but this will only be possible when the DSI encoder will be + * converted to the omapdrm-managed encoder model. + */ + dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE; + dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; + dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW; + dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH; + dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE; + dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; dss_mgr_set_timings(&dsi->output, &dsi->vm); @@ -5083,15 +5094,15 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) snprintf(name, sizeof(name), "dsi%u_regs", dsi->module_id + 1); dsi->debugfs.regs = dss_debugfs_create_file(dss, name, - dsi_dump_dsi_regs, &dsi); + dsi_dump_dsi_regs, dsi); #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS snprintf(name, sizeof(name), "dsi%u_irqs", dsi->module_id + 1); dsi->debugfs.irqs = dss_debugfs_create_file(dss, name, - dsi_dump_dsi_irqs, &dsi); + dsi_dump_dsi_irqs, dsi); #endif snprintf(name, sizeof(name), "dsi%u_clks", dsi->module_id + 1); dsi->debugfs.clks = dss_debugfs_create_file(dss, name, - dsi_dump_dsi_clocks, &dsi); + dsi_dump_dsi_clocks, dsi); return 0; } @@ -5104,8 +5115,6 @@ static void dsi_unbind(struct device *dev, struct device *master, void *data) dss_debugfs_remove_file(dsi->debugfs.irqs); dss_debugfs_remove_file(dsi->debugfs.regs); - of_platform_depopulate(dev); - WARN_ON(dsi->scp_clk_refcount > 0); dss_pll_unregister(&dsi->pll); @@ -5457,6 +5466,8 @@ static int dsi_remove(struct platform_device *pdev) dsi_uninit_output(dsi); + of_platform_depopulate(&pdev->dev); + pm_runtime_disable(&pdev->dev); if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) { diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index 13c8a662f9b4..ccb090f3ab30 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -250,14 +250,10 @@ static struct drm_driver qxl_driver = { #if defined(CONFIG_DEBUG_FS) .debugfs_init = qxl_debugfs_init, #endif - .prime_handle_to_fd = drm_gem_prime_handle_to_fd, - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = drm_gem_prime_export, .gem_prime_import = drm_gem_prime_import, .gem_prime_pin = qxl_gem_prime_pin, .gem_prime_unpin = qxl_gem_prime_unpin, - .gem_prime_get_sg_table = qxl_gem_prime_get_sg_table, - .gem_prime_import_sg_table = qxl_gem_prime_import_sg_table, .gem_prime_vmap = qxl_gem_prime_vmap, .gem_prime_vunmap = qxl_gem_prime_vunmap, .gem_prime_mmap = qxl_gem_prime_mmap, diff --git a/drivers/gpu/drm/qxl/qxl_prime.c b/drivers/gpu/drm/qxl/qxl_prime.c index a55dece118b2..df65d3c1a7b8 100644 --- a/drivers/gpu/drm/qxl/qxl_prime.c +++ b/drivers/gpu/drm/qxl/qxl_prime.c @@ -38,20 +38,6 @@ void qxl_gem_prime_unpin(struct drm_gem_object *obj) WARN_ONCE(1, "not implemented"); } -struct sg_table *qxl_gem_prime_get_sg_table(struct drm_gem_object *obj) -{ - WARN_ONCE(1, "not implemented"); - return ERR_PTR(-ENOSYS); -} - -struct drm_gem_object *qxl_gem_prime_import_sg_table( - struct drm_device *dev, struct dma_buf_attachment *attach, - struct sg_table *table) -{ - WARN_ONCE(1, "not implemented"); - return ERR_PTR(-ENOSYS); -} - void *qxl_gem_prime_vmap(struct drm_gem_object *obj) { WARN_ONCE(1, "not implemented"); diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index d587779a80b4..a97294ac96d5 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -5676,7 +5676,7 @@ int ci_dpm_init(struct radeon_device *rdev) u16 data_offset, size; u8 frev, crev; struct ci_power_info *pi; - enum pci_bus_speed speed_cap; + enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN; struct pci_dev *root = rdev->pdev->bus->self; int ret; @@ -5685,7 +5685,8 @@ int ci_dpm_init(struct radeon_device *rdev) return -ENOMEM; rdev->pm.dpm.priv = pi; - speed_cap = pcie_get_speed_cap(root); + if (!pci_is_root_bus(rdev->pdev->bus)) + speed_cap = pcie_get_speed_cap(root); if (speed_cap == PCI_SPEED_UNKNOWN) { pi->sys_pcie_mask = 0; } else { diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index dec1e081f529..6a8fb6fd183c 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -172,6 +172,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) } if (radeon_is_px(dev)) { + dev_pm_set_driver_flags(dev->dev, DPM_FLAG_NEVER_SKIP); pm_runtime_use_autosuspend(dev->dev); pm_runtime_set_autosuspend_delay(dev->dev, 5000); pm_runtime_set_active(dev->dev); diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 8fb60b3af015..0a785ef0ab66 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -6899,7 +6899,7 @@ int si_dpm_init(struct radeon_device *rdev) struct ni_power_info *ni_pi; struct si_power_info *si_pi; struct atom_clock_dividers dividers; - enum pci_bus_speed speed_cap; + enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN; struct pci_dev *root = rdev->pdev->bus->self; int ret; @@ -6911,7 +6911,8 @@ int si_dpm_init(struct radeon_device *rdev) eg_pi = &ni_pi->eg; pi = &eg_pi->rv7xx; - speed_cap = pcie_get_speed_cap(root); + if (!pci_is_root_bus(rdev->pdev->bus)) + speed_cap = pcie_get_speed_cap(root); if (speed_cap == PCI_SPEED_UNKNOWN) { si_pi->sys_pcie_mask = 0; } else { diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c index 96ac1458a59c..c0351abf83a3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c @@ -1,17 +1,8 @@ -//SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd * Author: * Sandy Huang <hjc@rock-chips.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <drm/drmP.h> @@ -113,8 +104,10 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, child_count++; ret = drm_of_find_panel_or_bridge(dev->of_node, 0, endpoint_id, &panel, &bridge); - if (!ret) + if (!ret) { + of_node_put(endpoint); break; + } } of_node_put(port); diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.h b/drivers/gpu/drm/rockchip/rockchip_rgb.h index 38b52e63b2b0..27b9635124bc 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.h +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.h @@ -1,17 +1,8 @@ -//SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd * Author: * Sandy Huang <hjc@rock-chips.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #ifdef CONFIG_ROCKCHIP_RGB diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index 4463d3826ecb..e2942c9a11a7 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -440,13 +440,10 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity) while ((entity->dependency = sched->ops->dependency(sched_job, entity))) { + trace_drm_sched_job_wait_dep(sched_job, entity->dependency); - if (drm_sched_entity_add_dependency_cb(entity)) { - - trace_drm_sched_job_wait_dep(sched_job, - entity->dependency); + if (drm_sched_entity_add_dependency_cb(entity)) return NULL; - } } /* skip jobs from entity that marked guilty */ diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 9e9255ee59cd..a021bab11a4f 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -786,17 +786,18 @@ static struct sun4i_frontend *sun4i_backend_find_frontend(struct sun4i_drv *drv, remote = of_graph_get_remote_port_parent(ep); if (!remote) continue; + of_node_put(remote); /* does this node match any registered engines? */ list_for_each_entry(frontend, &drv->frontend_list, list) { if (remote == frontend->node) { - of_node_put(remote); of_node_put(port); + of_node_put(ep); return frontend; } } } - + of_node_put(port); return ERR_PTR(-EINVAL); } diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c index 061d2e0d9011..416da5376701 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c @@ -92,6 +92,8 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder) val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG); val &= ~SUN4I_HDMI_VID_CTRL_ENABLE; writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG); + + clk_disable_unprepare(hdmi->tmds_clk); } static void sun4i_hdmi_enable(struct drm_encoder *encoder) @@ -102,6 +104,8 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder) DRM_DEBUG_DRIVER("Enabling the HDMI Output\n"); + clk_prepare_enable(hdmi->tmds_clk); + sun4i_hdmi_setup_avi_infoframes(hdmi, mode); val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI); val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END); diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 0420f5c978b9..cf45d0f940f9 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -761,6 +761,7 @@ static int sun4i_tcon_init_clocks(struct device *dev, return PTR_ERR(tcon->sclk0); } } + clk_prepare_enable(tcon->sclk0); if (tcon->quirks->has_channel_1) { tcon->sclk1 = devm_clk_get(dev, "tcon-ch1"); @@ -775,6 +776,7 @@ static int sun4i_tcon_init_clocks(struct device *dev, static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon) { + clk_disable_unprepare(tcon->sclk0); clk_disable_unprepare(tcon->clk); } diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index f7f32a885af7..2d1aaca49105 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -127,14 +127,10 @@ static struct drm_driver driver = { #if defined(CONFIG_DEBUG_FS) .debugfs_init = virtio_gpu_debugfs_init, #endif - .prime_handle_to_fd = drm_gem_prime_handle_to_fd, - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = drm_gem_prime_export, .gem_prime_import = drm_gem_prime_import, .gem_prime_pin = virtgpu_gem_prime_pin, .gem_prime_unpin = virtgpu_gem_prime_unpin, - .gem_prime_get_sg_table = virtgpu_gem_prime_get_sg_table, - .gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table, .gem_prime_vmap = virtgpu_gem_prime_vmap, .gem_prime_vunmap = virtgpu_gem_prime_vunmap, .gem_prime_mmap = virtgpu_gem_prime_mmap, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 1deb41d42ea4..0c15000f926e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -372,10 +372,6 @@ int virtio_gpu_object_wait(struct virtio_gpu_object *bo, bool no_wait); /* virtgpu_prime.c */ int virtgpu_gem_prime_pin(struct drm_gem_object *obj); void virtgpu_gem_prime_unpin(struct drm_gem_object *obj); -struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj); -struct drm_gem_object *virtgpu_gem_prime_import_sg_table( - struct drm_device *dev, struct dma_buf_attachment *attach, - struct sg_table *sgt); void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj); void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); int virtgpu_gem_prime_mmap(struct drm_gem_object *obj, diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c index 86ce0ae93f59..c59ec34c80a5 100644 --- a/drivers/gpu/drm/virtio/virtgpu_prime.c +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c @@ -39,20 +39,6 @@ void virtgpu_gem_prime_unpin(struct drm_gem_object *obj) WARN_ONCE(1, "not implemented"); } -struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj) -{ - WARN_ONCE(1, "not implemented"); - return ERR_PTR(-ENODEV); -} - -struct drm_gem_object *virtgpu_gem_prime_import_sg_table( - struct drm_device *dev, struct dma_buf_attachment *attach, - struct sg_table *table) -{ - WARN_ONCE(1, "not implemented"); - return ERR_PTR(-ENODEV); -} - void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj) { struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); diff --git a/drivers/gpu/drm/vkms/vkms_crc.c b/drivers/gpu/drm/vkms/vkms_crc.c index 9d9e8146db90..d7b409a3c0f8 100644 --- a/drivers/gpu/drm/vkms/vkms_crc.c +++ b/drivers/gpu/drm/vkms/vkms_crc.c @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0+ + #include "vkms_drv.h" #include <linux/crc32.h> #include <drm/drm_atomic.h> diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 177bbcb38306..eb56ee893761 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -1,10 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+ #include "vkms_drv.h" #include <drm/drm_atomic_helper.h> diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 83087877565c..7dcbecb5fac2 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -1,9 +1,4 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+ /** * DOC: vkms (Virtual Kernel Modesetting) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index e4469cd3d254..81f1cfbeb936 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + #ifndef _VKMS_DRV_H_ #define _VKMS_DRV_H_ diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c index 80311daed47a..138b0bb325cf 100644 --- a/drivers/gpu/drm/vkms/vkms_gem.c +++ b/drivers/gpu/drm/vkms/vkms_gem.c @@ -1,10 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+ #include <linux/shmem_fs.h> diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index 271a0eb9042c..4173e4f48334 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -1,10 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+ #include "vkms_drv.h" #include <drm/drm_crtc_helper.h> diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 418817600ad1..0e67d2d42f0c 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -1,10 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+ #include "vkms_drv.h" #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 25afb1d594e3..7ef5dcb06104 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -26,6 +26,7 @@ **************************************************************************/ #include <linux/module.h> #include <linux/console.h> +#include <linux/dma-mapping.h> #include <drm/drmP.h> #include "vmwgfx_drv.h" @@ -34,7 +35,6 @@ #include <drm/ttm/ttm_placement.h> #include <drm/ttm/ttm_bo_driver.h> #include <drm/ttm/ttm_module.h> -#include <linux/intel-iommu.h> #define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices" #define VMWGFX_CHIP_SVGAII 0 @@ -546,6 +546,21 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv) } /** + * vmw_assume_iommu - Figure out whether coherent dma-remapping might be + * taking place. + * @dev: Pointer to the struct drm_device. + * + * Return: true if iommu present, false otherwise. + */ +static bool vmw_assume_iommu(struct drm_device *dev) +{ + const struct dma_map_ops *ops = get_dma_ops(dev->dev); + + return !dma_is_direct(ops) && ops && + ops->map_page != dma_direct_map_page; +} + +/** * vmw_dma_select_mode - Determine how DMA mappings should be set up for this * system. * @@ -565,55 +580,27 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv) [vmw_dma_alloc_coherent] = "Using coherent TTM pages.", [vmw_dma_map_populate] = "Keeping DMA mappings.", [vmw_dma_map_bind] = "Giving up DMA mappings early."}; -#ifdef CONFIG_X86 - const struct dma_map_ops *dma_ops = get_dma_ops(dev_priv->dev->dev); -#ifdef CONFIG_INTEL_IOMMU - if (intel_iommu_enabled) { + if (vmw_force_coherent) + dev_priv->map_mode = vmw_dma_alloc_coherent; + else if (vmw_assume_iommu(dev_priv->dev)) dev_priv->map_mode = vmw_dma_map_populate; - goto out_fixup; - } -#endif - - if (!(vmw_force_iommu || vmw_force_coherent)) { + else if (!vmw_force_iommu) dev_priv->map_mode = vmw_dma_phys; - DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]); - return 0; - } - - dev_priv->map_mode = vmw_dma_map_populate; - - if (dma_ops && dma_ops->sync_single_for_cpu) + else if (IS_ENABLED(CONFIG_SWIOTLB) && swiotlb_nr_tbl()) dev_priv->map_mode = vmw_dma_alloc_coherent; -#ifdef CONFIG_SWIOTLB - if (swiotlb_nr_tbl() == 0) + else dev_priv->map_mode = vmw_dma_map_populate; -#endif -#ifdef CONFIG_INTEL_IOMMU -out_fixup: -#endif - if (dev_priv->map_mode == vmw_dma_map_populate && - vmw_restrict_iommu) + if (dev_priv->map_mode == vmw_dma_map_populate && vmw_restrict_iommu) dev_priv->map_mode = vmw_dma_map_bind; - if (vmw_force_coherent) - dev_priv->map_mode = vmw_dma_alloc_coherent; - -#if !defined(CONFIG_SWIOTLB) && !defined(CONFIG_INTEL_IOMMU) - /* - * No coherent page pool - */ - if (dev_priv->map_mode == vmw_dma_alloc_coherent) + /* No TTM coherent page pool? FIXME: Ask TTM instead! */ + if (!(IS_ENABLED(CONFIG_SWIOTLB) || IS_ENABLED(CONFIG_INTEL_IOMMU)) && + (dev_priv->map_mode == vmw_dma_alloc_coherent)) return -EINVAL; -#endif - -#else /* CONFIG_X86 */ - dev_priv->map_mode = vmw_dma_map_populate; -#endif /* CONFIG_X86 */ DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]); - return 0; } @@ -625,24 +612,20 @@ out_fixup: * With 32-bit we can only handle 32 bit PFNs. Optionally set that * restriction also for 64-bit systems. */ -#ifdef CONFIG_INTEL_IOMMU static int vmw_dma_masks(struct vmw_private *dev_priv) { struct drm_device *dev = dev_priv->dev; + int ret = 0; - if (intel_iommu_enabled && + ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64)); + if (dev_priv->map_mode != vmw_dma_phys && (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) { DRM_INFO("Restricting DMA addresses to 44 bits.\n"); - return dma_set_mask(dev->dev, DMA_BIT_MASK(44)); + return dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(44)); } - return 0; -} -#else -static int vmw_dma_masks(struct vmw_private *dev_priv) -{ - return 0; + + return ret; } -#endif static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index f2d13a72c05d..88b8178d4687 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -3570,7 +3570,7 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv, *p_fence = NULL; } - return 0; + return ret; } /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index b351fb5214d3..ed2f67822f45 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1646,7 +1646,7 @@ static int vmw_kms_check_topology(struct drm_device *dev, struct drm_connector_state *conn_state; struct vmw_connector_state *vmw_conn_state; - if (!du->pref_active) { + if (!du->pref_active && new_crtc_state->enable) { ret = -EINVAL; goto clean; } @@ -2554,8 +2554,8 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv, user_fence_rep) { struct vmw_fence_obj *fence = NULL; - uint32_t handle; - int ret; + uint32_t handle = 0; + int ret = 0; if (file_priv || user_fence_rep || vmw_validation_has_bos(ctx) || out_fence) diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index 474b00e19697..0a7d4395d427 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -898,8 +898,8 @@ static struct ipu_devtype ipu_type_imx51 = { .cpmem_ofs = 0x1f000000, .srm_ofs = 0x1f040000, .tpm_ofs = 0x1f060000, - .csi0_ofs = 0x1f030000, - .csi1_ofs = 0x1f038000, + .csi0_ofs = 0x1e030000, + .csi1_ofs = 0x1e038000, .ic_ofs = 0x1e020000, .disp0_ofs = 0x1e040000, .disp1_ofs = 0x1e048000, @@ -914,8 +914,8 @@ static struct ipu_devtype ipu_type_imx53 = { .cpmem_ofs = 0x07000000, .srm_ofs = 0x07040000, .tpm_ofs = 0x07060000, - .csi0_ofs = 0x07030000, - .csi1_ofs = 0x07038000, + .csi0_ofs = 0x06030000, + .csi1_ofs = 0x06038000, .ic_ofs = 0x06020000, .disp0_ofs = 0x06040000, .disp1_ofs = 0x06048000, diff --git a/drivers/gpu/ipu-v3/ipu-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c index 2f8db9d62551..4a28f3fbb0a2 100644 --- a/drivers/gpu/ipu-v3/ipu-pre.c +++ b/drivers/gpu/ipu-v3/ipu-pre.c @@ -106,6 +106,7 @@ struct ipu_pre { void *buffer_virt; bool in_use; unsigned int safe_window_end; + unsigned int last_bufaddr; }; static DEFINE_MUTEX(ipu_pre_list_mutex); @@ -185,6 +186,7 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width, writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF); writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF); + pre->last_bufaddr = bufaddr; val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) | IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) | @@ -242,7 +244,11 @@ void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr) unsigned short current_yblock; u32 val; + if (bufaddr == pre->last_bufaddr) + return; + writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF); + pre->last_bufaddr = bufaddr; do { if (time_after(jiffies, timeout)) { diff --git a/drivers/gpu/vga/Kconfig b/drivers/gpu/vga/Kconfig index b677e5d524e6..d5f1d8e1c6f8 100644 --- a/drivers/gpu/vga/Kconfig +++ b/drivers/gpu/vga/Kconfig @@ -21,6 +21,7 @@ config VGA_SWITCHEROO bool "Laptop Hybrid Graphics - GPU switching support" depends on X86 depends on ACPI + depends on PCI select VGA_ARB help Many laptops released in 2008/9/10 have two GPUs with a multiplexer diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index f41d5fe51abe..9993b692598f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -125,6 +125,7 @@ static int open_collection(struct hid_parser *parser, unsigned type) { struct hid_collection *collection; unsigned usage; + int collection_index; usage = parser->local.usage[0]; @@ -167,13 +168,13 @@ static int open_collection(struct hid_parser *parser, unsigned type) parser->collection_stack[parser->collection_stack_ptr++] = parser->device->maxcollection; - collection = parser->device->collection + - parser->device->maxcollection++; + collection_index = parser->device->maxcollection++; + collection = parser->device->collection + collection_index; collection->type = type; collection->usage = usage; collection->level = parser->collection_stack_ptr - 1; - collection->parent = parser->active_collection; - parser->active_collection = collection; + collection->parent_idx = (collection->level == 0) ? -1 : + parser->collection_stack[collection->level - 1]; if (type == HID_COLLECTION_APPLICATION) parser->device->maxapplication++; @@ -192,8 +193,6 @@ static int close_collection(struct hid_parser *parser) return -EINVAL; } parser->collection_stack_ptr--; - if (parser->active_collection) - parser->active_collection = parser->active_collection->parent; return 0; } @@ -1006,10 +1005,12 @@ static void hid_apply_multiplier_to_field(struct hid_device *hid, usage = &field->usage[i]; collection = &hid->collection[usage->collection_index]; - while (collection && collection != multiplier_collection) - collection = collection->parent; + while (collection->parent_idx != -1 && + collection != multiplier_collection) + collection = &hid->collection[collection->parent_idx]; - if (collection || multiplier_collection == NULL) + if (collection->parent_idx != -1 || + multiplier_collection == NULL) usage->resolution_multiplier = effective_multiplier; } @@ -1044,9 +1045,9 @@ static void hid_apply_multiplier(struct hid_device *hid, * applicable fields later. */ multiplier_collection = &hid->collection[multiplier->usage->collection_index]; - while (multiplier_collection && + while (multiplier_collection->parent_idx != -1 && multiplier_collection->type != HID_COLLECTION_LOGICAL) - multiplier_collection = multiplier_collection->parent; + multiplier_collection = &hid->collection[multiplier_collection->parent_idx]; effective_multiplier = hid_calculate_multiplier(hid, multiplier); diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index c530476edba6..ac9fda1b5a72 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -30,6 +30,7 @@ #include <linux/debugfs.h> #include <linux/seq_file.h> +#include <linux/kfifo.h> #include <linux/sched/signal.h> #include <linux/export.h> #include <linux/slab.h> @@ -661,17 +662,12 @@ EXPORT_SYMBOL_GPL(hid_dump_device); /* enqueue string to 'events' ring buffer */ void hid_debug_event(struct hid_device *hdev, char *buf) { - unsigned i; struct hid_debug_list *list; unsigned long flags; spin_lock_irqsave(&hdev->debug_list_lock, flags); - list_for_each_entry(list, &hdev->debug_list, node) { - for (i = 0; buf[i]; i++) - list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] = - buf[i]; - list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE; - } + list_for_each_entry(list, &hdev->debug_list, node) + kfifo_in(&list->hid_debug_fifo, buf, strlen(buf)); spin_unlock_irqrestore(&hdev->debug_list_lock, flags); wake_up_interruptible(&hdev->debug_wait); @@ -722,8 +718,7 @@ void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 valu hid_debug_event(hdev, buf); kfree(buf); - wake_up_interruptible(&hdev->debug_wait); - + wake_up_interruptible(&hdev->debug_wait); } EXPORT_SYMBOL_GPL(hid_dump_input); @@ -1083,8 +1078,8 @@ static int hid_debug_events_open(struct inode *inode, struct file *file) goto out; } - if (!(list->hid_debug_buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_KERNEL))) { - err = -ENOMEM; + err = kfifo_alloc(&list->hid_debug_fifo, HID_DEBUG_FIFOSIZE, GFP_KERNEL); + if (err) { kfree(list); goto out; } @@ -1104,77 +1099,57 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct hid_debug_list *list = file->private_data; - int ret = 0, len; + int ret = 0, copied; DECLARE_WAITQUEUE(wait, current); mutex_lock(&list->read_mutex); - while (ret == 0) { - if (list->head == list->tail) { - add_wait_queue(&list->hdev->debug_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - while (list->head == list->tail) { - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } + if (kfifo_is_empty(&list->hid_debug_fifo)) { + add_wait_queue(&list->hdev->debug_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + while (kfifo_is_empty(&list->hid_debug_fifo)) { + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + break; + } - if (!list->hdev || !list->hdev->debug) { - ret = -EIO; - set_current_state(TASK_RUNNING); - goto out; - } + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } - /* allow O_NONBLOCK from other threads */ - mutex_unlock(&list->read_mutex); - schedule(); - mutex_lock(&list->read_mutex); - set_current_state(TASK_INTERRUPTIBLE); + /* if list->hdev is NULL we cannot remove_wait_queue(). + * if list->hdev->debug is 0 then hid_debug_unregister() + * was already called and list->hdev is being destroyed. + * if we add remove_wait_queue() here we can hit a race. + */ + if (!list->hdev || !list->hdev->debug) { + ret = -EIO; + set_current_state(TASK_RUNNING); + goto out; } - set_current_state(TASK_RUNNING); - remove_wait_queue(&list->hdev->debug_wait, &wait); + /* allow O_NONBLOCK from other threads */ + mutex_unlock(&list->read_mutex); + schedule(); + mutex_lock(&list->read_mutex); + set_current_state(TASK_INTERRUPTIBLE); } - if (ret) - goto out; + __set_current_state(TASK_RUNNING); + remove_wait_queue(&list->hdev->debug_wait, &wait); - /* pass the ringbuffer contents to userspace */ -copy_rest: - if (list->tail == list->head) + if (ret) goto out; - if (list->tail > list->head) { - len = list->tail - list->head; - if (len > count) - len = count; - - if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) { - ret = -EFAULT; - goto out; - } - ret += len; - list->head += len; - } else { - len = HID_DEBUG_BUFSIZE - list->head; - if (len > count) - len = count; - - if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) { - ret = -EFAULT; - goto out; - } - list->head = 0; - ret += len; - count -= len; - if (count > 0) - goto copy_rest; - } - } + + /* pass the fifo content to userspace, locking is not needed with only + * one concurrent reader and one concurrent writer + */ + ret = kfifo_to_user(&list->hid_debug_fifo, buffer, count, &copied); + if (ret) + goto out; + ret = copied; out: mutex_unlock(&list->read_mutex); return ret; @@ -1185,7 +1160,7 @@ static __poll_t hid_debug_events_poll(struct file *file, poll_table *wait) struct hid_debug_list *list = file->private_data; poll_wait(file, &list->hdev->debug_wait, wait); - if (list->head != list->tail) + if (!kfifo_is_empty(&list->hid_debug_fifo)) return EPOLLIN | EPOLLRDNORM; if (!list->hdev->debug) return EPOLLERR | EPOLLHUP; @@ -1200,7 +1175,7 @@ static int hid_debug_events_release(struct inode *inode, struct file *file) spin_lock_irqsave(&list->hdev->debug_list_lock, flags); list_del(&list->node); spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags); - kfree(list->hid_debug_buf); + kfifo_free(&list->hid_debug_fifo); kfree(list); return 0; @@ -1246,4 +1221,3 @@ void hid_debug_exit(void) { debugfs_remove_recursive(hid_debug_root); } - diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 518fa76414f5..24f846d67478 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -461,6 +461,9 @@ #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100 +#define I2C_VENDOR_ID_GOODIX 0x27c6 +#define I2C_DEVICE_ID_GOODIX_01F0 0x01f0 + #define USB_VENDOR_ID_GOODTOUCH 0x1aad #define USB_DEVICE_ID_GOODTOUCH_000f 0x000f diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index 8555ce7e737b..c5edfa966343 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -179,6 +179,8 @@ static const struct i2c_hid_quirks { I2C_HID_QUIRK_DELAY_AFTER_SLEEP }, { USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_8001, I2C_HID_QUIRK_NO_RUNTIME_PM }, + { I2C_VENDOR_ID_GOODIX, I2C_DEVICE_ID_GOODIX_01F0, + I2C_HID_QUIRK_NO_RUNTIME_PM }, { 0, 0 } }; diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index ce0ba2062723..bea4c9850247 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -701,19 +701,12 @@ static int vmbus_close_internal(struct vmbus_channel *channel) int vmbus_disconnect_ring(struct vmbus_channel *channel) { struct vmbus_channel *cur_channel, *tmp; - unsigned long flags; - LIST_HEAD(list); int ret; if (channel->primary_channel != NULL) return -EINVAL; - /* Snapshot the list of subchannels */ - spin_lock_irqsave(&channel->lock, flags); - list_splice_init(&channel->sc_list, &list); - spin_unlock_irqrestore(&channel->lock, flags); - - list_for_each_entry_safe(cur_channel, tmp, &list, sc_list) { + list_for_each_entry_safe(cur_channel, tmp, &channel->sc_list, sc_list) { if (cur_channel->rescind) wait_for_completion(&cur_channel->rescind_event); diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 5301fef16c31..7c6349a50ef1 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -888,12 +888,14 @@ static unsigned long handle_pg_range(unsigned long pg_start, pfn_cnt -= pgs_ol; /* * Check if the corresponding memory block is already - * online by checking its last previously backed page. - * In case it is we need to bring rest (which was not - * backed previously) online too. + * online. It is possible to observe struct pages still + * being uninitialized here so check section instead. + * In case the section is online we need to bring the + * rest of pfns (which were not backed previously) + * online too. */ if (start_pfn > has->start_pfn && - !PageReserved(pfn_to_page(start_pfn - 1))) + online_section_nr(pfn_to_section_nr(start_pfn))) hv_bring_pgs_online(has, start_pfn, pgs_ol); } diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 64d0c85d5161..1f1a55e07733 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -164,26 +164,25 @@ hv_get_ringbuffer_availbytes(const struct hv_ring_buffer_info *rbi, } /* Get various debug metrics for the specified ring buffer. */ -void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info, - struct hv_ring_buffer_debug_info *debug_info) +int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info, + struct hv_ring_buffer_debug_info *debug_info) { u32 bytes_avail_towrite; u32 bytes_avail_toread; - if (ring_info->ring_buffer) { - hv_get_ringbuffer_availbytes(ring_info, - &bytes_avail_toread, - &bytes_avail_towrite); - - debug_info->bytes_avail_toread = bytes_avail_toread; - debug_info->bytes_avail_towrite = bytes_avail_towrite; - debug_info->current_read_index = - ring_info->ring_buffer->read_index; - debug_info->current_write_index = - ring_info->ring_buffer->write_index; - debug_info->current_interrupt_mask = - ring_info->ring_buffer->interrupt_mask; - } + if (!ring_info->ring_buffer) + return -EINVAL; + + hv_get_ringbuffer_availbytes(ring_info, + &bytes_avail_toread, + &bytes_avail_towrite); + debug_info->bytes_avail_toread = bytes_avail_toread; + debug_info->bytes_avail_towrite = bytes_avail_towrite; + debug_info->current_read_index = ring_info->ring_buffer->read_index; + debug_info->current_write_index = ring_info->ring_buffer->write_index; + debug_info->current_interrupt_mask + = ring_info->ring_buffer->interrupt_mask; + return 0; } EXPORT_SYMBOL_GPL(hv_ringbuffer_get_debuginfo); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index d0ff65675292..403fee01572c 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -313,12 +313,16 @@ static ssize_t out_intr_mask_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info outbound; + int ret; if (!hv_dev->channel) return -ENODEV; - if (hv_dev->channel->state != CHANNEL_OPENED_STATE) - return -EINVAL; - hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); + + ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, + &outbound); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", outbound.current_interrupt_mask); } static DEVICE_ATTR_RO(out_intr_mask); @@ -328,12 +332,15 @@ static ssize_t out_read_index_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info outbound; + int ret; if (!hv_dev->channel) return -ENODEV; - if (hv_dev->channel->state != CHANNEL_OPENED_STATE) - return -EINVAL; - hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); + + ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, + &outbound); + if (ret < 0) + return ret; return sprintf(buf, "%d\n", outbound.current_read_index); } static DEVICE_ATTR_RO(out_read_index); @@ -344,12 +351,15 @@ static ssize_t out_write_index_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info outbound; + int ret; if (!hv_dev->channel) return -ENODEV; - if (hv_dev->channel->state != CHANNEL_OPENED_STATE) - return -EINVAL; - hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); + + ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, + &outbound); + if (ret < 0) + return ret; return sprintf(buf, "%d\n", outbound.current_write_index); } static DEVICE_ATTR_RO(out_write_index); @@ -360,12 +370,15 @@ static ssize_t out_read_bytes_avail_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info outbound; + int ret; if (!hv_dev->channel) return -ENODEV; - if (hv_dev->channel->state != CHANNEL_OPENED_STATE) - return -EINVAL; - hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); + + ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, + &outbound); + if (ret < 0) + return ret; return sprintf(buf, "%d\n", outbound.bytes_avail_toread); } static DEVICE_ATTR_RO(out_read_bytes_avail); @@ -376,12 +389,15 @@ static ssize_t out_write_bytes_avail_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info outbound; + int ret; if (!hv_dev->channel) return -ENODEV; - if (hv_dev->channel->state != CHANNEL_OPENED_STATE) - return -EINVAL; - hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); + + ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, + &outbound); + if (ret < 0) + return ret; return sprintf(buf, "%d\n", outbound.bytes_avail_towrite); } static DEVICE_ATTR_RO(out_write_bytes_avail); @@ -391,12 +407,15 @@ static ssize_t in_intr_mask_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info inbound; + int ret; if (!hv_dev->channel) return -ENODEV; - if (hv_dev->channel->state != CHANNEL_OPENED_STATE) - return -EINVAL; - hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); + + ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", inbound.current_interrupt_mask); } static DEVICE_ATTR_RO(in_intr_mask); @@ -406,12 +425,15 @@ static ssize_t in_read_index_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info inbound; + int ret; if (!hv_dev->channel) return -ENODEV; - if (hv_dev->channel->state != CHANNEL_OPENED_STATE) - return -EINVAL; - hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); + + ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", inbound.current_read_index); } static DEVICE_ATTR_RO(in_read_index); @@ -421,12 +443,15 @@ static ssize_t in_write_index_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info inbound; + int ret; if (!hv_dev->channel) return -ENODEV; - if (hv_dev->channel->state != CHANNEL_OPENED_STATE) - return -EINVAL; - hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); + + ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", inbound.current_write_index); } static DEVICE_ATTR_RO(in_write_index); @@ -437,12 +462,15 @@ static ssize_t in_read_bytes_avail_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info inbound; + int ret; if (!hv_dev->channel) return -ENODEV; - if (hv_dev->channel->state != CHANNEL_OPENED_STATE) - return -EINVAL; - hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); + + ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", inbound.bytes_avail_toread); } static DEVICE_ATTR_RO(in_read_bytes_avail); @@ -453,12 +481,15 @@ static ssize_t in_write_bytes_avail_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info inbound; + int ret; if (!hv_dev->channel) return -ENODEV; - if (hv_dev->channel->state != CHANNEL_OPENED_STATE) - return -EINVAL; - hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); + + ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", inbound.bytes_avail_towrite); } static DEVICE_ATTR_RO(in_write_bytes_avail); diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c index 76f0a5c01e8a..4aeba29b4629 100644 --- a/drivers/hwmon/ad7418.c +++ b/drivers/hwmon/ad7418.c @@ -19,6 +19,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/mutex.h> +#include <linux/of_device.h> #include <linux/delay.h> #include <linux/slab.h> @@ -54,10 +55,11 @@ struct ad7418_data { u16 in[4]; }; -static struct ad7418_data *ad7418_update_device(struct device *dev) +static int ad7418_update_device(struct device *dev) { struct ad7418_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; + s32 val; mutex_lock(&data->lock); @@ -67,47 +69,74 @@ static struct ad7418_data *ad7418_update_device(struct device *dev) int i, ch; /* read config register and clear channel bits */ - cfg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF); + val = i2c_smbus_read_byte_data(client, AD7418_REG_CONF); + if (val < 0) + goto abort; + + cfg = val; cfg &= 0x1F; - i2c_smbus_write_byte_data(client, AD7418_REG_CONF, + val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF, cfg | AD7418_CH_TEMP); + if (val < 0) + goto abort; + udelay(30); for (i = 0; i < 3; i++) { - data->temp[i] = - i2c_smbus_read_word_swapped(client, - AD7418_REG_TEMP[i]); + val = i2c_smbus_read_word_swapped(client, + AD7418_REG_TEMP[i]); + if (val < 0) + goto abort; + + data->temp[i] = val; } for (i = 0, ch = 4; i < data->adc_max; i++, ch--) { - i2c_smbus_write_byte_data(client, - AD7418_REG_CONF, + val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF, cfg | AD7418_REG_ADC_CH(ch)); + if (val < 0) + goto abort; udelay(15); - data->in[data->adc_max - 1 - i] = - i2c_smbus_read_word_swapped(client, - AD7418_REG_ADC); + val = i2c_smbus_read_word_swapped(client, + AD7418_REG_ADC); + if (val < 0) + goto abort; + + data->in[data->adc_max - 1 - i] = val; } /* restore old configuration value */ - i2c_smbus_write_word_swapped(client, AD7418_REG_CONF, cfg); + val = i2c_smbus_write_word_swapped(client, AD7418_REG_CONF, + cfg); + if (val < 0) + goto abort; data->last_updated = jiffies; data->valid = 1; } mutex_unlock(&data->lock); + return 0; - return data; +abort: + data->valid = 0; + mutex_unlock(&data->lock); + return val; } static ssize_t temp_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct ad7418_data *data = ad7418_update_device(dev); + struct ad7418_data *data = dev_get_drvdata(dev); + int ret; + + ret = ad7418_update_device(dev); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[attr->index])); } @@ -116,7 +145,12 @@ static ssize_t adc_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct ad7418_data *data = ad7418_update_device(dev); + struct ad7418_data *data = dev_get_drvdata(dev); + int ret; + + ret = ad7418_update_device(dev); + if (ret < 0) + return ret; return sprintf(buf, "%d\n", ((data->in[attr->index] >> 6) * 2500 + 512) / 1024); @@ -220,7 +254,10 @@ static int ad7418_probe(struct i2c_client *client, mutex_init(&data->lock); data->client = client; - data->type = id->driver_data; + if (dev->of_node) + data->type = (enum chips)of_device_get_match_data(dev); + else + data->type = id->driver_data; switch (data->type) { case ad7416: @@ -258,9 +295,18 @@ static const struct i2c_device_id ad7418_id[] = { }; MODULE_DEVICE_TABLE(i2c, ad7418_id); +static const struct of_device_id ad7418_dt_ids[] = { + { .compatible = "adi,ad7416", .data = (void *)ad7416, }, + { .compatible = "adi,ad7417", .data = (void *)ad7417, }, + { .compatible = "adi,ad7418", .data = (void *)ad7418, }, + { } +}; +MODULE_DEVICE_TABLE(of, ad7418_dt_ids); + static struct i2c_driver ad7418_driver = { .driver = { .name = "ad7418", + .of_match_table = ad7418_dt_ids, }, .probe = ad7418_probe, .id_table = ad7418_id, diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c index 8c5cdb560258..e561279aea21 100644 --- a/drivers/hwmon/adm1029.c +++ b/drivers/hwmon/adm1029.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * adm1029.c - Part of lm_sensors, Linux kernel modules for hardware monitoring * @@ -19,10 +20,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/module.h> @@ -111,7 +108,7 @@ static const u8 ADM1029_REG_FAN_DIV[] = { struct adm1029_data { struct i2c_client *client; - struct mutex update_lock; + struct mutex update_lock; /* protect register access */ char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -134,8 +131,7 @@ static struct adm1029_data *adm1029_update_device(struct device *dev) * Use the "cache" Luke, don't recheck values * if there are already checked not a long time later */ - if (time_after(jiffies, data->last_updated + HZ * 2) - || !data->valid) { + if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { int nr; dev_dbg(&client->dev, "Updating adm1029 data\n"); @@ -174,6 +170,7 @@ show_temp(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct adm1029_data *data = adm1029_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); } @@ -183,9 +180,10 @@ show_fan(struct device *dev, struct device_attribute *devattr, char *buf) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct adm1029_data *data = adm1029_update_device(dev); u16 val; - if (data->fan[attr->index] == 0 - || (data->fan_div[attr->index] & 0xC0) == 0 - || data->fan[attr->index] == 255) { + + if (data->fan[attr->index] == 0 || + (data->fan_div[attr->index] & 0xC0) == 0 || + data->fan[attr->index] == 255) { return sprintf(buf, "0\n"); } @@ -199,13 +197,14 @@ show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct adm1029_data *data = adm1029_update_device(dev); + if ((data->fan_div[attr->index] & 0xC0) == 0) return sprintf(buf, "0\n"); return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); } -static ssize_t set_fan_div(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count) +static ssize_t set_fan_div(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) { struct adm1029_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -213,6 +212,7 @@ static ssize_t set_fan_div(struct device *dev, u8 reg; long val; int ret = kstrtol(buf, 10, &val); + if (ret < 0) return ret; @@ -253,32 +253,27 @@ static ssize_t set_fan_div(struct device *dev, return count; } -/* - * Access rights on sysfs. S_IRUGO: Is Readable by User, Group and Others - * S_IWUSR: Is Writable by User. - */ -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); +/* Access rights on sysfs. */ +static SENSOR_DEVICE_ATTR(temp1_input, 0444, show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_input, 0444, show_temp, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_input, 0444, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp, NULL, 4); -static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp, NULL, 5); +static SENSOR_DEVICE_ATTR(temp1_max, 0444, show_temp, NULL, 3); +static SENSOR_DEVICE_ATTR(temp2_max, 0444, show_temp, NULL, 4); +static SENSOR_DEVICE_ATTR(temp3_max, 0444, show_temp, NULL, 5); -static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp, NULL, 6); -static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp, NULL, 7); -static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp, NULL, 8); +static SENSOR_DEVICE_ATTR(temp1_min, 0444, show_temp, NULL, 6); +static SENSOR_DEVICE_ATTR(temp2_min, 0444, show_temp, NULL, 7); +static SENSOR_DEVICE_ATTR(temp3_min, 0444, show_temp, NULL, 8); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); +static SENSOR_DEVICE_ATTR(fan1_input, 0444, show_fan, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_input, 0444, show_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan, NULL, 3); +static SENSOR_DEVICE_ATTR(fan1_min, 0444, show_fan, NULL, 2); +static SENSOR_DEVICE_ATTR(fan2_min, 0444, show_fan, NULL, 3); -static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, - show_fan_div, set_fan_div, 0); -static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, - show_fan_div, set_fan_div, 1); +static SENSOR_DEVICE_ATTR(fan1_div, 0644, show_fan_div, set_fan_div, 0); +static SENSOR_DEVICE_ATTR(fan2_div, 0644, show_fan_div, set_fan_div, 1); static struct attribute *adm1029_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, @@ -327,10 +322,10 @@ static int adm1029_detect(struct i2c_client *client, temp_devices_installed = i2c_smbus_read_byte_data(client, ADM1029_REG_TEMP_DEVICES_INSTALLED); nb_fan_support = i2c_smbus_read_byte_data(client, - ADM1029_REG_NB_FAN_SUPPORT); + ADM1029_REG_NB_FAN_SUPPORT); /* 0x41 is Analog Devices */ - if (man_id != 0x41 || (temp_devices_installed & 0xf9) != 0x01 - || nb_fan_support != 0x03) + if (man_id != 0x41 || (temp_devices_installed & 0xf9) != 0x01 || + nb_fan_support != 0x03) return -ENODEV; if ((chip_id & 0xF0) != 0x00) { diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c index b0211f731251..030f5d49c061 100644 --- a/drivers/hwmon/adt7462.c +++ b/drivers/hwmon/adt7462.c @@ -448,6 +448,7 @@ static const char *voltage_label(struct adt7462_data *data, int which) case 3: return "+1.5V"; } + /* fall through */ case 2: if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) return "+12V3"; @@ -505,6 +506,7 @@ static const char *voltage_label(struct adt7462_data *data, int which) case 3: return "+1.5"; } + /* fall through */ case 11: if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == ADT7462_PIN28_VOLT && @@ -542,6 +544,7 @@ static int voltage_multiplier(struct adt7462_data *data, int which) case 3: return 7800; } + /* fall through */ case 2: if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) return 62500; @@ -599,6 +602,7 @@ static int voltage_multiplier(struct adt7462_data *data, int which) case 3: return 7800; } + /* fall through */ case 11: case 12: if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 68c9a6664557..a6a38ceec174 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -82,9 +82,15 @@ static bool disallow_fan_support; #define I8K_HWMON_HAVE_TEMP2 (1 << 1) #define I8K_HWMON_HAVE_TEMP3 (1 << 2) #define I8K_HWMON_HAVE_TEMP4 (1 << 3) -#define I8K_HWMON_HAVE_FAN1 (1 << 4) -#define I8K_HWMON_HAVE_FAN2 (1 << 5) -#define I8K_HWMON_HAVE_FAN3 (1 << 6) +#define I8K_HWMON_HAVE_TEMP5 (1 << 4) +#define I8K_HWMON_HAVE_TEMP6 (1 << 5) +#define I8K_HWMON_HAVE_TEMP7 (1 << 6) +#define I8K_HWMON_HAVE_TEMP8 (1 << 7) +#define I8K_HWMON_HAVE_TEMP9 (1 << 8) +#define I8K_HWMON_HAVE_TEMP10 (1 << 9) +#define I8K_HWMON_HAVE_FAN1 (1 << 10) +#define I8K_HWMON_HAVE_FAN2 (1 << 11) +#define I8K_HWMON_HAVE_FAN3 (1 << 12) MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); @@ -737,6 +743,18 @@ static SENSOR_DEVICE_ATTR_RO(temp3_input, i8k_hwmon_temp, 2); static SENSOR_DEVICE_ATTR_RO(temp3_label, i8k_hwmon_temp_label, 2); static SENSOR_DEVICE_ATTR_RO(temp4_input, i8k_hwmon_temp, 3); static SENSOR_DEVICE_ATTR_RO(temp4_label, i8k_hwmon_temp_label, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_input, i8k_hwmon_temp, 4); +static SENSOR_DEVICE_ATTR_RO(temp5_label, i8k_hwmon_temp_label, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_input, i8k_hwmon_temp, 5); +static SENSOR_DEVICE_ATTR_RO(temp6_label, i8k_hwmon_temp_label, 5); +static SENSOR_DEVICE_ATTR_RO(temp7_input, i8k_hwmon_temp, 6); +static SENSOR_DEVICE_ATTR_RO(temp7_label, i8k_hwmon_temp_label, 6); +static SENSOR_DEVICE_ATTR_RO(temp8_input, i8k_hwmon_temp, 7); +static SENSOR_DEVICE_ATTR_RO(temp8_label, i8k_hwmon_temp_label, 7); +static SENSOR_DEVICE_ATTR_RO(temp9_input, i8k_hwmon_temp, 8); +static SENSOR_DEVICE_ATTR_RO(temp9_label, i8k_hwmon_temp_label, 8); +static SENSOR_DEVICE_ATTR_RO(temp10_input, i8k_hwmon_temp, 9); +static SENSOR_DEVICE_ATTR_RO(temp10_label, i8k_hwmon_temp_label, 9); static SENSOR_DEVICE_ATTR_RO(fan1_input, i8k_hwmon_fan, 0); static SENSOR_DEVICE_ATTR_RO(fan1_label, i8k_hwmon_fan_label, 0); static SENSOR_DEVICE_ATTR_RW(pwm1, i8k_hwmon_pwm, 0); @@ -756,15 +774,27 @@ static struct attribute *i8k_attrs[] = { &sensor_dev_attr_temp3_label.dev_attr.attr, /* 5 */ &sensor_dev_attr_temp4_input.dev_attr.attr, /* 6 */ &sensor_dev_attr_temp4_label.dev_attr.attr, /* 7 */ - &sensor_dev_attr_fan1_input.dev_attr.attr, /* 8 */ - &sensor_dev_attr_fan1_label.dev_attr.attr, /* 9 */ - &sensor_dev_attr_pwm1.dev_attr.attr, /* 10 */ - &sensor_dev_attr_fan2_input.dev_attr.attr, /* 11 */ - &sensor_dev_attr_fan2_label.dev_attr.attr, /* 12 */ - &sensor_dev_attr_pwm2.dev_attr.attr, /* 13 */ - &sensor_dev_attr_fan3_input.dev_attr.attr, /* 14 */ - &sensor_dev_attr_fan3_label.dev_attr.attr, /* 15 */ - &sensor_dev_attr_pwm3.dev_attr.attr, /* 16 */ + &sensor_dev_attr_temp5_input.dev_attr.attr, /* 8 */ + &sensor_dev_attr_temp5_label.dev_attr.attr, /* 9 */ + &sensor_dev_attr_temp6_input.dev_attr.attr, /* 10 */ + &sensor_dev_attr_temp6_label.dev_attr.attr, /* 11 */ + &sensor_dev_attr_temp7_input.dev_attr.attr, /* 12 */ + &sensor_dev_attr_temp7_label.dev_attr.attr, /* 13 */ + &sensor_dev_attr_temp8_input.dev_attr.attr, /* 14 */ + &sensor_dev_attr_temp8_label.dev_attr.attr, /* 15 */ + &sensor_dev_attr_temp9_input.dev_attr.attr, /* 16 */ + &sensor_dev_attr_temp9_label.dev_attr.attr, /* 17 */ + &sensor_dev_attr_temp10_input.dev_attr.attr, /* 18 */ + &sensor_dev_attr_temp10_label.dev_attr.attr, /* 19 */ + &sensor_dev_attr_fan1_input.dev_attr.attr, /* 20 */ + &sensor_dev_attr_fan1_label.dev_attr.attr, /* 21 */ + &sensor_dev_attr_pwm1.dev_attr.attr, /* 22 */ + &sensor_dev_attr_fan2_input.dev_attr.attr, /* 23 */ + &sensor_dev_attr_fan2_label.dev_attr.attr, /* 24 */ + &sensor_dev_attr_pwm2.dev_attr.attr, /* 25 */ + &sensor_dev_attr_fan3_input.dev_attr.attr, /* 26 */ + &sensor_dev_attr_fan3_label.dev_attr.attr, /* 27 */ + &sensor_dev_attr_pwm3.dev_attr.attr, /* 28 */ NULL }; @@ -788,13 +818,32 @@ static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr, if (index >= 6 && index <= 7 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4)) return 0; - if (index >= 8 && index <= 10 && + if (index >= 8 && index <= 9 && + !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP5)) + return 0; + if (index >= 10 && index <= 11 && + !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP6)) + return 0; + if (index >= 12 && index <= 13 && + !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP7)) + return 0; + if (index >= 14 && index <= 15 && + !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP8)) + return 0; + if (index >= 16 && index <= 17 && + !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP9)) + return 0; + if (index >= 18 && index <= 19 && + !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP10)) + return 0; + + if (index >= 20 && index <= 22 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1)) return 0; - if (index >= 11 && index <= 13 && + if (index >= 23 && index <= 25 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2)) return 0; - if (index >= 14 && index <= 16 && + if (index >= 26 && index <= 28 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN3)) return 0; @@ -827,6 +876,24 @@ static int __init i8k_init_hwmon(void) err = i8k_get_temp_type(3); if (err >= 0) i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4; + err = i8k_get_temp_type(4); + if (err >= 0) + i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP5; + err = i8k_get_temp_type(5); + if (err >= 0) + i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP6; + err = i8k_get_temp_type(6); + if (err >= 0) + i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP7; + err = i8k_get_temp_type(7); + if (err >= 0) + i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP8; + err = i8k_get_temp_type(8); + if (err >= 0) + i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP9; + err = i8k_get_temp_type(9); + if (err >= 0) + i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP10; /* First fan attributes, if fan status or type is OK */ err = i8k_get_fan_status(0); diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index ca54ce5c8e10..83023798e489 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2455,7 +2455,7 @@ static int f71882fg_probe(struct platform_device *pdev) case f71869a: /* These always have signed auto point temps */ data->auto_point_temp_signed = 1; - /* Fall through to select correct fan/pwm reg bank! */ + /* Fall through - to select correct fan/pwm reg bank! */ case f71889fg: case f71889ed: case f71889a: diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index b267510daeb2..b7e453298409 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -264,7 +264,7 @@ show(RAW, alarms, alarms); show(BOOL, beep_enable, beep_enable); show(BEEP_MASK, beep_mask, beep_mask); -static ssize_t show_fan_input(struct device *dev, +static ssize_t fan_input_show(struct device *dev, struct device_attribute *attr, char *buf) { int nr = to_sensor_dev_attr(attr)->index; @@ -273,8 +273,8 @@ static ssize_t show_fan_input(struct device *dev, DIV_FROM_REG(data->fan_div[nr]))); } -static ssize_t show_fan_min(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr, + char *buf) { int nr = to_sensor_dev_attr(attr)->index; struct gl518_data *data = gl518_update_device(dev); @@ -282,8 +282,8 @@ static ssize_t show_fan_min(struct device *dev, DIV_FROM_REG(data->fan_div[nr]))); } -static ssize_t show_fan_div(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr, + char *buf) { int nr = to_sensor_dev_attr(attr)->index; struct gl518_data *data = gl518_update_device(dev); @@ -350,8 +350,9 @@ set_high(IN, in_max3, voltage_max[3], GL518_REG_VIN3_LIMIT); set_bits(BOOL, beep_enable, beep_enable, GL518_REG_CONF, 0x04, 2); set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM); -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t fan_min_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { struct gl518_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -383,8 +384,9 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t fan_div_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { struct gl518_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -427,40 +429,36 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, return count; } -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL); -static DEVICE_ATTR(temp1_max, S_IWUSR|S_IRUGO, show_temp_max1, set_temp_max1); -static DEVICE_ATTR(temp1_max_hyst, S_IWUSR|S_IRUGO, - show_temp_hyst1, set_temp_hyst1); -static DEVICE_ATTR(fan1_auto, S_IWUSR|S_IRUGO, show_fan_auto1, set_fan_auto1); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); -static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR|S_IRUGO, - show_fan_min, set_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR|S_IRUGO, - show_fan_min, set_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR|S_IRUGO, - show_fan_div, set_fan_div, 0); -static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR|S_IRUGO, - show_fan_div, set_fan_div, 1); -static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL); -static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL); -static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL); -static DEVICE_ATTR(in3_input, S_IRUGO, show_in_input3, NULL); -static DEVICE_ATTR(in0_min, S_IWUSR|S_IRUGO, show_in_min0, set_in_min0); -static DEVICE_ATTR(in1_min, S_IWUSR|S_IRUGO, show_in_min1, set_in_min1); -static DEVICE_ATTR(in2_min, S_IWUSR|S_IRUGO, show_in_min2, set_in_min2); -static DEVICE_ATTR(in3_min, S_IWUSR|S_IRUGO, show_in_min3, set_in_min3); -static DEVICE_ATTR(in0_max, S_IWUSR|S_IRUGO, show_in_max0, set_in_max0); -static DEVICE_ATTR(in1_max, S_IWUSR|S_IRUGO, show_in_max1, set_in_max1); -static DEVICE_ATTR(in2_max, S_IWUSR|S_IRUGO, show_in_max2, set_in_max2); -static DEVICE_ATTR(in3_max, S_IWUSR|S_IRUGO, show_in_max3, set_in_max3); -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); -static DEVICE_ATTR(beep_enable, S_IWUSR|S_IRUGO, - show_beep_enable, set_beep_enable); -static DEVICE_ATTR(beep_mask, S_IWUSR|S_IRUGO, - show_beep_mask, set_beep_mask); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, +static DEVICE_ATTR(temp1_input, 0444, show_temp_input1, NULL); +static DEVICE_ATTR(temp1_max, 0644, show_temp_max1, set_temp_max1); +static DEVICE_ATTR(temp1_max_hyst, 0644, + show_temp_hyst1, set_temp_hyst1); +static DEVICE_ATTR(fan1_auto, 0644, show_fan_auto1, set_fan_auto1); +static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1); +static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0); +static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1); +static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0); +static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1); +static DEVICE_ATTR(in0_input, 0444, show_in_input0, NULL); +static DEVICE_ATTR(in1_input, 0444, show_in_input1, NULL); +static DEVICE_ATTR(in2_input, 0444, show_in_input2, NULL); +static DEVICE_ATTR(in3_input, 0444, show_in_input3, NULL); +static DEVICE_ATTR(in0_min, 0644, show_in_min0, set_in_min0); +static DEVICE_ATTR(in1_min, 0644, show_in_min1, set_in_min1); +static DEVICE_ATTR(in2_min, 0644, show_in_min2, set_in_min2); +static DEVICE_ATTR(in3_min, 0644, show_in_min3, set_in_min3); +static DEVICE_ATTR(in0_max, 0644, show_in_max0, set_in_max0); +static DEVICE_ATTR(in1_max, 0644, show_in_max1, set_in_max1); +static DEVICE_ATTR(in2_max, 0644, show_in_max2, set_in_max2); +static DEVICE_ATTR(in3_max, 0644, show_in_max3, set_in_max3); +static DEVICE_ATTR(alarms, 0444, show_alarms, NULL); +static DEVICE_ATTR(beep_enable, 0644, + show_beep_enable, set_beep_enable); +static DEVICE_ATTR(beep_mask, 0644, + show_beep_mask, set_beep_mask); + +static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, char *buf) { int bitnr = to_sensor_dev_attr(attr)->index; @@ -468,24 +466,24 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); } -static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0); +static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1); +static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2); +static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3); +static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 4); +static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 5); +static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 6); -static ssize_t show_beep(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t beep_show(struct device *dev, struct device_attribute *attr, + char *buf) { int bitnr = to_sensor_dev_attr(attr)->index; struct gl518_data *data = gl518_update_device(dev); return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1); } -static ssize_t set_beep(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t beep_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct gl518_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -511,13 +509,13 @@ static ssize_t set_beep(struct device *dev, struct device_attribute *attr, return count; } -static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 0); -static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 1); -static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 2); -static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 3); -static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 4); -static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 5); -static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 6); +static SENSOR_DEVICE_ATTR_RW(in0_beep, beep, 0); +static SENSOR_DEVICE_ATTR_RW(in1_beep, beep, 1); +static SENSOR_DEVICE_ATTR_RW(in2_beep, beep, 2); +static SENSOR_DEVICE_ATTR_RW(in3_beep, beep, 3); +static SENSOR_DEVICE_ATTR_RW(temp1_beep, beep, 4); +static SENSOR_DEVICE_ATTR_RW(fan1_beep, beep, 5); +static SENSOR_DEVICE_ATTR_RW(fan2_beep, beep, 6); static struct attribute *gl518_attributes[] = { &dev_attr_in3_input.attr, diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 4ff32ee67fb6..7d430ad955fe 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -216,8 +216,8 @@ static DEVICE_ATTR_RO(cpu0_vid); #define IN_CLAMP(val) clamp_val(val, 0, 255 * 19) #define IN_TO_REG(val) DIV_ROUND_CLOSEST(IN_CLAMP(val), 19) -static ssize_t get_in_input(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t in_input_show(struct device *dev, + struct device_attribute *attr, char *buf) { int n = to_sensor_dev_attr(attr)->index; struct gl520_data *data = gl520_update_device(dev); @@ -229,8 +229,8 @@ static ssize_t get_in_input(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", IN_FROM_REG(r)); } -static ssize_t get_in_min(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t in_min_show(struct device *dev, struct device_attribute *attr, + char *buf) { int n = to_sensor_dev_attr(attr)->index; struct gl520_data *data = gl520_update_device(dev); @@ -242,8 +242,8 @@ static ssize_t get_in_min(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", IN_FROM_REG(r)); } -static ssize_t get_in_max(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t in_max_show(struct device *dev, struct device_attribute *attr, + char *buf) { int n = to_sensor_dev_attr(attr)->index; struct gl520_data *data = gl520_update_device(dev); @@ -255,8 +255,8 @@ static ssize_t get_in_max(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", IN_FROM_REG(r)); } -static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t in_min_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct gl520_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -289,8 +289,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t in_max_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct gl520_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -323,31 +323,21 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, return count; } -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, get_in_input, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, get_in_input, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, get_in_input, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, get_in_input, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, get_in_input, NULL, 4); -static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, - get_in_min, set_in_min, 0); -static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, - get_in_min, set_in_min, 1); -static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR, - get_in_min, set_in_min, 2); -static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR, - get_in_min, set_in_min, 3); -static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR, - get_in_min, set_in_min, 4); -static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, - get_in_max, set_in_max, 0); -static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, - get_in_max, set_in_max, 1); -static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR, - get_in_max, set_in_max, 2); -static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR, - get_in_max, set_in_max, 3); -static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR, - get_in_max, set_in_max, 4); +static SENSOR_DEVICE_ATTR_RO(in0_input, in_input, 0); +static SENSOR_DEVICE_ATTR_RO(in1_input, in_input, 1); +static SENSOR_DEVICE_ATTR_RO(in2_input, in_input, 2); +static SENSOR_DEVICE_ATTR_RO(in3_input, in_input, 3); +static SENSOR_DEVICE_ATTR_RO(in4_input, in_input, 4); +static SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0); +static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1); +static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2); +static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3); +static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4); +static SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0); +static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1); +static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2); +static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3); +static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4); #define DIV_FROM_REG(val) (1 << (val)) #define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (480000 / ((val) << (div)))) @@ -359,8 +349,8 @@ static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR, DIV_ROUND_CLOSEST(480000, \ FAN_CLAMP(val, div) << (div))) -static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t fan_input_show(struct device *dev, + struct device_attribute *attr, char *buf) { int n = to_sensor_dev_attr(attr)->index; struct gl520_data *data = gl520_update_device(dev); @@ -369,8 +359,8 @@ static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr, data->fan_div[n])); } -static ssize_t get_fan_min(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr, + char *buf) { int n = to_sensor_dev_attr(attr)->index; struct gl520_data *data = gl520_update_device(dev); @@ -379,8 +369,8 @@ static ssize_t get_fan_min(struct device *dev, struct device_attribute *attr, data->fan_div[n])); } -static ssize_t get_fan_div(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr, + char *buf) { int n = to_sensor_dev_attr(attr)->index; struct gl520_data *data = gl520_update_device(dev); @@ -395,8 +385,9 @@ static ssize_t fan1_off_show(struct device *dev, return sprintf(buf, "%d\n", data->fan_off); } -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t fan_min_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { struct gl520_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -434,8 +425,9 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t fan_div_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { struct gl520_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -508,24 +500,20 @@ static ssize_t fan1_off_store(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan_input, NULL, 1); -static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, - get_fan_min, set_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR, - get_fan_min, set_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, - get_fan_div, set_fan_div, 0); -static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, - get_fan_div, set_fan_div, 1); +static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1); +static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0); +static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1); +static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0); +static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1); static DEVICE_ATTR_RW(fan1_off); #define TEMP_FROM_REG(val) (((val) - 130) * 1000) #define TEMP_CLAMP(val) clamp_val(val, -130000, 125000) #define TEMP_TO_REG(val) (DIV_ROUND_CLOSEST(TEMP_CLAMP(val), 1000) + 130) -static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t temp_input_show(struct device *dev, + struct device_attribute *attr, char *buf) { int n = to_sensor_dev_attr(attr)->index; struct gl520_data *data = gl520_update_device(dev); @@ -533,8 +521,8 @@ static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_input[n])); } -static ssize_t get_temp_max(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t temp_max_show(struct device *dev, + struct device_attribute *attr, char *buf) { int n = to_sensor_dev_attr(attr)->index; struct gl520_data *data = gl520_update_device(dev); @@ -542,8 +530,8 @@ static ssize_t get_temp_max(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n])); } -static ssize_t get_temp_max_hyst(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t temp_max_hyst_show(struct device *dev, + struct device_attribute *attr, char *buf) { int n = to_sensor_dev_attr(attr)->index; struct gl520_data *data = gl520_update_device(dev); @@ -551,8 +539,9 @@ static ssize_t get_temp_max_hyst(struct device *dev, return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[n])); } -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t temp_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { struct gl520_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -571,8 +560,9 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute - *attr, const char *buf, size_t count) +static ssize_t temp_max_hyst_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct gl520_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -592,16 +582,12 @@ static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute return count; } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, get_temp_input, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, get_temp_input, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, - get_temp_max, set_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, - get_temp_max, set_temp_max, 1); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, - get_temp_max_hyst, set_temp_max_hyst, 0); -static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, - get_temp_max_hyst, set_temp_max_hyst, 1); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_input, 1); +static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1); +static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp_max_hyst, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_max_hyst, temp_max_hyst, 1); static ssize_t alarms_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -674,8 +660,8 @@ static DEVICE_ATTR_RO(alarms); static DEVICE_ATTR_RW(beep_enable); static DEVICE_ATTR_RW(beep_mask); -static ssize_t get_alarm(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, + char *buf) { int bit_nr = to_sensor_dev_attr(attr)->index; struct gl520_data *data = gl520_update_device(dev); @@ -683,18 +669,18 @@ static ssize_t get_alarm(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", (data->alarms >> bit_nr) & 1); } -static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, get_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, get_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, get_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, get_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, get_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, get_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, get_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, get_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, get_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0); +static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1); +static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2); +static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3); +static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 4); +static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 5); +static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 6); +static SENSOR_DEVICE_ATTR_RO(temp2_alarm, alarm, 7); +static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 7); -static ssize_t get_beep(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t beep_show(struct device *dev, struct device_attribute *attr, + char *buf) { int bitnr = to_sensor_dev_attr(attr)->index; struct gl520_data *data = gl520_update_device(dev); @@ -702,8 +688,8 @@ static ssize_t get_beep(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", (data->beep_mask >> bitnr) & 1); } -static ssize_t set_beep(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t beep_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct gl520_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -729,15 +715,15 @@ static ssize_t set_beep(struct device *dev, struct device_attribute *attr, return count; } -static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 0); -static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 1); -static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 2); -static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 3); -static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 4); -static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 5); -static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 6); -static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 7); -static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 7); +static SENSOR_DEVICE_ATTR_RW(in0_beep, beep, 0); +static SENSOR_DEVICE_ATTR_RW(in1_beep, beep, 1); +static SENSOR_DEVICE_ATTR_RW(in2_beep, beep, 2); +static SENSOR_DEVICE_ATTR_RW(in3_beep, beep, 3); +static SENSOR_DEVICE_ATTR_RW(temp1_beep, beep, 4); +static SENSOR_DEVICE_ATTR_RW(fan1_beep, beep, 5); +static SENSOR_DEVICE_ATTR_RW(fan2_beep, beep, 6); +static SENSOR_DEVICE_ATTR_RW(temp2_beep, beep, 7); +static SENSOR_DEVICE_ATTR_RW(in4_beep, beep, 7); static struct attribute *gl520_attributes[] = { &dev_attr_cpu0_vid.attr, diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index a3974cddef07..f1bf67aca9e8 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -307,7 +307,7 @@ static DEVICE_ATTR_RO(pwm1_mode); static DEVICE_ATTR_RO(fan1_min); static DEVICE_ATTR_RO(fan1_max); static DEVICE_ATTR_RO(fan1_input); -static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, fan1_input_show, set_rpm); +static DEVICE_ATTR(fan1_target, 0644, fan1_input_show, set_rpm); static umode_t gpio_fan_is_visible(struct kobject *kobj, struct attribute *attr, int index) diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c index 0ae1ee1dbf76..d167fcfec765 100644 --- a/drivers/hwmon/hih6130.c +++ b/drivers/hwmon/hih6130.c @@ -171,7 +171,7 @@ out: * Will be called on read access to temp1_input sysfs attribute. * Returns number of bytes written into buffer, negative errno on error. */ -static ssize_t hih6130_show_temperature(struct device *dev, +static ssize_t hih6130_temperature_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -193,7 +193,7 @@ static ssize_t hih6130_show_temperature(struct device *dev, * Will be called on read access to humidity1_input sysfs attribute. * Returns number of bytes written into buffer, negative errno on error. */ -static ssize_t hih6130_show_humidity(struct device *dev, +static ssize_t hih6130_humidity_show(struct device *dev, struct device_attribute *attr, char *buf) { struct hih6130 *hih6130 = dev_get_drvdata(dev); @@ -206,10 +206,8 @@ static ssize_t hih6130_show_humidity(struct device *dev, } /* sysfs attributes */ -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, hih6130_show_temperature, - NULL, 0); -static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, hih6130_show_humidity, - NULL, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_input, hih6130_temperature, 0); +static SENSOR_DEVICE_ATTR_RO(humidity1_input, hih6130_humidity, 0); static struct attribute *hih6130_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, @@ -254,8 +252,17 @@ static const struct i2c_device_id hih6130_id[] = { }; MODULE_DEVICE_TABLE(i2c, hih6130_id); +static const struct of_device_id hih6130_of_match[] = { + { .compatible = "honeywell,hih6130", }, + { } +}; +MODULE_DEVICE_TABLE(of, hih6130_of_match); + static struct i2c_driver hih6130_driver = { - .driver.name = "hih6130", + .driver = { + .name = "hih6130", + .of_match_table = of_match_ptr(hih6130_of_match), + }, .probe = hih6130_probe, .id_table = hih6130_id, }; diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 36ed50d4b276..c22dc1e07911 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -278,10 +278,10 @@ static struct attribute *hwmon_genattr(struct device *dev, if (!mode) return ERR_PTR(-ENOENT); - if ((mode & S_IRUGO) && ((is_string && !ops->read_string) || + if ((mode & 0444) && ((is_string && !ops->read_string) || (!is_string && !ops->read))) return ERR_PTR(-EINVAL); - if ((mode & S_IWUGO) && !ops->write) + if ((mode & 0222) && !ops->write) return ERR_PTR(-EINVAL); hattr = devm_kzalloc(dev, sizeof(*hattr), GFP_KERNEL); diff --git a/drivers/hwmon/i5500_temp.c b/drivers/hwmon/i5500_temp.c index 400e0675a90b..a51038c6597d 100644 --- a/drivers/hwmon/i5500_temp.c +++ b/drivers/hwmon/i5500_temp.c @@ -58,7 +58,7 @@ static ssize_t temp1_input_show(struct device *dev, return sprintf(buf, "%ld\n", temp); } -static ssize_t show_thresh(struct device *dev, +static ssize_t thresh_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct pci_dev *pdev = to_pci_dev(dev->parent); @@ -72,7 +72,7 @@ static ssize_t show_thresh(struct device *dev, return sprintf(buf, "%ld\n", temp); } -static ssize_t show_alarm(struct device *dev, +static ssize_t alarm_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct pci_dev *pdev = to_pci_dev(dev->parent); @@ -84,11 +84,11 @@ static ssize_t show_alarm(struct device *dev, } static DEVICE_ATTR_RO(temp1_input); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_thresh, NULL, 0xE2); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_thresh, NULL, 0xEC); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_thresh, NULL, 0xEE); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR_RO(temp1_crit, thresh, 0xE2); +static SENSOR_DEVICE_ATTR_RO(temp1_max_hyst, thresh, 0xEC); +static SENSOR_DEVICE_ATTR_RO(temp1_max, thresh, 0xEE); +static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 1); static struct attribute *i5500_temp_attrs[] = { &dev_attr_temp1_input.attr, diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c index a4edc43dd060..2cf73d8eec1c 100644 --- a/drivers/hwmon/i5k_amb.c +++ b/drivers/hwmon/i5k_amb.c @@ -296,7 +296,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev) snprintf(iattr->name, AMB_SYSFS_NAME_LEN, "temp%d_label", d); iattr->s_attr.dev_attr.attr.name = iattr->name; - iattr->s_attr.dev_attr.attr.mode = S_IRUGO; + iattr->s_attr.dev_attr.attr.mode = 0444; iattr->s_attr.dev_attr.show = show_label; iattr->s_attr.index = k; sysfs_attr_init(&iattr->s_attr.dev_attr.attr); @@ -311,7 +311,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev) snprintf(iattr->name, AMB_SYSFS_NAME_LEN, "temp%d_input", d); iattr->s_attr.dev_attr.attr.name = iattr->name; - iattr->s_attr.dev_attr.attr.mode = S_IRUGO; + iattr->s_attr.dev_attr.attr.mode = 0444; iattr->s_attr.dev_attr.show = show_amb_temp; iattr->s_attr.index = k; sysfs_attr_init(&iattr->s_attr.dev_attr.attr); @@ -326,7 +326,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev) snprintf(iattr->name, AMB_SYSFS_NAME_LEN, "temp%d_min", d); iattr->s_attr.dev_attr.attr.name = iattr->name; - iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO; + iattr->s_attr.dev_attr.attr.mode = 0644; iattr->s_attr.dev_attr.show = show_amb_min; iattr->s_attr.dev_attr.store = store_amb_min; iattr->s_attr.index = k; @@ -342,7 +342,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev) snprintf(iattr->name, AMB_SYSFS_NAME_LEN, "temp%d_mid", d); iattr->s_attr.dev_attr.attr.name = iattr->name; - iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO; + iattr->s_attr.dev_attr.attr.mode = 0644; iattr->s_attr.dev_attr.show = show_amb_mid; iattr->s_attr.dev_attr.store = store_amb_mid; iattr->s_attr.index = k; @@ -358,7 +358,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev) snprintf(iattr->name, AMB_SYSFS_NAME_LEN, "temp%d_max", d); iattr->s_attr.dev_attr.attr.name = iattr->name; - iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO; + iattr->s_attr.dev_attr.attr.mode = 0644; iattr->s_attr.dev_attr.show = show_amb_max; iattr->s_attr.dev_attr.store = store_amb_max; iattr->s_attr.index = k; @@ -374,7 +374,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev) snprintf(iattr->name, AMB_SYSFS_NAME_LEN, "temp%d_alarm", d); iattr->s_attr.dev_attr.attr.name = iattr->name; - iattr->s_attr.dev_attr.attr.mode = S_IRUGO; + iattr->s_attr.dev_attr.attr.mode = 0444; iattr->s_attr.dev_attr.show = show_amb_alarm; iattr->s_attr.index = k; sysfs_attr_init(&iattr->s_attr.dev_attr.attr); diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index 9e92673f6913..db63c1295cb2 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c @@ -813,25 +813,24 @@ static void aem_bmc_gone(int iface) /* sysfs support functions */ /* AEM device name */ -static ssize_t show_name(struct device *dev, struct device_attribute *devattr, +static ssize_t name_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct aem_data *data = dev_get_drvdata(dev); return sprintf(buf, "%s%d\n", DRVNAME, data->ver_major); } -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); +static SENSOR_DEVICE_ATTR_RO(name, name, 0); /* AEM device version */ -static ssize_t show_version(struct device *dev, - struct device_attribute *devattr, - char *buf) +static ssize_t version_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct aem_data *data = dev_get_drvdata(dev); return sprintf(buf, "%d.%d\n", data->ver_major, data->ver_minor); } -static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, 0); +static SENSOR_DEVICE_ATTR_RO(version, version, 0); /* Display power use */ static ssize_t aem_show_power(struct device *dev, @@ -931,7 +930,7 @@ static int aem_register_sensors(struct aem_data *data, while (ro->label) { sysfs_attr_init(&sensors->dev_attr.attr); sensors->dev_attr.attr.name = ro->label; - sensors->dev_attr.attr.mode = S_IRUGO; + sensors->dev_attr.attr.mode = 0444; sensors->dev_attr.show = ro->show; sensors->index = ro->index; @@ -948,7 +947,7 @@ static int aem_register_sensors(struct aem_data *data, while (rw->label) { sysfs_attr_init(&sensors->dev_attr.attr); sensors->dev_attr.attr.name = rw->label; - sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR; + sensors->dev_attr.attr.mode = 0644; sensors->dev_attr.show = rw->show; sensors->dev_attr.store = rw->set; sensors->index = rw->index; diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c index bb17a29af64c..5fd70faf0d16 100644 --- a/drivers/hwmon/ibmpex.c +++ b/drivers/hwmon/ibmpex.c @@ -269,12 +269,12 @@ static struct ibmpex_bmc_data *get_bmc_data(int iface) return NULL; } -static ssize_t show_name(struct device *dev, struct device_attribute *devattr, +static ssize_t name_show(struct device *dev, struct device_attribute *devattr, char *buf) { return sprintf(buf, "%s\n", DRVNAME); } -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); +static SENSOR_DEVICE_ATTR_RO(name, name, 0); static ssize_t ibmpex_show_sensor(struct device *dev, struct device_attribute *devattr, @@ -289,10 +289,9 @@ static ssize_t ibmpex_show_sensor(struct device *dev, data->sensors[attr->index].values[attr->nr] * mult); } -static ssize_t ibmpex_reset_high_low(struct device *dev, +static ssize_t ibmpex_high_low_store(struct device *dev, struct device_attribute *devattr, - const char *buf, - size_t count) + const char *buf, size_t count) { struct ibmpex_bmc_data *data = dev_get_drvdata(dev); @@ -301,8 +300,7 @@ static ssize_t ibmpex_reset_high_low(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(reset_high_low, S_IWUSR, NULL, - ibmpex_reset_high_low, 0); +static SENSOR_DEVICE_ATTR_WO(reset_high_low, ibmpex_high_low, 0); static int is_power_sensor(const char *sensor_id, int len) { @@ -358,7 +356,7 @@ static int create_sensor(struct ibmpex_bmc_data *data, int type, sysfs_attr_init(&data->sensors[sensor].attr[func].dev_attr.attr); data->sensors[sensor].attr[func].dev_attr.attr.name = n; - data->sensors[sensor].attr[func].dev_attr.attr.mode = S_IRUGO; + data->sensors[sensor].attr[func].dev_attr.attr.mode = 0444; data->sensors[sensor].attr[func].dev_attr.show = ibmpex_show_sensor; data->sensors[sensor].attr[func].index = sensor; data->sensors[sensor].attr[func].nr = func; diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c index eed66e533ee2..5c3c08449de7 100644 --- a/drivers/hwmon/iio_hwmon.c +++ b/drivers/hwmon/iio_hwmon.c @@ -129,7 +129,7 @@ static int iio_hwmon_probe(struct platform_device *pdev) return -ENOMEM; a->dev_attr.show = iio_hwmon_read_val; - a->dev_attr.attr.mode = S_IRUGO; + a->dev_attr.attr.mode = 0444; a->index = i; st->attrs[i] = &a->dev_attr.attr; } diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c index aa0768ce8aea..e3854463db84 100644 --- a/drivers/hwmon/ina209.c +++ b/drivers/hwmon/ina209.c @@ -230,9 +230,9 @@ static u16 ina209_reg_from_interval(u16 config, long interval) return (config & 0xf807) | (adc << 3) | (adc << 7); } -static ssize_t ina209_set_interval(struct device *dev, - struct device_attribute *da, - const char *buf, size_t count) +static ssize_t ina209_interval_store(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) { struct ina209_data *data = ina209_update_device(dev); long val; @@ -257,7 +257,7 @@ static ssize_t ina209_set_interval(struct device *dev, return count; } -static ssize_t ina209_show_interval(struct device *dev, +static ssize_t ina209_interval_show(struct device *dev, struct device_attribute *da, char *buf) { struct ina209_data *data = dev_get_drvdata(dev); @@ -279,10 +279,9 @@ static u16 ina209_reset_history_regs[] = { INA209_POWER_PEAK }; -static ssize_t ina209_reset_history(struct device *dev, +static ssize_t ina209_history_store(struct device *dev, struct device_attribute *da, - const char *buf, - size_t count) + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct ina209_data *data = dev_get_drvdata(dev); @@ -306,10 +305,9 @@ static ssize_t ina209_reset_history(struct device *dev, return count; } -static ssize_t ina209_set_value(struct device *dev, - struct device_attribute *da, - const char *buf, - size_t count) +static ssize_t ina209_value_store(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) { struct ina209_data *data = ina209_update_device(dev); struct sensor_device_attribute *attr = to_sensor_dev_attr(da); @@ -337,9 +335,8 @@ abort: return count; } -static ssize_t ina209_show_value(struct device *dev, - struct device_attribute *da, - char *buf) +static ssize_t ina209_value_show(struct device *dev, + struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct ina209_data *data = ina209_update_device(dev); @@ -352,9 +349,8 @@ static ssize_t ina209_show_value(struct device *dev, return snprintf(buf, PAGE_SIZE, "%ld\n", val); } -static ssize_t ina209_show_alarm(struct device *dev, - struct device_attribute *da, - char *buf) +static ssize_t ina209_alarm_show(struct device *dev, + struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct ina209_data *data = ina209_update_device(dev); @@ -374,82 +370,65 @@ static ssize_t ina209_show_alarm(struct device *dev, } /* Shunt voltage, history, limits, alarms */ -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ina209_show_value, NULL, - INA209_SHUNT_VOLTAGE); -static SENSOR_DEVICE_ATTR(in0_input_highest, S_IRUGO, ina209_show_value, NULL, - INA209_SHUNT_VOLTAGE_POS_PEAK); -static SENSOR_DEVICE_ATTR(in0_input_lowest, S_IRUGO, ina209_show_value, NULL, - INA209_SHUNT_VOLTAGE_NEG_PEAK); -static SENSOR_DEVICE_ATTR(in0_reset_history, S_IWUSR, NULL, - ina209_reset_history, (1 << 0) | (1 << 1)); -static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, ina209_show_value, - ina209_set_value, INA209_SHUNT_VOLTAGE_POS_WARN); -static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, ina209_show_value, - ina209_set_value, INA209_SHUNT_VOLTAGE_NEG_WARN); -static SENSOR_DEVICE_ATTR(in0_crit_max, S_IRUGO | S_IWUSR, ina209_show_value, - ina209_set_value, INA209_CRITICAL_DAC_POS); -static SENSOR_DEVICE_ATTR(in0_crit_min, S_IRUGO | S_IWUSR, ina209_show_value, - ina209_set_value, INA209_CRITICAL_DAC_NEG); - -static SENSOR_DEVICE_ATTR(in0_min_alarm, S_IRUGO, ina209_show_alarm, NULL, - 1 << 11); -static SENSOR_DEVICE_ATTR(in0_max_alarm, S_IRUGO, ina209_show_alarm, NULL, - 1 << 12); -static SENSOR_DEVICE_ATTR(in0_crit_min_alarm, S_IRUGO, ina209_show_alarm, NULL, - 1 << 6); -static SENSOR_DEVICE_ATTR(in0_crit_max_alarm, S_IRUGO, ina209_show_alarm, NULL, - 1 << 7); +static SENSOR_DEVICE_ATTR_RO(in0_input, ina209_value, INA209_SHUNT_VOLTAGE); +static SENSOR_DEVICE_ATTR_RO(in0_input_highest, ina209_value, + INA209_SHUNT_VOLTAGE_POS_PEAK); +static SENSOR_DEVICE_ATTR_RO(in0_input_lowest, ina209_value, + INA209_SHUNT_VOLTAGE_NEG_PEAK); +static SENSOR_DEVICE_ATTR_WO(in0_reset_history, ina209_history, + (1 << 0) | (1 << 1)); +static SENSOR_DEVICE_ATTR_RW(in0_max, ina209_value, + INA209_SHUNT_VOLTAGE_POS_WARN); +static SENSOR_DEVICE_ATTR_RW(in0_min, ina209_value, + INA209_SHUNT_VOLTAGE_NEG_WARN); +static SENSOR_DEVICE_ATTR_RW(in0_crit_max, ina209_value, + INA209_CRITICAL_DAC_POS); +static SENSOR_DEVICE_ATTR_RW(in0_crit_min, ina209_value, + INA209_CRITICAL_DAC_NEG); + +static SENSOR_DEVICE_ATTR_RO(in0_min_alarm, ina209_alarm, 1 << 11); +static SENSOR_DEVICE_ATTR_RO(in0_max_alarm, ina209_alarm, 1 << 12); +static SENSOR_DEVICE_ATTR_RO(in0_crit_min_alarm, ina209_alarm, 1 << 6); +static SENSOR_DEVICE_ATTR_RO(in0_crit_max_alarm, ina209_alarm, 1 << 7); /* Bus voltage, history, limits, alarms */ -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ina209_show_value, NULL, - INA209_BUS_VOLTAGE); -static SENSOR_DEVICE_ATTR(in1_input_highest, S_IRUGO, ina209_show_value, NULL, - INA209_BUS_VOLTAGE_MAX_PEAK); -static SENSOR_DEVICE_ATTR(in1_input_lowest, S_IRUGO, ina209_show_value, NULL, - INA209_BUS_VOLTAGE_MIN_PEAK); -static SENSOR_DEVICE_ATTR(in1_reset_history, S_IWUSR, NULL, - ina209_reset_history, (1 << 2) | (1 << 3)); -static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, ina209_show_value, - ina209_set_value, INA209_BUS_VOLTAGE_OVER_WARN); -static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, ina209_show_value, - ina209_set_value, INA209_BUS_VOLTAGE_UNDER_WARN); -static SENSOR_DEVICE_ATTR(in1_crit_max, S_IRUGO | S_IWUSR, ina209_show_value, - ina209_set_value, INA209_BUS_VOLTAGE_OVER_LIMIT); -static SENSOR_DEVICE_ATTR(in1_crit_min, S_IRUGO | S_IWUSR, ina209_show_value, - ina209_set_value, INA209_BUS_VOLTAGE_UNDER_LIMIT); - -static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ina209_show_alarm, NULL, - 1 << 14); -static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ina209_show_alarm, NULL, - 1 << 15); -static SENSOR_DEVICE_ATTR(in1_crit_min_alarm, S_IRUGO, ina209_show_alarm, NULL, - 1 << 9); -static SENSOR_DEVICE_ATTR(in1_crit_max_alarm, S_IRUGO, ina209_show_alarm, NULL, - 1 << 10); +static SENSOR_DEVICE_ATTR_RO(in1_input, ina209_value, INA209_BUS_VOLTAGE); +static SENSOR_DEVICE_ATTR_RO(in1_input_highest, ina209_value, + INA209_BUS_VOLTAGE_MAX_PEAK); +static SENSOR_DEVICE_ATTR_RO(in1_input_lowest, ina209_value, + INA209_BUS_VOLTAGE_MIN_PEAK); +static SENSOR_DEVICE_ATTR_WO(in1_reset_history, ina209_history, + (1 << 2) | (1 << 3)); +static SENSOR_DEVICE_ATTR_RW(in1_max, ina209_value, + INA209_BUS_VOLTAGE_OVER_WARN); +static SENSOR_DEVICE_ATTR_RW(in1_min, ina209_value, + INA209_BUS_VOLTAGE_UNDER_WARN); +static SENSOR_DEVICE_ATTR_RW(in1_crit_max, ina209_value, + INA209_BUS_VOLTAGE_OVER_LIMIT); +static SENSOR_DEVICE_ATTR_RW(in1_crit_min, ina209_value, + INA209_BUS_VOLTAGE_UNDER_LIMIT); + +static SENSOR_DEVICE_ATTR_RO(in1_min_alarm, ina209_alarm, 1 << 14); +static SENSOR_DEVICE_ATTR_RO(in1_max_alarm, ina209_alarm, 1 << 15); +static SENSOR_DEVICE_ATTR_RO(in1_crit_min_alarm, ina209_alarm, 1 << 9); +static SENSOR_DEVICE_ATTR_RO(in1_crit_max_alarm, ina209_alarm, 1 << 10); /* Power */ -static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina209_show_value, NULL, - INA209_POWER); -static SENSOR_DEVICE_ATTR(power1_input_highest, S_IRUGO, ina209_show_value, - NULL, INA209_POWER_PEAK); -static SENSOR_DEVICE_ATTR(power1_reset_history, S_IWUSR, NULL, - ina209_reset_history, 1 << 4); -static SENSOR_DEVICE_ATTR(power1_max, S_IRUGO | S_IWUSR, ina209_show_value, - ina209_set_value, INA209_POWER_WARN); -static SENSOR_DEVICE_ATTR(power1_crit, S_IRUGO | S_IWUSR, ina209_show_value, - ina209_set_value, INA209_POWER_OVER_LIMIT); - -static SENSOR_DEVICE_ATTR(power1_max_alarm, S_IRUGO, ina209_show_alarm, NULL, - 1 << 13); -static SENSOR_DEVICE_ATTR(power1_crit_alarm, S_IRUGO, ina209_show_alarm, NULL, - 1 << 8); +static SENSOR_DEVICE_ATTR_RO(power1_input, ina209_value, INA209_POWER); +static SENSOR_DEVICE_ATTR_RO(power1_input_highest, ina209_value, + INA209_POWER_PEAK); +static SENSOR_DEVICE_ATTR_WO(power1_reset_history, ina209_history, 1 << 4); +static SENSOR_DEVICE_ATTR_RW(power1_max, ina209_value, INA209_POWER_WARN); +static SENSOR_DEVICE_ATTR_RW(power1_crit, ina209_value, + INA209_POWER_OVER_LIMIT); + +static SENSOR_DEVICE_ATTR_RO(power1_max_alarm, ina209_alarm, 1 << 13); +static SENSOR_DEVICE_ATTR_RO(power1_crit_alarm, ina209_alarm, 1 << 8); /* Current */ -static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ina209_show_value, NULL, - INA209_CURRENT); +static SENSOR_DEVICE_ATTR_RO(curr1_input, ina209_value, INA209_CURRENT); -static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, - ina209_show_interval, ina209_set_interval, 0); +static SENSOR_DEVICE_ATTR_RW(update_interval, ina209_interval, 0); /* * Finally, construct an array of pointers to members of the above objects, diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index e90ccac8bebb..3626b87a5fd2 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c @@ -111,6 +111,7 @@ struct ina3221_input { * @inputs: Array of channel input source specific structures * @lock: mutex lock to serialize sysfs attribute accesses * @reg_config: Register value of INA3221_CONFIG + * @single_shot: running in single-shot operating mode */ struct ina3221_data { struct device *pm_dev; @@ -119,6 +120,8 @@ struct ina3221_data { struct ina3221_input inputs[INA3221_NUM_CHANNELS]; struct mutex lock; u32 reg_config; + + bool single_shot; }; static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel) @@ -188,6 +191,11 @@ static int ina3221_read_in(struct device *dev, u32 attr, int channel, long *val) if (!ina3221_is_enabled(ina, channel)) return -ENODATA; + /* Write CONFIG register to trigger a single-shot measurement */ + if (ina->single_shot) + regmap_write(ina->regmap, INA3221_CONFIG, + ina->reg_config); + ret = ina3221_wait_for_data(ina); if (ret) return ret; @@ -232,6 +240,11 @@ static int ina3221_read_curr(struct device *dev, u32 attr, if (!ina3221_is_enabled(ina, channel)) return -ENODATA; + /* Write CONFIG register to trigger a single-shot measurement */ + if (ina->single_shot) + regmap_write(ina->regmap, INA3221_CONFIG, + ina->reg_config); + ret = ina3221_wait_for_data(ina); if (ret) return ret; @@ -499,7 +512,7 @@ static const struct hwmon_chip_info ina3221_chip_info = { }; /* Extra attribute groups */ -static ssize_t ina3221_show_shunt(struct device *dev, +static ssize_t ina3221_shunt_show(struct device *dev, struct device_attribute *attr, char *buf) { struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); @@ -510,9 +523,9 @@ static ssize_t ina3221_show_shunt(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", input->shunt_resistor); } -static ssize_t ina3221_set_shunt(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t ina3221_shunt_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); struct ina3221_data *ina = dev_get_drvdata(dev); @@ -533,12 +546,9 @@ static ssize_t ina3221_set_shunt(struct device *dev, } /* shunt resistance */ -static SENSOR_DEVICE_ATTR(shunt1_resistor, S_IRUGO | S_IWUSR, - ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL1); -static SENSOR_DEVICE_ATTR(shunt2_resistor, S_IRUGO | S_IWUSR, - ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL2); -static SENSOR_DEVICE_ATTR(shunt3_resistor, S_IRUGO | S_IWUSR, - ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL3); +static SENSOR_DEVICE_ATTR_RW(shunt1_resistor, ina3221_shunt, INA3221_CHANNEL1); +static SENSOR_DEVICE_ATTR_RW(shunt2_resistor, ina3221_shunt, INA3221_CHANNEL2); +static SENSOR_DEVICE_ATTR_RW(shunt3_resistor, ina3221_shunt, INA3221_CHANNEL3); static struct attribute *ina3221_attrs[] = { &sensor_dev_attr_shunt1_resistor.dev_attr.attr, @@ -617,6 +627,8 @@ static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina) if (!np) return 0; + ina->single_shot = of_property_read_bool(np, "ti,single-shot"); + for_each_child_of_node(np, child) { ret = ina3221_probe_child_from_dt(dev, child, ina); if (ret) @@ -666,6 +678,10 @@ static int ina3221_probe(struct i2c_client *client, /* The driver will be reset, so use reset value */ ina->reg_config = INA3221_CONFIG_DEFAULT; + /* Clear continuous bit to use single-shot mode */ + if (ina->single_shot) + ina->reg_config &= ~INA3221_CONFIG_MODE_CONTINUOUS; + /* Disable channels if their inputs are disconnected */ for (i = 0; i < INA3221_NUM_CHANNELS; i++) { if (ina->inputs[i].disconnected) diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c index e5234f953a6d..4fa482ae0eb5 100644 --- a/drivers/hwmon/jc42.c +++ b/drivers/hwmon/jc42.c @@ -390,21 +390,21 @@ static umode_t jc42_is_visible(const void *_data, enum hwmon_sensor_types type, { const struct jc42_data *data = _data; unsigned int config = data->config; - umode_t mode = S_IRUGO; + umode_t mode = 0444; switch (attr) { case hwmon_temp_min: case hwmon_temp_max: if (!(config & JC42_CFG_EVENT_LOCK)) - mode |= S_IWUSR; + mode |= 0200; break; case hwmon_temp_crit: if (!(config & JC42_CFG_TCRIT_LOCK)) - mode |= S_IWUSR; + mode |= 0200; break; case hwmon_temp_crit_hyst: if (!(config & (JC42_CFG_EVENT_LOCK | JC42_CFG_TCRIT_LOCK))) - mode |= S_IWUSR; + mode |= 0200; break; case hwmon_temp_input: case hwmon_temp_max_hyst: diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index e59f9113fb93..93a5d51f3c6d 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c @@ -109,8 +109,8 @@ static ssize_t name_show(struct device *dev, struct device_attribute } -static ssize_t show_temp(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t temp_show(struct device *dev, struct device_attribute *devattr, + char *buf) { struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); @@ -129,10 +129,10 @@ static ssize_t show_temp(struct device *dev, /* core, place */ -static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0); -static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1); -static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0); -static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1); +static SENSOR_DEVICE_ATTR_2_RO(temp1_input, temp, 0, 0); +static SENSOR_DEVICE_ATTR_2_RO(temp2_input, temp, 0, 1); +static SENSOR_DEVICE_ATTR_2_RO(temp3_input, temp, 1, 0); +static SENSOR_DEVICE_ATTR_2_RO(temp4_input, temp, 1, 1); static DEVICE_ATTR_RO(name); static const struct pci_device_id k8temp_ids[] = { diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c index 84d791bdb62d..d470295760e2 100644 --- a/drivers/hwmon/lineage-pem.c +++ b/drivers/hwmon/lineage-pem.c @@ -282,8 +282,8 @@ static long pem_get_fan(u8 *data, int len, int index) * Show boolean, either a fault or an alarm. * .nr points to the register, .index is the bit mask to check */ -static ssize_t pem_show_bool(struct device *dev, - struct device_attribute *da, char *buf) +static ssize_t pem_bool_show(struct device *dev, struct device_attribute *da, + char *buf) { struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da); struct pem_data *data = pem_update_device(dev); @@ -296,7 +296,7 @@ static ssize_t pem_show_bool(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", !!status); } -static ssize_t pem_show_data(struct device *dev, struct device_attribute *da, +static ssize_t pem_data_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); @@ -312,7 +312,7 @@ static ssize_t pem_show_data(struct device *dev, struct device_attribute *da, return snprintf(buf, PAGE_SIZE, "%ld\n", value); } -static ssize_t pem_show_input(struct device *dev, struct device_attribute *da, +static ssize_t pem_input_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); @@ -328,7 +328,7 @@ static ssize_t pem_show_input(struct device *dev, struct device_attribute *da, return snprintf(buf, PAGE_SIZE, "%ld\n", value); } -static ssize_t pem_show_fan(struct device *dev, struct device_attribute *da, +static ssize_t pem_fan_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); @@ -345,53 +345,42 @@ static ssize_t pem_show_fan(struct device *dev, struct device_attribute *da, } /* Voltages */ -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, pem_show_data, NULL, - PEM_DATA_VOUT_LSB); -static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, ALRM1_VOUT_OUT_LIMIT); -static SENSOR_DEVICE_ATTR_2(in1_crit_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, ALRM1_OV_VOLT_SHUTDOWN); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, pem_show_input, NULL, - PEM_INPUT_VOLTAGE); -static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, - ALRM1_VIN_OUT_LIMIT | ALRM1_PRIMARY_FAULT); +static SENSOR_DEVICE_ATTR_RO(in1_input, pem_data, PEM_DATA_VOUT_LSB); +static SENSOR_DEVICE_ATTR_2_RO(in1_alarm, pem_bool, PEM_DATA_ALARM_1, + ALRM1_VOUT_OUT_LIMIT); +static SENSOR_DEVICE_ATTR_2_RO(in1_crit_alarm, pem_bool, PEM_DATA_ALARM_1, + ALRM1_OV_VOLT_SHUTDOWN); +static SENSOR_DEVICE_ATTR_RO(in2_input, pem_input, PEM_INPUT_VOLTAGE); +static SENSOR_DEVICE_ATTR_2_RO(in2_alarm, pem_bool, PEM_DATA_ALARM_1, + ALRM1_VIN_OUT_LIMIT | ALRM1_PRIMARY_FAULT); /* Currents */ -static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, pem_show_data, NULL, - PEM_DATA_CURRENT); -static SENSOR_DEVICE_ATTR_2(curr1_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, ALRM1_VIN_OVERCURRENT); +static SENSOR_DEVICE_ATTR_RO(curr1_input, pem_data, PEM_DATA_CURRENT); +static SENSOR_DEVICE_ATTR_2_RO(curr1_alarm, pem_bool, PEM_DATA_ALARM_1, + ALRM1_VIN_OVERCURRENT); /* Power */ -static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, pem_show_input, NULL, - PEM_INPUT_POWER_LSB); -static SENSOR_DEVICE_ATTR_2(power1_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, ALRM1_POWER_LIMIT); +static SENSOR_DEVICE_ATTR_RO(power1_input, pem_input, PEM_INPUT_POWER_LSB); +static SENSOR_DEVICE_ATTR_2_RO(power1_alarm, pem_bool, PEM_DATA_ALARM_1, + ALRM1_POWER_LIMIT); /* Fans */ -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, pem_show_fan, NULL, - PEM_FAN_FAN1); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, pem_show_fan, NULL, - PEM_FAN_FAN2); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, pem_show_fan, NULL, - PEM_FAN_FAN3); -static SENSOR_DEVICE_ATTR_2(fan1_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_2, ALRM2_FAN_FAULT); +static SENSOR_DEVICE_ATTR_RO(fan1_input, pem_fan, PEM_FAN_FAN1); +static SENSOR_DEVICE_ATTR_RO(fan2_input, pem_fan, PEM_FAN_FAN2); +static SENSOR_DEVICE_ATTR_RO(fan3_input, pem_fan, PEM_FAN_FAN3); +static SENSOR_DEVICE_ATTR_2_RO(fan1_alarm, pem_bool, PEM_DATA_ALARM_2, + ALRM2_FAN_FAULT); /* Temperatures */ -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, pem_show_data, NULL, - PEM_DATA_TEMP); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, pem_show_data, NULL, - PEM_DATA_TEMP_MAX); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, pem_show_data, NULL, - PEM_DATA_TEMP_CRIT); -static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, ALRM1_TEMP_WARNING); -static SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, ALRM1_TEMP_SHUTDOWN); -static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_2, ALRM2_TEMP_FAULT); +static SENSOR_DEVICE_ATTR_RO(temp1_input, pem_data, PEM_DATA_TEMP); +static SENSOR_DEVICE_ATTR_RO(temp1_max, pem_data, PEM_DATA_TEMP_MAX); +static SENSOR_DEVICE_ATTR_RO(temp1_crit, pem_data, PEM_DATA_TEMP_CRIT); +static SENSOR_DEVICE_ATTR_2_RO(temp1_alarm, pem_bool, PEM_DATA_ALARM_1, + ALRM1_TEMP_WARNING); +static SENSOR_DEVICE_ATTR_2_RO(temp1_crit_alarm, pem_bool, PEM_DATA_ALARM_1, + ALRM1_TEMP_SHUTDOWN); +static SENSOR_DEVICE_ATTR_2_RO(temp1_fault, pem_bool, PEM_DATA_ALARM_2, + ALRM2_TEMP_FAULT); static struct attribute *pem_attributes[] = { &sensor_dev_attr_in1_input.dev_attr.attr, diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c index 9653bb870a47..d1d728aa31d2 100644 --- a/drivers/hwmon/lm73.c +++ b/drivers/hwmon/lm73.c @@ -62,8 +62,8 @@ struct lm73_data { /*-----------------------------------------------------------------------*/ -static ssize_t set_temp(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) +static ssize_t temp_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct lm73_data *data = dev_get_drvdata(dev); @@ -81,7 +81,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, return (err < 0) ? err : count; } -static ssize_t show_temp(struct device *dev, struct device_attribute *da, +static ssize_t temp_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); @@ -98,8 +98,8 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da, return scnprintf(buf, PAGE_SIZE, "%d\n", temp); } -static ssize_t set_convrate(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) +static ssize_t convrate_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { struct lm73_data *data = dev_get_drvdata(dev); unsigned long convrate; @@ -133,7 +133,7 @@ static ssize_t set_convrate(struct device *dev, struct device_attribute *da, return count; } -static ssize_t show_convrate(struct device *dev, struct device_attribute *da, +static ssize_t convrate_show(struct device *dev, struct device_attribute *da, char *buf) { struct lm73_data *data = dev_get_drvdata(dev); @@ -143,7 +143,7 @@ static ssize_t show_convrate(struct device *dev, struct device_attribute *da, return scnprintf(buf, PAGE_SIZE, "%hu\n", lm73_convrates[res]); } -static ssize_t show_maxmin_alarm(struct device *dev, +static ssize_t maxmin_alarm_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); @@ -168,18 +168,14 @@ abort: /* sysfs attributes for hwmon */ -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, - show_temp, set_temp, LM73_REG_MAX); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, - show_temp, set_temp, LM73_REG_MIN); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, - show_temp, NULL, LM73_REG_INPUT); -static SENSOR_DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, - show_convrate, set_convrate, 0); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, - show_maxmin_alarm, NULL, LM73_CTRL_HI_SHIFT); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, - show_maxmin_alarm, NULL, LM73_CTRL_LO_SHIFT); +static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, LM73_REG_MAX); +static SENSOR_DEVICE_ATTR_RW(temp1_min, temp, LM73_REG_MIN); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, LM73_REG_INPUT); +static SENSOR_DEVICE_ATTR_RW(update_interval, convrate, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, maxmin_alarm, + LM73_CTRL_HI_SHIFT); +static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, maxmin_alarm, + LM73_CTRL_LO_SHIFT); static struct attribute *lm73_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 62acb9f16ec5..447af07450f1 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -176,16 +176,16 @@ static umode_t lm75_is_visible(const void *data, enum hwmon_sensor_types type, case hwmon_chip: switch (attr) { case hwmon_chip_update_interval: - return S_IRUGO; + return 0444; } break; case hwmon_temp: switch (attr) { case hwmon_temp_input: - return S_IRUGO; + return 0444; case hwmon_temp_max: case hwmon_temp_max_hyst: - return S_IRUGO | S_IWUSR; + return 0644; } break; default: diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index 69b05cc2f60e..c27073dc24c1 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c @@ -137,7 +137,7 @@ static struct lm77_data *lm77_update_device(struct device *dev) /* sysfs stuff */ -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, +static ssize_t temp_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -146,7 +146,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, return sprintf(buf, "%d\n", data->temp[attr->index]); } -static ssize_t show_temp_hyst(struct device *dev, +static ssize_t temp_hyst_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -160,8 +160,9 @@ static ssize_t show_temp_hyst(struct device *dev, return sprintf(buf, "%d\n", temp); } -static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t temp_store(struct device *dev, + struct device_attribute *devattr, const char *buf, + size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct lm77_data *data = dev_get_drvdata(dev); @@ -186,9 +187,9 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, * hysteresis is stored as a relative value on the chip, so it has to be * converted first. */ -static ssize_t set_temp_hyst(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t temp_hyst_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { struct lm77_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -208,7 +209,7 @@ static ssize_t set_temp_hyst(struct device *dev, return count; } -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, +static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, char *buf) { int bitnr = to_sensor_dev_attr(attr)->index; @@ -216,22 +217,18 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, t_input); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp, set_temp, - t_crit); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, - t_min); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, - t_max); - -static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, - set_temp_hyst, t_crit); -static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO, show_temp_hyst, NULL, t_min); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp_hyst, NULL, t_max); - -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, t_input); +static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp, t_crit); +static SENSOR_DEVICE_ATTR_RW(temp1_min, temp, t_min); +static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, t_max); + +static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, temp_hyst, t_crit); +static SENSOR_DEVICE_ATTR_RO(temp1_min_hyst, temp_hyst, t_min); +static SENSOR_DEVICE_ATTR_RO(temp1_max_hyst, temp_hyst, t_max); + +static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 2); +static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 1); static struct attribute *lm77_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index 0e30fa00204c..54cf24a2b0ed 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -269,7 +269,7 @@ done: * Sysfs stuff */ -static ssize_t show_in(struct device *dev, struct device_attribute *attr, +static ssize_t in_show(struct device *dev, struct device_attribute *attr, char *buf) { struct lm80_data *data = lm80_update_device(dev); @@ -281,8 +281,8 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr][index])); } -static ssize_t set_in(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t in_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct lm80_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -303,7 +303,7 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t show_fan(struct device *dev, struct device_attribute *attr, +static ssize_t fan_show(struct device *dev, struct device_attribute *attr, char *buf) { int index = to_sensor_dev_attr_2(attr)->index; @@ -315,8 +315,8 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr, DIV_FROM_REG(data->fan_div[index]))); } -static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr, + char *buf) { int nr = to_sensor_dev_attr(attr)->index; struct lm80_data *data = lm80_update_device(dev); @@ -325,8 +325,8 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); } -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t fan_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { int index = to_sensor_dev_attr_2(attr)->index; int nr = to_sensor_dev_attr_2(attr)->nr; @@ -352,8 +352,9 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, * least surprise; the user doesn't expect the fan minimum to change just * because the divisor changed. */ -static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t fan_div_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { int nr = to_sensor_dev_attr(attr)->index; struct lm80_data *data = dev_get_drvdata(dev); @@ -393,8 +394,10 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, } rv = lm80_read_value(client, LM80_REG_FANDIV); - if (rv < 0) + if (rv < 0) { + mutex_unlock(&data->update_lock); return rv; + } reg = (rv & ~(3 << (2 * (nr + 1)))) | (data->fan_div[nr] << (2 * (nr + 1))); lm80_write_value(client, LM80_REG_FANDIV, reg); @@ -408,7 +411,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, +static ssize_t temp_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -418,8 +421,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); } -static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t temp_store(struct device *dev, + struct device_attribute *devattr, const char *buf, + size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct lm80_data *data = dev_get_drvdata(dev); @@ -446,7 +450,7 @@ static ssize_t alarms_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%u\n", data->alarms); } -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, +static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, char *buf) { int bitnr = to_sensor_dev_attr(attr)->index; @@ -456,72 +460,50 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); } -static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO, - show_in, set_in, i_min, 0); -static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO, - show_in, set_in, i_min, 1); -static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO, - show_in, set_in, i_min, 2); -static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO, - show_in, set_in, i_min, 3); -static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO, - show_in, set_in, i_min, 4); -static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO, - show_in, set_in, i_min, 5); -static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO, - show_in, set_in, i_min, 6); -static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO, - show_in, set_in, i_max, 0); -static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO, - show_in, set_in, i_max, 1); -static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO, - show_in, set_in, i_max, 2); -static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO, - show_in, set_in, i_max, 3); -static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO, - show_in, set_in, i_max, 4); -static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO, - show_in, set_in, i_max, 5); -static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO, - show_in, set_in, i_max, 6); -static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in, NULL, i_input, 0); -static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in, NULL, i_input, 1); -static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in, NULL, i_input, 2); -static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in, NULL, i_input, 3); -static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in, NULL, i_input, 4); -static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in, NULL, i_input, 5); -static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in, NULL, i_input, 6); -static SENSOR_DEVICE_ATTR_2(fan1_min, S_IWUSR | S_IRUGO, - show_fan, set_fan_min, f_min, 0); -static SENSOR_DEVICE_ATTR_2(fan2_min, S_IWUSR | S_IRUGO, - show_fan, set_fan_min, f_min, 1); -static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, f_input, 0); -static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, f_input, 1); -static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, - show_fan_div, set_fan_div, 0); -static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO, - show_fan_div, set_fan_div, 1); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, t_input); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, - set_temp, t_hot_max); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp, - set_temp, t_hot_hyst); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp, - set_temp, t_os_max); -static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp, - set_temp, t_os_hyst); +static SENSOR_DEVICE_ATTR_2_RW(in0_min, in, i_min, 0); +static SENSOR_DEVICE_ATTR_2_RW(in1_min, in, i_min, 1); +static SENSOR_DEVICE_ATTR_2_RW(in2_min, in, i_min, 2); +static SENSOR_DEVICE_ATTR_2_RW(in3_min, in, i_min, 3); +static SENSOR_DEVICE_ATTR_2_RW(in4_min, in, i_min, 4); +static SENSOR_DEVICE_ATTR_2_RW(in5_min, in, i_min, 5); +static SENSOR_DEVICE_ATTR_2_RW(in6_min, in, i_min, 6); +static SENSOR_DEVICE_ATTR_2_RW(in0_max, in, i_max, 0); +static SENSOR_DEVICE_ATTR_2_RW(in1_max, in, i_max, 1); +static SENSOR_DEVICE_ATTR_2_RW(in2_max, in, i_max, 2); +static SENSOR_DEVICE_ATTR_2_RW(in3_max, in, i_max, 3); +static SENSOR_DEVICE_ATTR_2_RW(in4_max, in, i_max, 4); +static SENSOR_DEVICE_ATTR_2_RW(in5_max, in, i_max, 5); +static SENSOR_DEVICE_ATTR_2_RW(in6_max, in, i_max, 6); +static SENSOR_DEVICE_ATTR_2_RO(in0_input, in, i_input, 0); +static SENSOR_DEVICE_ATTR_2_RO(in1_input, in, i_input, 1); +static SENSOR_DEVICE_ATTR_2_RO(in2_input, in, i_input, 2); +static SENSOR_DEVICE_ATTR_2_RO(in3_input, in, i_input, 3); +static SENSOR_DEVICE_ATTR_2_RO(in4_input, in, i_input, 4); +static SENSOR_DEVICE_ATTR_2_RO(in5_input, in, i_input, 5); +static SENSOR_DEVICE_ATTR_2_RO(in6_input, in, i_input, 6); +static SENSOR_DEVICE_ATTR_2_RW(fan1_min, fan, f_min, 0); +static SENSOR_DEVICE_ATTR_2_RW(fan2_min, fan, f_min, 1); +static SENSOR_DEVICE_ATTR_2_RO(fan1_input, fan, f_input, 0); +static SENSOR_DEVICE_ATTR_2_RO(fan2_input, fan, f_input, 1); +static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0); +static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, t_input); +static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, t_hot_max); +static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp, t_hot_hyst); +static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp, t_os_max); +static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, temp, t_os_hyst); static DEVICE_ATTR_RO(alarms); -static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 8); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 13); +static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0); +static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1); +static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2); +static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3); +static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 4); +static SENSOR_DEVICE_ATTR_RO(in5_alarm, alarm, 5); +static SENSOR_DEVICE_ATTR_RO(in6_alarm, alarm, 6); +static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 10); +static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 11); +static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 8); +static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 13); /* * Real code diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index cbfd0bb7f135..5bb35dff3d76 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c @@ -158,7 +158,7 @@ static struct lm83_data *lm83_update_device(struct device *dev) * Sysfs stuff */ -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, +static ssize_t temp_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -166,8 +166,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); } -static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t temp_store(struct device *dev, + struct device_attribute *devattr, const char *buf, + size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct lm83_data *data = dev_get_drvdata(dev); @@ -195,8 +196,8 @@ static ssize_t alarms_show(struct device *dev, struct device_attribute *dummy, return sprintf(buf, "%d\n", data->alarms); } -static ssize_t show_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t alarm_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct lm83_data *data = lm83_update_device(dev); @@ -205,36 +206,31 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, - set_temp, 4); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp, - set_temp, 5); -static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp, - set_temp, 6); -static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp, - set_temp, 7); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, 8); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp, NULL, 8); -static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp, - set_temp, 8); -static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_input, temp, 3); +static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, 4); +static SENSOR_DEVICE_ATTR_RW(temp2_max, temp, 5); +static SENSOR_DEVICE_ATTR_RW(temp3_max, temp, 6); +static SENSOR_DEVICE_ATTR_RW(temp4_max, temp, 7); +static SENSOR_DEVICE_ATTR_RO(temp1_crit, temp, 8); +static SENSOR_DEVICE_ATTR_RO(temp2_crit, temp, 8); +static SENSOR_DEVICE_ATTR_RW(temp3_crit, temp, 8); +static SENSOR_DEVICE_ATTR_RO(temp4_crit, temp, 8); /* Individual alarm files */ -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8); -static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 12); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 13); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 15); +static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 0); +static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, alarm, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 2); +static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, alarm, 4); +static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6); +static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 8); +static SENSOR_DEVICE_ATTR_RO(temp4_crit_alarm, alarm, 9); +static SENSOR_DEVICE_ATTR_RO(temp4_fault, alarm, 10); +static SENSOR_DEVICE_ATTR_RO(temp4_max_alarm, alarm, 12); +static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 13); +static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 15); /* Raw alarm file for compatibility */ static DEVICE_ATTR_RO(alarms); diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 0a325878e8f5..a95d48316f06 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -41,7 +41,7 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; enum chips { - lm85, + lm85, lm96000, adm1027, adt7463, adt7468, emc6d100, emc6d102, emc6d103, emc6d103s }; @@ -198,13 +198,18 @@ static int RANGE_TO_REG(long range) #define RANGE_FROM_REG(val) lm85_range_map[(val) & 0x0f] /* These are the PWM frequency encodings */ -static const int lm85_freq_map[8] = { /* 1 Hz */ +static const int lm85_freq_map[] = { /* 1 Hz */ 10, 15, 23, 30, 38, 47, 61, 94 }; -static const int adm1027_freq_map[8] = { /* 1 Hz */ + +static const int lm96000_freq_map[] = { /* 1 Hz */ + 10, 15, 23, 30, 38, 47, 61, 94, + 22500, 24000, 25700, 25700, 27700, 27700, 30000, 30000 +}; + +static const int adm1027_freq_map[] = { /* 1 Hz */ 11, 15, 22, 29, 35, 44, 59, 88 }; -#define FREQ_MAP_LEN 8 static int FREQ_TO_REG(const int *map, unsigned int map_size, unsigned long freq) @@ -212,9 +217,9 @@ static int FREQ_TO_REG(const int *map, return find_closest(freq, map, map_size); } -static int FREQ_FROM_REG(const int *map, u8 reg) +static int FREQ_FROM_REG(const int *map, unsigned int map_size, u8 reg) { - return map[reg & 0x07]; + return map[reg % map_size]; } /* @@ -296,6 +301,8 @@ struct lm85_data { struct i2c_client *client; const struct attribute_group *groups[6]; const int *freq_map; + unsigned int freq_map_size; + enum chips type; bool has_vid5; /* true if VID5 is configured for ADT7463 or ADT7468 */ @@ -514,7 +521,7 @@ static struct lm85_data *lm85_update_device(struct device *dev) data->autofan[i].config = lm85_read_value(client, LM85_REG_AFAN_CONFIG(i)); val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i)); - data->pwm_freq[i] = val & 0x07; + data->pwm_freq[i] = val % data->freq_map_size; data->zone[i].range = val >> 4; data->autofan[i].min_pwm = lm85_read_value(client, LM85_REG_AFAN_MINPWM(i)); @@ -791,7 +798,8 @@ static ssize_t show_pwm_freq(struct device *dev, if (IS_ADT7468_HFPWM(data)) freq = 22500; else - freq = FREQ_FROM_REG(data->freq_map, data->pwm_freq[nr]); + freq = FREQ_FROM_REG(data->freq_map, data->freq_map_size, + data->pwm_freq[nr]); return sprintf(buf, "%d\n", freq); } @@ -820,7 +828,7 @@ static ssize_t set_pwm_freq(struct device *dev, lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5); } else { /* Low freq. mode */ data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, - FREQ_MAP_LEN, val); + data->freq_map_size, val); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), (data->zone[nr].range << 4) | data->pwm_freq[nr]); @@ -1196,7 +1204,7 @@ static ssize_t set_temp_auto_temp_min(struct device *dev, TEMP_FROM_REG(data->zone[nr].limit)); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), ((data->zone[nr].range & 0x0f) << 4) - | (data->pwm_freq[nr] & 0x07)); + | data->pwm_freq[nr]); mutex_unlock(&data->update_lock); return count; @@ -1232,7 +1240,7 @@ static ssize_t set_temp_auto_temp_max(struct device *dev, val - min); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), ((data->zone[nr].range & 0x0f) << 4) - | (data->pwm_freq[nr] & 0x07)); + | data->pwm_freq[nr]); mutex_unlock(&data->update_lock); return count; } @@ -1496,7 +1504,7 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info) "Found Winbond WPCD377I, ignoring\n"); return -ENODEV; } - type_name = "lm85"; + type_name = "lm96000"; break; } } else if (company == LM85_COMPANY_ANALOG_DEV) { @@ -1569,9 +1577,15 @@ static int lm85_probe(struct i2c_client *client, const struct i2c_device_id *id) case emc6d103: case emc6d103s: data->freq_map = adm1027_freq_map; + data->freq_map_size = ARRAY_SIZE(adm1027_freq_map); + break; + case lm96000: + data->freq_map = lm96000_freq_map; + data->freq_map_size = ARRAY_SIZE(lm96000_freq_map); break; default: data->freq_map = lm85_freq_map; + data->freq_map_size = ARRAY_SIZE(lm85_freq_map); } /* Set the VRM version */ @@ -1618,6 +1632,7 @@ static const struct i2c_device_id lm85_id[] = { { "lm85", lm85 }, { "lm85b", lm85 }, { "lm85c", lm85 }, + { "lm96000", lm96000 }, { "emc6d100", emc6d100 }, { "emc6d101", emc6d100 }, { "emc6d102", emc6d102 }, @@ -1653,6 +1668,10 @@ static const struct of_device_id lm85_of_match[] = { .data = (void *)lm85 }, { + .compatible = "ti,lm96000", + .data = (void *)lm96000 + }, + { .compatible = "smsc,emc6d100", .data = (void *)emc6d100 }, diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index c2f411c290bf..480d70a51778 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -1266,17 +1266,17 @@ static umode_t lm90_temp_is_visible(const void *data, u32 attr, int channel) case hwmon_temp_emergency_alarm: case hwmon_temp_emergency_hyst: case hwmon_temp_fault: - return S_IRUGO; + return 0444; case hwmon_temp_min: case hwmon_temp_max: case hwmon_temp_crit: case hwmon_temp_emergency: case hwmon_temp_offset: - return S_IRUGO | S_IWUSR; + return 0644; case hwmon_temp_crit_hyst: if (channel == 0) - return S_IRUGO | S_IWUSR; - return S_IRUGO; + return 0644; + return 0444; default: return 0; } @@ -1338,9 +1338,9 @@ static umode_t lm90_chip_is_visible(const void *data, u32 attr, int channel) { switch (attr) { case hwmon_chip_update_interval: - return S_IRUGO | S_IWUSR; + return 0644; case hwmon_chip_alarms: - return S_IRUGO; + return 0444; default: return 0; } diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c index e7333f8e185c..39d8afe4279a 100644 --- a/drivers/hwmon/lm92.c +++ b/drivers/hwmon/lm92.c @@ -143,7 +143,7 @@ static struct lm92_data *lm92_update_device(struct device *dev) return data; } -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, +static ssize_t temp_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -152,8 +152,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); } -static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t temp_store(struct device *dev, + struct device_attribute *devattr, const char *buf, + size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct lm92_data *data = dev_get_drvdata(dev); @@ -173,7 +174,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, return count; } -static ssize_t show_temp_hyst(struct device *dev, +static ssize_t temp_hyst_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -192,9 +193,9 @@ static ssize_t temp1_min_hyst_show(struct device *dev, + TEMP_FROM_REG(data->temp[t_hyst])); } -static ssize_t set_temp_hyst(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t temp_hyst_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct lm92_data *data = dev_get_drvdata(dev); @@ -224,7 +225,7 @@ static ssize_t alarms_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp[t_input])); } -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, +static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, char *buf) { int bitnr = to_sensor_dev_attr(attr)->index; @@ -232,21 +233,17 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", (data->temp[t_input] >> bitnr) & 1); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, t_input); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp, set_temp, - t_crit); -static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, - set_temp_hyst, t_crit); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, - t_min); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, t_input); +static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp, t_crit); +static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, temp_hyst, t_crit); +static SENSOR_DEVICE_ATTR_RW(temp1_min, temp, t_min); static DEVICE_ATTR_RO(temp1_min_hyst); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, - t_max); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp_hyst, NULL, t_max); +static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, t_max); +static SENSOR_DEVICE_ATTR_RO(temp1_max_hyst, temp_hyst, t_max); static DEVICE_ATTR_RO(alarms); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 2); +static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 1); /* * Detection and registration diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index 77a0a83399b3..a0b5fbf958f3 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -1111,8 +1111,8 @@ static void lm93_update_client_min(struct lm93_data *data, } /* following are the sysfs callback functions */ -static ssize_t show_in(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t in_show(struct device *dev, struct device_attribute *attr, + char *buf) { int nr = (to_sensor_dev_attr(attr))->index; @@ -1120,25 +1120,25 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", LM93_IN_FROM_REG(nr, data->block3[nr])); } -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 0); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 1); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 2); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 3); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 4); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 5); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 6); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 7); -static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in, NULL, 8); -static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in, NULL, 9); -static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_in, NULL, 10); -static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_in, NULL, 11); -static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_in, NULL, 12); -static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, show_in, NULL, 13); -static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, show_in, NULL, 14); -static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in, NULL, 15); - -static ssize_t show_in_min(struct device *dev, - struct device_attribute *attr, char *buf) +static SENSOR_DEVICE_ATTR_RO(in1_input, in, 0); +static SENSOR_DEVICE_ATTR_RO(in2_input, in, 1); +static SENSOR_DEVICE_ATTR_RO(in3_input, in, 2); +static SENSOR_DEVICE_ATTR_RO(in4_input, in, 3); +static SENSOR_DEVICE_ATTR_RO(in5_input, in, 4); +static SENSOR_DEVICE_ATTR_RO(in6_input, in, 5); +static SENSOR_DEVICE_ATTR_RO(in7_input, in, 6); +static SENSOR_DEVICE_ATTR_RO(in8_input, in, 7); +static SENSOR_DEVICE_ATTR_RO(in9_input, in, 8); +static SENSOR_DEVICE_ATTR_RO(in10_input, in, 9); +static SENSOR_DEVICE_ATTR_RO(in11_input, in, 10); +static SENSOR_DEVICE_ATTR_RO(in12_input, in, 11); +static SENSOR_DEVICE_ATTR_RO(in13_input, in, 12); +static SENSOR_DEVICE_ATTR_RO(in14_input, in, 13); +static SENSOR_DEVICE_ATTR_RO(in15_input, in, 14); +static SENSOR_DEVICE_ATTR_RO(in16_input, in, 15); + +static ssize_t in_min_show(struct device *dev, struct device_attribute *attr, + char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); @@ -1154,7 +1154,7 @@ static ssize_t show_in_min(struct device *dev, return sprintf(buf, "%ld\n", rc); } -static ssize_t store_in_min(struct device *dev, struct device_attribute *attr, +static ssize_t in_min_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; @@ -1185,41 +1185,25 @@ static ssize_t store_in_min(struct device *dev, struct device_attribute *attr, return count; } -static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 0); -static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 1); -static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 2); -static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 3); -static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 4); -static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 5); -static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 6); -static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 7); -static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 8); -static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 9); -static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 10); -static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 11); -static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 12); -static SENSOR_DEVICE_ATTR(in14_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 13); -static SENSOR_DEVICE_ATTR(in15_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 14); -static SENSOR_DEVICE_ATTR(in16_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 15); - -static ssize_t show_in_max(struct device *dev, - struct device_attribute *attr, char *buf) +static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 0); +static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 1); +static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 2); +static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 3); +static SENSOR_DEVICE_ATTR_RW(in5_min, in_min, 4); +static SENSOR_DEVICE_ATTR_RW(in6_min, in_min, 5); +static SENSOR_DEVICE_ATTR_RW(in7_min, in_min, 6); +static SENSOR_DEVICE_ATTR_RW(in8_min, in_min, 7); +static SENSOR_DEVICE_ATTR_RW(in9_min, in_min, 8); +static SENSOR_DEVICE_ATTR_RW(in10_min, in_min, 9); +static SENSOR_DEVICE_ATTR_RW(in11_min, in_min, 10); +static SENSOR_DEVICE_ATTR_RW(in12_min, in_min, 11); +static SENSOR_DEVICE_ATTR_RW(in13_min, in_min, 12); +static SENSOR_DEVICE_ATTR_RW(in14_min, in_min, 13); +static SENSOR_DEVICE_ATTR_RW(in15_min, in_min, 14); +static SENSOR_DEVICE_ATTR_RW(in16_min, in_min, 15); + +static ssize_t in_max_show(struct device *dev, struct device_attribute *attr, + char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); @@ -1235,7 +1219,7 @@ static ssize_t show_in_max(struct device *dev, return sprintf(buf, "%ld\n", rc); } -static ssize_t store_in_max(struct device *dev, struct device_attribute *attr, +static ssize_t in_max_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; @@ -1266,61 +1250,46 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute *attr, return count; } -static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 0); -static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 1); -static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 2); -static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 3); -static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 4); -static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 5); -static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 6); -static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 7); -static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 8); -static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 9); -static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 10); -static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 11); -static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 12); -static SENSOR_DEVICE_ATTR(in14_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 13); -static SENSOR_DEVICE_ATTR(in15_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 14); -static SENSOR_DEVICE_ATTR(in16_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 15); - -static ssize_t show_temp(struct device *dev, - struct device_attribute *attr, char *buf) +static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 0); +static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 1); +static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 2); +static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 3); +static SENSOR_DEVICE_ATTR_RW(in5_max, in_max, 4); +static SENSOR_DEVICE_ATTR_RW(in6_max, in_max, 5); +static SENSOR_DEVICE_ATTR_RW(in7_max, in_max, 6); +static SENSOR_DEVICE_ATTR_RW(in8_max, in_max, 7); +static SENSOR_DEVICE_ATTR_RW(in9_max, in_max, 8); +static SENSOR_DEVICE_ATTR_RW(in10_max, in_max, 9); +static SENSOR_DEVICE_ATTR_RW(in11_max, in_max, 10); +static SENSOR_DEVICE_ATTR_RW(in12_max, in_max, 11); +static SENSOR_DEVICE_ATTR_RW(in13_max, in_max, 12); +static SENSOR_DEVICE_ATTR_RW(in14_max, in_max, 13); +static SENSOR_DEVICE_ATTR_RW(in15_max, in_max, 14); +static SENSOR_DEVICE_ATTR_RW(in16_max, in_max, 15); + +static ssize_t temp_show(struct device *dev, struct device_attribute *attr, + char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->block2[nr])); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2); -static ssize_t show_temp_min(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t temp_min_show(struct device *dev, + struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->temp_lim[nr].min)); } -static ssize_t store_temp_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t temp_min_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -1339,14 +1308,11 @@ static ssize_t store_temp_min(struct device *dev, struct device_attribute *attr, return count; } -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, - show_temp_min, store_temp_min, 0); -static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, - show_temp_min, store_temp_min, 1); -static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, - show_temp_min, store_temp_min, 2); +static SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1); +static SENSOR_DEVICE_ATTR_RW(temp3_min, temp_min, 2); -static ssize_t show_temp_max(struct device *dev, +static ssize_t temp_max_show(struct device *dev, struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; @@ -1354,8 +1320,9 @@ static ssize_t show_temp_max(struct device *dev, return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->temp_lim[nr].max)); } -static ssize_t store_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t temp_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -1374,24 +1341,21 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute *attr, return count; } -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, - show_temp_max, store_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, - show_temp_max, store_temp_max, 1); -static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, - show_temp_max, store_temp_max, 2); +static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1); +static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2); -static ssize_t show_temp_auto_base(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t temp_auto_base_show(struct device *dev, + struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->block10.base[nr])); } -static ssize_t store_temp_auto_base(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t temp_auto_base_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -1410,14 +1374,11 @@ static ssize_t store_temp_auto_base(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(temp1_auto_base, S_IWUSR | S_IRUGO, - show_temp_auto_base, store_temp_auto_base, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_base, S_IWUSR | S_IRUGO, - show_temp_auto_base, store_temp_auto_base, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_base, S_IWUSR | S_IRUGO, - show_temp_auto_base, store_temp_auto_base, 2); +static SENSOR_DEVICE_ATTR_RW(temp1_auto_base, temp_auto_base, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_auto_base, temp_auto_base, 1); +static SENSOR_DEVICE_ATTR_RW(temp3_auto_base, temp_auto_base, 2); -static ssize_t show_temp_auto_boost(struct device *dev, +static ssize_t temp_auto_boost_show(struct device *dev, struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; @@ -1425,7 +1386,7 @@ static ssize_t show_temp_auto_boost(struct device *dev, return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->boost[nr])); } -static ssize_t store_temp_auto_boost(struct device *dev, +static ssize_t temp_auto_boost_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -1446,14 +1407,11 @@ static ssize_t store_temp_auto_boost(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(temp1_auto_boost, S_IWUSR | S_IRUGO, - show_temp_auto_boost, store_temp_auto_boost, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_boost, S_IWUSR | S_IRUGO, - show_temp_auto_boost, store_temp_auto_boost, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_boost, S_IWUSR | S_IRUGO, - show_temp_auto_boost, store_temp_auto_boost, 2); +static SENSOR_DEVICE_ATTR_RW(temp1_auto_boost, temp_auto_boost, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_auto_boost, temp_auto_boost, 1); +static SENSOR_DEVICE_ATTR_RW(temp3_auto_boost, temp_auto_boost, 2); -static ssize_t show_temp_auto_boost_hyst(struct device *dev, +static ssize_t temp_auto_boost_hyst_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1464,7 +1422,7 @@ static ssize_t show_temp_auto_boost_hyst(struct device *dev, LM93_AUTO_BOOST_HYST_FROM_REGS(data, nr, mode)); } -static ssize_t store_temp_auto_boost_hyst(struct device *dev, +static ssize_t temp_auto_boost_hyst_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -1490,18 +1448,12 @@ static ssize_t store_temp_auto_boost_hyst(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(temp1_auto_boost_hyst, S_IWUSR | S_IRUGO, - show_temp_auto_boost_hyst, - store_temp_auto_boost_hyst, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_boost_hyst, S_IWUSR | S_IRUGO, - show_temp_auto_boost_hyst, - store_temp_auto_boost_hyst, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_boost_hyst, S_IWUSR | S_IRUGO, - show_temp_auto_boost_hyst, - store_temp_auto_boost_hyst, 2); +static SENSOR_DEVICE_ATTR_RW(temp1_auto_boost_hyst, temp_auto_boost_hyst, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_auto_boost_hyst, temp_auto_boost_hyst, 1); +static SENSOR_DEVICE_ATTR_RW(temp3_auto_boost_hyst, temp_auto_boost_hyst, 2); -static ssize_t show_temp_auto_offset(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t temp_auto_offset_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr); int nr = s_attr->index; @@ -1513,9 +1465,9 @@ static ssize_t show_temp_auto_offset(struct device *dev, nr, mode)); } -static ssize_t store_temp_auto_offset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t temp_auto_offset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr); int nr = s_attr->index; @@ -1542,81 +1494,46 @@ static ssize_t store_temp_auto_offset(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset1, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 0, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset2, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 1, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset3, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 2, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset4, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 3, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset5, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 4, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset6, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 5, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset7, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 6, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset8, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 7, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset9, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 8, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset10, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 9, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset11, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 10, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset12, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 11, 0); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset1, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 0, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset2, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 1, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset3, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 2, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset4, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 3, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset5, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 4, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset6, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 5, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset7, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 6, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset8, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 7, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset9, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 8, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset10, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 9, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset11, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 10, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset12, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 11, 1); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset1, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 0, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset2, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 1, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset3, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 2, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset4, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 3, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset5, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 4, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset6, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 5, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset7, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 6, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset8, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 7, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset9, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 8, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset10, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 9, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset11, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 10, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset12, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 11, 2); - -static ssize_t show_temp_auto_pwm_min(struct device *dev, - struct device_attribute *attr, char *buf) +static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset1, temp_auto_offset, 0, 0); +static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset2, temp_auto_offset, 1, 0); +static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset3, temp_auto_offset, 2, 0); +static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset4, temp_auto_offset, 3, 0); +static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset5, temp_auto_offset, 4, 0); +static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset6, temp_auto_offset, 5, 0); +static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset7, temp_auto_offset, 6, 0); +static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset8, temp_auto_offset, 7, 0); +static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset9, temp_auto_offset, 8, 0); +static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset10, temp_auto_offset, 9, 0); +static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset11, temp_auto_offset, 10, 0); +static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset12, temp_auto_offset, 11, 0); +static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset1, temp_auto_offset, 0, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset2, temp_auto_offset, 1, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset3, temp_auto_offset, 2, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset4, temp_auto_offset, 3, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset5, temp_auto_offset, 4, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset6, temp_auto_offset, 5, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset7, temp_auto_offset, 6, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset8, temp_auto_offset, 7, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset9, temp_auto_offset, 8, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset10, temp_auto_offset, 9, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset11, temp_auto_offset, 10, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset12, temp_auto_offset, 11, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset1, temp_auto_offset, 0, 2); +static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset2, temp_auto_offset, 1, 2); +static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset3, temp_auto_offset, 2, 2); +static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset4, temp_auto_offset, 3, 2); +static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset5, temp_auto_offset, 4, 2); +static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset6, temp_auto_offset, 5, 2); +static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset7, temp_auto_offset, 6, 2); +static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset8, temp_auto_offset, 7, 2); +static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset9, temp_auto_offset, 8, 2); +static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset10, temp_auto_offset, 9, 2); +static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset11, temp_auto_offset, 10, 2); +static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset12, temp_auto_offset, 11, 2); + +static ssize_t temp_auto_pwm_min_show(struct device *dev, + struct device_attribute *attr, + char *buf) { int nr = (to_sensor_dev_attr(attr))->index; u8 reg, ctl4; @@ -1627,9 +1544,9 @@ static ssize_t show_temp_auto_pwm_min(struct device *dev, LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ)); } -static ssize_t store_temp_auto_pwm_min(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t temp_auto_pwm_min_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -1655,18 +1572,13 @@ static ssize_t store_temp_auto_pwm_min(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(temp1_auto_pwm_min, S_IWUSR | S_IRUGO, - show_temp_auto_pwm_min, - store_temp_auto_pwm_min, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_pwm_min, S_IWUSR | S_IRUGO, - show_temp_auto_pwm_min, - store_temp_auto_pwm_min, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_pwm_min, S_IWUSR | S_IRUGO, - show_temp_auto_pwm_min, - store_temp_auto_pwm_min, 2); +static SENSOR_DEVICE_ATTR_RW(temp1_auto_pwm_min, temp_auto_pwm_min, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_auto_pwm_min, temp_auto_pwm_min, 1); +static SENSOR_DEVICE_ATTR_RW(temp3_auto_pwm_min, temp_auto_pwm_min, 2); -static ssize_t show_temp_auto_offset_hyst(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t temp_auto_offset_hyst_show(struct device *dev, + struct device_attribute *attr, + char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); @@ -1675,9 +1587,9 @@ static ssize_t show_temp_auto_offset_hyst(struct device *dev, data->auto_pwm_min_hyst[nr / 2], mode)); } -static ssize_t store_temp_auto_offset_hyst(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t temp_auto_offset_hyst_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -1703,18 +1615,12 @@ static ssize_t store_temp_auto_offset_hyst(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(temp1_auto_offset_hyst, S_IWUSR | S_IRUGO, - show_temp_auto_offset_hyst, - store_temp_auto_offset_hyst, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_offset_hyst, S_IWUSR | S_IRUGO, - show_temp_auto_offset_hyst, - store_temp_auto_offset_hyst, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_offset_hyst, S_IWUSR | S_IRUGO, - show_temp_auto_offset_hyst, - store_temp_auto_offset_hyst, 2); +static SENSOR_DEVICE_ATTR_RW(temp1_auto_offset_hyst, temp_auto_offset_hyst, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_auto_offset_hyst, temp_auto_offset_hyst, 1); +static SENSOR_DEVICE_ATTR_RW(temp3_auto_offset_hyst, temp_auto_offset_hyst, 2); -static ssize_t show_fan_input(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t fan_input_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr); int nr = s_attr->index; @@ -1723,13 +1629,13 @@ static ssize_t show_fan_input(struct device *dev, return sprintf(buf, "%d\n", LM93_FAN_FROM_REG(data->block5[nr])); } -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3); +static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1); +static SENSOR_DEVICE_ATTR_RO(fan3_input, fan_input, 2); +static SENSOR_DEVICE_ATTR_RO(fan4_input, fan_input, 3); -static ssize_t show_fan_min(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr, + char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); @@ -1737,8 +1643,9 @@ static ssize_t show_fan_min(struct device *dev, return sprintf(buf, "%d\n", LM93_FAN_FROM_REG(data->block8[nr])); } -static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t fan_min_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -1757,14 +1664,10 @@ static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr, return count; } -static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 2); -static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 3); +static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0); +static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1); +static SENSOR_DEVICE_ATTR_RW(fan3_min, fan_min, 2); +static SENSOR_DEVICE_ATTR_RW(fan4_min, fan_min, 3); /* * some tedious bit-twiddling here to deal with the register format: @@ -1780,8 +1683,8 @@ static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, * T4 T3 T2 T1 */ -static ssize_t show_fan_smart_tach(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t fan_smart_tach_show(struct device *dev, + struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); @@ -1819,9 +1722,9 @@ static void lm93_write_fan_smart_tach(struct i2c_client *client, lm93_write_byte(client, LM93_REG_SFC2, data->sfc2); } -static ssize_t store_fan_smart_tach(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t fan_smart_tach_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -1849,16 +1752,12 @@ static ssize_t store_fan_smart_tach(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(fan1_smart_tach, S_IWUSR | S_IRUGO, - show_fan_smart_tach, store_fan_smart_tach, 0); -static SENSOR_DEVICE_ATTR(fan2_smart_tach, S_IWUSR | S_IRUGO, - show_fan_smart_tach, store_fan_smart_tach, 1); -static SENSOR_DEVICE_ATTR(fan3_smart_tach, S_IWUSR | S_IRUGO, - show_fan_smart_tach, store_fan_smart_tach, 2); -static SENSOR_DEVICE_ATTR(fan4_smart_tach, S_IWUSR | S_IRUGO, - show_fan_smart_tach, store_fan_smart_tach, 3); +static SENSOR_DEVICE_ATTR_RW(fan1_smart_tach, fan_smart_tach, 0); +static SENSOR_DEVICE_ATTR_RW(fan2_smart_tach, fan_smart_tach, 1); +static SENSOR_DEVICE_ATTR_RW(fan3_smart_tach, fan_smart_tach, 2); +static SENSOR_DEVICE_ATTR_RW(fan4_smart_tach, fan_smart_tach, 3); -static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, +static ssize_t pwm_show(struct device *dev, struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; @@ -1876,8 +1775,8 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%ld\n", rc); } -static ssize_t store_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t pwm_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -1904,11 +1803,11 @@ static ssize_t store_pwm(struct device *dev, struct device_attribute *attr, return count; } -static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1); +static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0); +static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1); -static ssize_t show_pwm_enable(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pwm_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); @@ -1923,7 +1822,7 @@ static ssize_t show_pwm_enable(struct device *dev, return sprintf(buf, "%ld\n", rc); } -static ssize_t store_pwm_enable(struct device *dev, +static ssize_t pwm_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -1961,13 +1860,11 @@ static ssize_t store_pwm_enable(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, - show_pwm_enable, store_pwm_enable, 0); -static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, - show_pwm_enable, store_pwm_enable, 1); +static SENSOR_DEVICE_ATTR_RW(pwm1_enable, pwm_enable, 0); +static SENSOR_DEVICE_ATTR_RW(pwm2_enable, pwm_enable, 1); -static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t pwm_freq_show(struct device *dev, + struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); @@ -2001,9 +1898,9 @@ static void lm93_disable_fan_smart_tach(struct i2c_client *client, lm93_write_byte(client, LM93_REG_SFC2, data->sfc2); } -static ssize_t store_pwm_freq(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t pwm_freq_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -2028,22 +1925,21 @@ static ssize_t store_pwm_freq(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(pwm1_freq, S_IWUSR | S_IRUGO, - show_pwm_freq, store_pwm_freq, 0); -static SENSOR_DEVICE_ATTR(pwm2_freq, S_IWUSR | S_IRUGO, - show_pwm_freq, store_pwm_freq, 1); +static SENSOR_DEVICE_ATTR_RW(pwm1_freq, pwm_freq, 0); +static SENSOR_DEVICE_ATTR_RW(pwm2_freq, pwm_freq, 1); -static ssize_t show_pwm_auto_channels(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pwm_auto_channels_show(struct device *dev, + struct device_attribute *attr, + char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); return sprintf(buf, "%d\n", data->block9[nr][LM93_PWM_CTL1]); } -static ssize_t store_pwm_auto_channels(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t pwm_auto_channels_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -2063,13 +1959,12 @@ static ssize_t store_pwm_auto_channels(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(pwm1_auto_channels, S_IWUSR | S_IRUGO, - show_pwm_auto_channels, store_pwm_auto_channels, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_channels, S_IWUSR | S_IRUGO, - show_pwm_auto_channels, store_pwm_auto_channels, 1); +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_channels, pwm_auto_channels, 0); +static SENSOR_DEVICE_ATTR_RW(pwm2_auto_channels, pwm_auto_channels, 1); -static ssize_t show_pwm_auto_spinup_min(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pwm_auto_spinup_min_show(struct device *dev, + struct device_attribute *attr, + char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); @@ -2082,9 +1977,9 @@ static ssize_t show_pwm_auto_spinup_min(struct device *dev, LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ)); } -static ssize_t store_pwm_auto_spinup_min(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t pwm_auto_spinup_min_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -2109,15 +2004,12 @@ static ssize_t store_pwm_auto_spinup_min(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(pwm1_auto_spinup_min, S_IWUSR | S_IRUGO, - show_pwm_auto_spinup_min, - store_pwm_auto_spinup_min, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_spinup_min, S_IWUSR | S_IRUGO, - show_pwm_auto_spinup_min, - store_pwm_auto_spinup_min, 1); +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_spinup_min, pwm_auto_spinup_min, 0); +static SENSOR_DEVICE_ATTR_RW(pwm2_auto_spinup_min, pwm_auto_spinup_min, 1); -static ssize_t show_pwm_auto_spinup_time(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pwm_auto_spinup_time_show(struct device *dev, + struct device_attribute *attr, + char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); @@ -2125,9 +2017,9 @@ static ssize_t show_pwm_auto_spinup_time(struct device *dev, data->block9[nr][LM93_PWM_CTL3])); } -static ssize_t store_pwm_auto_spinup_time(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t pwm_auto_spinup_time_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -2149,12 +2041,8 @@ static ssize_t store_pwm_auto_spinup_time(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(pwm1_auto_spinup_time, S_IWUSR | S_IRUGO, - show_pwm_auto_spinup_time, - store_pwm_auto_spinup_time, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_spinup_time, S_IWUSR | S_IRUGO, - show_pwm_auto_spinup_time, - store_pwm_auto_spinup_time, 1); +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_spinup_time, pwm_auto_spinup_time, 0); +static SENSOR_DEVICE_ATTR_RW(pwm2_auto_spinup_time, pwm_auto_spinup_time, 1); static ssize_t pwm_auto_prochot_ramp_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -2220,7 +2108,7 @@ static ssize_t pwm_auto_vrdhot_ramp_store(struct device *dev, static DEVICE_ATTR_RW(pwm_auto_vrdhot_ramp); -static ssize_t show_vid(struct device *dev, struct device_attribute *attr, +static ssize_t vid_show(struct device *dev, struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; @@ -2228,21 +2116,21 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", LM93_VID_FROM_REG(data->vid[nr])); } -static SENSOR_DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL, 0); -static SENSOR_DEVICE_ATTR(cpu1_vid, S_IRUGO, show_vid, NULL, 1); +static SENSOR_DEVICE_ATTR_RO(cpu0_vid, vid, 0); +static SENSOR_DEVICE_ATTR_RO(cpu1_vid, vid, 1); -static ssize_t show_prochot(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t prochot_show(struct device *dev, struct device_attribute *attr, + char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); return sprintf(buf, "%d\n", data->block4[nr].cur); } -static SENSOR_DEVICE_ATTR(prochot1, S_IRUGO, show_prochot, NULL, 0); -static SENSOR_DEVICE_ATTR(prochot2, S_IRUGO, show_prochot, NULL, 1); +static SENSOR_DEVICE_ATTR_RO(prochot1, prochot, 0); +static SENSOR_DEVICE_ATTR_RO(prochot2, prochot, 1); -static ssize_t show_prochot_avg(struct device *dev, +static ssize_t prochot_avg_show(struct device *dev, struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; @@ -2250,10 +2138,10 @@ static ssize_t show_prochot_avg(struct device *dev, return sprintf(buf, "%d\n", data->block4[nr].avg); } -static SENSOR_DEVICE_ATTR(prochot1_avg, S_IRUGO, show_prochot_avg, NULL, 0); -static SENSOR_DEVICE_ATTR(prochot2_avg, S_IRUGO, show_prochot_avg, NULL, 1); +static SENSOR_DEVICE_ATTR_RO(prochot1_avg, prochot_avg, 0); +static SENSOR_DEVICE_ATTR_RO(prochot2_avg, prochot_avg, 1); -static ssize_t show_prochot_max(struct device *dev, +static ssize_t prochot_max_show(struct device *dev, struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; @@ -2261,9 +2149,9 @@ static ssize_t show_prochot_max(struct device *dev, return sprintf(buf, "%d\n", data->prochot_max[nr]); } -static ssize_t store_prochot_max(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t prochot_max_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -2283,15 +2171,13 @@ static ssize_t store_prochot_max(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(prochot1_max, S_IWUSR | S_IRUGO, - show_prochot_max, store_prochot_max, 0); -static SENSOR_DEVICE_ATTR(prochot2_max, S_IWUSR | S_IRUGO, - show_prochot_max, store_prochot_max, 1); +static SENSOR_DEVICE_ATTR_RW(prochot1_max, prochot_max, 0); +static SENSOR_DEVICE_ATTR_RW(prochot2_max, prochot_max, 1); static const u8 prochot_override_mask[] = { 0x80, 0x40 }; -static ssize_t show_prochot_override(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t prochot_override_show(struct device *dev, + struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); @@ -2299,9 +2185,9 @@ static ssize_t show_prochot_override(struct device *dev, (data->prochot_override & prochot_override_mask[nr]) ? 1 : 0); } -static ssize_t store_prochot_override(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t prochot_override_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -2324,13 +2210,11 @@ static ssize_t store_prochot_override(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(prochot1_override, S_IWUSR | S_IRUGO, - show_prochot_override, store_prochot_override, 0); -static SENSOR_DEVICE_ATTR(prochot2_override, S_IWUSR | S_IRUGO, - show_prochot_override, store_prochot_override, 1); +static SENSOR_DEVICE_ATTR_RW(prochot1_override, prochot_override, 0); +static SENSOR_DEVICE_ATTR_RW(prochot2_override, prochot_override, 1); -static ssize_t show_prochot_interval(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t prochot_interval_show(struct device *dev, + struct device_attribute *attr, char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); @@ -2342,9 +2226,9 @@ static ssize_t show_prochot_interval(struct device *dev, return sprintf(buf, "%d\n", LM93_INTERVAL_FROM_REG(tmp)); } -static ssize_t store_prochot_interval(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t prochot_interval_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = dev_get_drvdata(dev); @@ -2369,10 +2253,8 @@ static ssize_t store_prochot_interval(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(prochot1_interval, S_IWUSR | S_IRUGO, - show_prochot_interval, store_prochot_interval, 0); -static SENSOR_DEVICE_ATTR(prochot2_interval, S_IWUSR | S_IRUGO, - show_prochot_interval, store_prochot_interval, 1); +static SENSOR_DEVICE_ATTR_RW(prochot1_interval, prochot_interval, 0); +static SENSOR_DEVICE_ATTR_RW(prochot2_interval, prochot_interval, 1); static ssize_t prochot_override_duty_cycle_show(struct device *dev, struct device_attribute *attr, @@ -2438,8 +2320,8 @@ static ssize_t prochot_short_store(struct device *dev, static DEVICE_ATTR_RW(prochot_short); -static ssize_t show_vrdhot(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t vrdhot_show(struct device *dev, struct device_attribute *attr, + char *buf) { int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); @@ -2447,8 +2329,8 @@ static ssize_t show_vrdhot(struct device *dev, struct device_attribute *attr, data->block1.host_status_1 & (1 << (nr + 4)) ? 1 : 0); } -static SENSOR_DEVICE_ATTR(vrdhot1, S_IRUGO, show_vrdhot, NULL, 0); -static SENSOR_DEVICE_ATTR(vrdhot2, S_IRUGO, show_vrdhot, NULL, 1); +static SENSOR_DEVICE_ATTR_RO(vrdhot1, vrdhot, 0); +static SENSOR_DEVICE_ATTR_RO(vrdhot2, vrdhot, 1); static ssize_t gpio_show(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 8c573e6e9726..3ff188937158 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -349,19 +349,19 @@ static umode_t lm95241_is_visible(const void *data, case hwmon_chip: switch (attr) { case hwmon_chip_update_interval: - return S_IRUGO | S_IWUSR; + return 0644; } break; case hwmon_temp: switch (attr) { case hwmon_temp_input: - return S_IRUGO; + return 0444; case hwmon_temp_fault: - return S_IRUGO; + return 0444; case hwmon_temp_min: case hwmon_temp_max: case hwmon_temp_type: - return S_IRUGO | S_IWUSR; + return 0644; } break; default: diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c index 996b50246175..e4cac3a04536 100644 --- a/drivers/hwmon/lm95245.c +++ b/drivers/hwmon/lm95245.c @@ -421,14 +421,14 @@ static umode_t lm95245_temp_is_visible(const void *data, u32 attr, int channel) case hwmon_temp_max_hyst: case hwmon_temp_crit_alarm: case hwmon_temp_fault: - return S_IRUGO; + return 0444; case hwmon_temp_type: case hwmon_temp_max: case hwmon_temp_crit: case hwmon_temp_offset: - return S_IRUGO | S_IWUSR; + return 0644; case hwmon_temp_crit_hyst: - return (channel == 0) ? S_IRUGO | S_IWUSR : S_IRUGO; + return (channel == 0) ? 0644 : 0444; default: return 0; } @@ -442,7 +442,7 @@ static umode_t lm95245_is_visible(const void *data, case hwmon_chip: switch (attr) { case hwmon_chip_update_interval: - return S_IRUGO | S_IWUSR; + return 0644; default: return 0; } diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c index 2aefdc58b242..be4e89645c0b 100644 --- a/drivers/hwmon/ltc2990.c +++ b/drivers/hwmon/ltc2990.c @@ -136,7 +136,7 @@ static int ltc2990_get_value(struct i2c_client *i2c, int index, int *result) return 0; } -static ssize_t ltc2990_show_value(struct device *dev, +static ssize_t ltc2990_value_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); @@ -170,26 +170,16 @@ static umode_t ltc2990_attrs_visible(struct kobject *kobj, return 0; } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ltc2990_show_value, NULL, - LTC2990_TEMP1); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, ltc2990_show_value, NULL, - LTC2990_TEMP2); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, ltc2990_show_value, NULL, - LTC2990_TEMP3); -static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc2990_show_value, NULL, - LTC2990_CURR1); -static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc2990_show_value, NULL, - LTC2990_CURR2); -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ltc2990_show_value, NULL, - LTC2990_IN0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc2990_show_value, NULL, - LTC2990_IN1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc2990_show_value, NULL, - LTC2990_IN2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ltc2990_show_value, NULL, - LTC2990_IN3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ltc2990_show_value, NULL, - LTC2990_IN4); +static SENSOR_DEVICE_ATTR_RO(temp1_input, ltc2990_value, LTC2990_TEMP1); +static SENSOR_DEVICE_ATTR_RO(temp2_input, ltc2990_value, LTC2990_TEMP2); +static SENSOR_DEVICE_ATTR_RO(temp3_input, ltc2990_value, LTC2990_TEMP3); +static SENSOR_DEVICE_ATTR_RO(curr1_input, ltc2990_value, LTC2990_CURR1); +static SENSOR_DEVICE_ATTR_RO(curr2_input, ltc2990_value, LTC2990_CURR2); +static SENSOR_DEVICE_ATTR_RO(in0_input, ltc2990_value, LTC2990_IN0); +static SENSOR_DEVICE_ATTR_RO(in1_input, ltc2990_value, LTC2990_IN1); +static SENSOR_DEVICE_ATTR_RO(in2_input, ltc2990_value, LTC2990_IN2); +static SENSOR_DEVICE_ATTR_RO(in3_input, ltc2990_value, LTC2990_IN3); +static SENSOR_DEVICE_ATTR_RO(in4_input, ltc2990_value, LTC2990_IN4); static struct attribute *ltc2990_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c index b904cb547ffb..76c6fda76d95 100644 --- a/drivers/hwmon/ltc4151.c +++ b/drivers/hwmon/ltc4151.c @@ -131,7 +131,7 @@ static int ltc4151_get_value(struct ltc4151_data *data, u8 reg) return val; } -static ssize_t ltc4151_show_value(struct device *dev, +static ssize_t ltc4151_value_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); @@ -148,14 +148,11 @@ static ssize_t ltc4151_show_value(struct device *dev, /* * Input voltages. */ -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4151_show_value, NULL, - LTC4151_VIN_H); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4151_show_value, NULL, - LTC4151_ADIN_H); +static SENSOR_DEVICE_ATTR_RO(in1_input, ltc4151_value, LTC4151_VIN_H); +static SENSOR_DEVICE_ATTR_RO(in2_input, ltc4151_value, LTC4151_ADIN_H); /* Currents (via sense resistor) */ -static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4151_show_value, NULL, - LTC4151_SENSE_H); +static SENSOR_DEVICE_ATTR_RO(curr1_input, ltc4151_value, LTC4151_SENSE_H); /* * Finally, construct an array of pointers to members of the above objects, diff --git a/drivers/hwmon/ltc4222.c b/drivers/hwmon/ltc4222.c index 88f747292816..32248f351a6e 100644 --- a/drivers/hwmon/ltc4222.c +++ b/drivers/hwmon/ltc4222.c @@ -94,7 +94,7 @@ static int ltc4222_get_value(struct device *dev, u8 reg) return val; } -static ssize_t ltc4222_show_value(struct device *dev, +static ssize_t ltc4222_value_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); @@ -106,7 +106,7 @@ static ssize_t ltc4222_show_value(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", value); } -static ssize_t ltc4222_show_bool(struct device *dev, +static ssize_t ltc4222_bool_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da); @@ -125,45 +125,39 @@ static ssize_t ltc4222_show_bool(struct device *dev, } /* Voltages */ -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4222_show_value, NULL, - LTC4222_SOURCE1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4222_show_value, NULL, - LTC4222_ADIN1); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ltc4222_show_value, NULL, - LTC4222_SOURCE2); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ltc4222_show_value, NULL, - LTC4222_ADIN2); +static SENSOR_DEVICE_ATTR_RO(in1_input, ltc4222_value, LTC4222_SOURCE1); +static SENSOR_DEVICE_ATTR_RO(in2_input, ltc4222_value, LTC4222_ADIN1); +static SENSOR_DEVICE_ATTR_RO(in3_input, ltc4222_value, LTC4222_SOURCE2); +static SENSOR_DEVICE_ATTR_RO(in4_input, ltc4222_value, LTC4222_ADIN2); /* * Voltage alarms * UV/OV faults are associated with the input voltage, and power bad and fet * faults are associated with the output voltage. */ -static SENSOR_DEVICE_ATTR_2(in1_min_alarm, S_IRUGO, ltc4222_show_bool, NULL, - LTC4222_FAULT1, FAULT_UV); -static SENSOR_DEVICE_ATTR_2(in1_max_alarm, S_IRUGO, ltc4222_show_bool, NULL, - LTC4222_FAULT1, FAULT_OV); -static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, ltc4222_show_bool, NULL, - LTC4222_FAULT1, FAULT_POWER_BAD | FAULT_FET_BAD); - -static SENSOR_DEVICE_ATTR_2(in3_min_alarm, S_IRUGO, ltc4222_show_bool, NULL, - LTC4222_FAULT2, FAULT_UV); -static SENSOR_DEVICE_ATTR_2(in3_max_alarm, S_IRUGO, ltc4222_show_bool, NULL, - LTC4222_FAULT2, FAULT_OV); -static SENSOR_DEVICE_ATTR_2(in4_alarm, S_IRUGO, ltc4222_show_bool, NULL, - LTC4222_FAULT2, FAULT_POWER_BAD | FAULT_FET_BAD); +static SENSOR_DEVICE_ATTR_2_RO(in1_min_alarm, ltc4222_bool, LTC4222_FAULT1, + FAULT_UV); +static SENSOR_DEVICE_ATTR_2_RO(in1_max_alarm, ltc4222_bool, LTC4222_FAULT1, + FAULT_OV); +static SENSOR_DEVICE_ATTR_2_RO(in2_alarm, ltc4222_bool, LTC4222_FAULT1, + FAULT_POWER_BAD | FAULT_FET_BAD); + +static SENSOR_DEVICE_ATTR_2_RO(in3_min_alarm, ltc4222_bool, LTC4222_FAULT2, + FAULT_UV); +static SENSOR_DEVICE_ATTR_2_RO(in3_max_alarm, ltc4222_bool, LTC4222_FAULT2, + FAULT_OV); +static SENSOR_DEVICE_ATTR_2_RO(in4_alarm, ltc4222_bool, LTC4222_FAULT2, + FAULT_POWER_BAD | FAULT_FET_BAD); /* Current (via sense resistor) */ -static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4222_show_value, NULL, - LTC4222_SENSE1); -static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc4222_show_value, NULL, - LTC4222_SENSE2); +static SENSOR_DEVICE_ATTR_RO(curr1_input, ltc4222_value, LTC4222_SENSE1); +static SENSOR_DEVICE_ATTR_RO(curr2_input, ltc4222_value, LTC4222_SENSE2); /* Overcurrent alarm */ -static SENSOR_DEVICE_ATTR_2(curr1_max_alarm, S_IRUGO, ltc4222_show_bool, NULL, - LTC4222_FAULT1, FAULT_OC); -static SENSOR_DEVICE_ATTR_2(curr2_max_alarm, S_IRUGO, ltc4222_show_bool, NULL, - LTC4222_FAULT2, FAULT_OC); +static SENSOR_DEVICE_ATTR_2_RO(curr1_max_alarm, ltc4222_bool, LTC4222_FAULT1, + FAULT_OC); +static SENSOR_DEVICE_ATTR_2_RO(curr2_max_alarm, ltc4222_bool, LTC4222_FAULT2, + FAULT_OC); static struct attribute *ltc4222_attrs[] = { &sensor_dev_attr_in1_input.dev_attr.attr, diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c index 082f0a0bd8a0..34d0653ca607 100644 --- a/drivers/hwmon/ltc4245.c +++ b/drivers/hwmon/ltc4245.c @@ -362,11 +362,11 @@ static umode_t ltc4245_is_visible(const void *_data, case hwmon_in_input: if (channel > 9 && !data->use_extra_gpios) return 0; - return S_IRUGO; + return 0444; case hwmon_in_min_alarm: if (channel > 8) return 0; - return S_IRUGO; + return 0444; default: return 0; } @@ -374,14 +374,14 @@ static umode_t ltc4245_is_visible(const void *_data, switch (attr) { case hwmon_curr_input: case hwmon_curr_max_alarm: - return S_IRUGO; + return 0444; default: return 0; } case hwmon_power: switch (attr) { case hwmon_power_input: - return S_IRUGO; + return 0444; default: return 0; } diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c index 0becd69842bb..6eb3415e0639 100644 --- a/drivers/hwmon/ltc4261.c +++ b/drivers/hwmon/ltc4261.c @@ -132,7 +132,7 @@ static int ltc4261_get_value(struct ltc4261_data *data, u8 reg) return val; } -static ssize_t ltc4261_show_value(struct device *dev, +static ssize_t ltc4261_value_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); @@ -146,7 +146,7 @@ static ssize_t ltc4261_show_value(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", value); } -static ssize_t ltc4261_show_bool(struct device *dev, +static ssize_t ltc4261_bool_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); @@ -166,10 +166,8 @@ static ssize_t ltc4261_show_bool(struct device *dev, /* * Input voltages. */ -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4261_show_value, NULL, - LTC4261_ADIN_H); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4261_show_value, NULL, - LTC4261_ADIN2_H); +static SENSOR_DEVICE_ATTR_RO(in1_input, ltc4261_value, LTC4261_ADIN_H); +static SENSOR_DEVICE_ATTR_RO(in2_input, ltc4261_value, LTC4261_ADIN2_H); /* * Voltage alarms. The chip has only one set of voltage alarm status bits, @@ -179,22 +177,16 @@ static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4261_show_value, NULL, * To ensure that the alarm condition is reported to the user, report it * with both voltage sensors. */ -static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ltc4261_show_bool, NULL, - FAULT_UV); -static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ltc4261_show_bool, NULL, - FAULT_OV); -static SENSOR_DEVICE_ATTR(in2_min_alarm, S_IRUGO, ltc4261_show_bool, NULL, - FAULT_UV); -static SENSOR_DEVICE_ATTR(in2_max_alarm, S_IRUGO, ltc4261_show_bool, NULL, - FAULT_OV); +static SENSOR_DEVICE_ATTR_RO(in1_min_alarm, ltc4261_bool, FAULT_UV); +static SENSOR_DEVICE_ATTR_RO(in1_max_alarm, ltc4261_bool, FAULT_OV); +static SENSOR_DEVICE_ATTR_RO(in2_min_alarm, ltc4261_bool, FAULT_UV); +static SENSOR_DEVICE_ATTR_RO(in2_max_alarm, ltc4261_bool, FAULT_OV); /* Currents (via sense resistor) */ -static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4261_show_value, NULL, - LTC4261_SENSE_H); +static SENSOR_DEVICE_ATTR_RO(curr1_input, ltc4261_value, LTC4261_SENSE_H); /* Overcurrent alarm */ -static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc4261_show_bool, NULL, - FAULT_OC); +static SENSOR_DEVICE_ATTR_RO(curr1_max_alarm, ltc4261_bool, FAULT_OC); static struct attribute *ltc4261_attrs[] = { &sensor_dev_attr_in1_input.dev_attr.attr, diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c index 162401aaef71..1c372f76cd0b 100644 --- a/drivers/hwmon/max16065.c +++ b/drivers/hwmon/max16065.c @@ -175,7 +175,7 @@ static struct max16065_data *max16065_update_device(struct device *dev) return data; } -static ssize_t max16065_show_alarm(struct device *dev, +static ssize_t max16065_alarm_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da); @@ -193,7 +193,7 @@ static ssize_t max16065_show_alarm(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", !!val); } -static ssize_t max16065_show_input(struct device *dev, +static ssize_t max16065_input_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); @@ -207,7 +207,7 @@ static ssize_t max16065_show_input(struct device *dev, ADC_TO_MV(adc, data->range[attr->index])); } -static ssize_t max16065_show_current(struct device *dev, +static ssize_t max16065_current_show(struct device *dev, struct device_attribute *da, char *buf) { struct max16065_data *data = max16065_update_device(dev); @@ -219,9 +219,9 @@ static ssize_t max16065_show_current(struct device *dev, ADC_TO_CURR(data->curr_sense, data->curr_gain)); } -static ssize_t max16065_set_limit(struct device *dev, - struct device_attribute *da, - const char *buf, size_t count) +static ssize_t max16065_limit_store(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) { struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da); struct max16065_data *data = dev_get_drvdata(dev); @@ -246,7 +246,7 @@ static ssize_t max16065_set_limit(struct device *dev, return count; } -static ssize_t max16065_show_limit(struct device *dev, +static ssize_t max16065_limit_show(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da); @@ -259,154 +259,93 @@ static ssize_t max16065_show_limit(struct device *dev, /* Construct a sensor_device_attribute structure for each register */ /* Input voltages */ -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, max16065_show_input, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, max16065_show_input, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, max16065_show_input, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, max16065_show_input, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, max16065_show_input, NULL, 4); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, max16065_show_input, NULL, 5); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, max16065_show_input, NULL, 6); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, max16065_show_input, NULL, 7); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, max16065_show_input, NULL, 8); -static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, max16065_show_input, NULL, 9); -static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, max16065_show_input, NULL, 10); -static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, max16065_show_input, NULL, 11); -static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, max16065_show_input, NULL, 12); +static SENSOR_DEVICE_ATTR_RO(in0_input, max16065_input, 0); +static SENSOR_DEVICE_ATTR_RO(in1_input, max16065_input, 1); +static SENSOR_DEVICE_ATTR_RO(in2_input, max16065_input, 2); +static SENSOR_DEVICE_ATTR_RO(in3_input, max16065_input, 3); +static SENSOR_DEVICE_ATTR_RO(in4_input, max16065_input, 4); +static SENSOR_DEVICE_ATTR_RO(in5_input, max16065_input, 5); +static SENSOR_DEVICE_ATTR_RO(in6_input, max16065_input, 6); +static SENSOR_DEVICE_ATTR_RO(in7_input, max16065_input, 7); +static SENSOR_DEVICE_ATTR_RO(in8_input, max16065_input, 8); +static SENSOR_DEVICE_ATTR_RO(in9_input, max16065_input, 9); +static SENSOR_DEVICE_ATTR_RO(in10_input, max16065_input, 10); +static SENSOR_DEVICE_ATTR_RO(in11_input, max16065_input, 11); +static SENSOR_DEVICE_ATTR_RO(in12_input, max16065_input, 12); /* Input voltages lcrit */ -static SENSOR_DEVICE_ATTR_2(in0_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 0); -static SENSOR_DEVICE_ATTR_2(in1_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 1); -static SENSOR_DEVICE_ATTR_2(in2_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 2); -static SENSOR_DEVICE_ATTR_2(in3_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 3); -static SENSOR_DEVICE_ATTR_2(in4_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 4); -static SENSOR_DEVICE_ATTR_2(in5_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 5); -static SENSOR_DEVICE_ATTR_2(in6_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 6); -static SENSOR_DEVICE_ATTR_2(in7_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 7); -static SENSOR_DEVICE_ATTR_2(in8_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 8); -static SENSOR_DEVICE_ATTR_2(in9_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 9); -static SENSOR_DEVICE_ATTR_2(in10_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 10); -static SENSOR_DEVICE_ATTR_2(in11_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 11); +static SENSOR_DEVICE_ATTR_2_RW(in0_lcrit, max16065_limit, 2, 0); +static SENSOR_DEVICE_ATTR_2_RW(in1_lcrit, max16065_limit, 2, 1); +static SENSOR_DEVICE_ATTR_2_RW(in2_lcrit, max16065_limit, 2, 2); +static SENSOR_DEVICE_ATTR_2_RW(in3_lcrit, max16065_limit, 2, 3); +static SENSOR_DEVICE_ATTR_2_RW(in4_lcrit, max16065_limit, 2, 4); +static SENSOR_DEVICE_ATTR_2_RW(in5_lcrit, max16065_limit, 2, 5); +static SENSOR_DEVICE_ATTR_2_RW(in6_lcrit, max16065_limit, 2, 6); +static SENSOR_DEVICE_ATTR_2_RW(in7_lcrit, max16065_limit, 2, 7); +static SENSOR_DEVICE_ATTR_2_RW(in8_lcrit, max16065_limit, 2, 8); +static SENSOR_DEVICE_ATTR_2_RW(in9_lcrit, max16065_limit, 2, 9); +static SENSOR_DEVICE_ATTR_2_RW(in10_lcrit, max16065_limit, 2, 10); +static SENSOR_DEVICE_ATTR_2_RW(in11_lcrit, max16065_limit, 2, 11); /* Input voltages crit */ -static SENSOR_DEVICE_ATTR_2(in0_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 0); -static SENSOR_DEVICE_ATTR_2(in1_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 1); -static SENSOR_DEVICE_ATTR_2(in2_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 2); -static SENSOR_DEVICE_ATTR_2(in3_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 3); -static SENSOR_DEVICE_ATTR_2(in4_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 4); -static SENSOR_DEVICE_ATTR_2(in5_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 5); -static SENSOR_DEVICE_ATTR_2(in6_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 6); -static SENSOR_DEVICE_ATTR_2(in7_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 7); -static SENSOR_DEVICE_ATTR_2(in8_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 8); -static SENSOR_DEVICE_ATTR_2(in9_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 9); -static SENSOR_DEVICE_ATTR_2(in10_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 10); -static SENSOR_DEVICE_ATTR_2(in11_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 11); +static SENSOR_DEVICE_ATTR_2_RW(in0_crit, max16065_limit, 1, 0); +static SENSOR_DEVICE_ATTR_2_RW(in1_crit, max16065_limit, 1, 1); +static SENSOR_DEVICE_ATTR_2_RW(in2_crit, max16065_limit, 1, 2); +static SENSOR_DEVICE_ATTR_2_RW(in3_crit, max16065_limit, 1, 3); +static SENSOR_DEVICE_ATTR_2_RW(in4_crit, max16065_limit, 1, 4); +static SENSOR_DEVICE_ATTR_2_RW(in5_crit, max16065_limit, 1, 5); +static SENSOR_DEVICE_ATTR_2_RW(in6_crit, max16065_limit, 1, 6); +static SENSOR_DEVICE_ATTR_2_RW(in7_crit, max16065_limit, 1, 7); +static SENSOR_DEVICE_ATTR_2_RW(in8_crit, max16065_limit, 1, 8); +static SENSOR_DEVICE_ATTR_2_RW(in9_crit, max16065_limit, 1, 9); +static SENSOR_DEVICE_ATTR_2_RW(in10_crit, max16065_limit, 1, 10); +static SENSOR_DEVICE_ATTR_2_RW(in11_crit, max16065_limit, 1, 11); /* Input voltages min */ -static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 0); -static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 1); -static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 2); -static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 3); -static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 4); -static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 5); -static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 6); -static SENSOR_DEVICE_ATTR_2(in7_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 7); -static SENSOR_DEVICE_ATTR_2(in8_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 8); -static SENSOR_DEVICE_ATTR_2(in9_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 9); -static SENSOR_DEVICE_ATTR_2(in10_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 10); -static SENSOR_DEVICE_ATTR_2(in11_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 11); +static SENSOR_DEVICE_ATTR_2_RW(in0_min, max16065_limit, 0, 0); +static SENSOR_DEVICE_ATTR_2_RW(in1_min, max16065_limit, 0, 1); +static SENSOR_DEVICE_ATTR_2_RW(in2_min, max16065_limit, 0, 2); +static SENSOR_DEVICE_ATTR_2_RW(in3_min, max16065_limit, 0, 3); +static SENSOR_DEVICE_ATTR_2_RW(in4_min, max16065_limit, 0, 4); +static SENSOR_DEVICE_ATTR_2_RW(in5_min, max16065_limit, 0, 5); +static SENSOR_DEVICE_ATTR_2_RW(in6_min, max16065_limit, 0, 6); +static SENSOR_DEVICE_ATTR_2_RW(in7_min, max16065_limit, 0, 7); +static SENSOR_DEVICE_ATTR_2_RW(in8_min, max16065_limit, 0, 8); +static SENSOR_DEVICE_ATTR_2_RW(in9_min, max16065_limit, 0, 9); +static SENSOR_DEVICE_ATTR_2_RW(in10_min, max16065_limit, 0, 10); +static SENSOR_DEVICE_ATTR_2_RW(in11_min, max16065_limit, 0, 11); /* Input voltages max */ -static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 0); -static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 1); -static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 2); -static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 3); -static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 4); -static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 5); -static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 6); -static SENSOR_DEVICE_ATTR_2(in7_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 7); -static SENSOR_DEVICE_ATTR_2(in8_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 8); -static SENSOR_DEVICE_ATTR_2(in9_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 9); -static SENSOR_DEVICE_ATTR_2(in10_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 10); -static SENSOR_DEVICE_ATTR_2(in11_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 11); +static SENSOR_DEVICE_ATTR_2_RW(in0_max, max16065_limit, 0, 0); +static SENSOR_DEVICE_ATTR_2_RW(in1_max, max16065_limit, 0, 1); +static SENSOR_DEVICE_ATTR_2_RW(in2_max, max16065_limit, 0, 2); +static SENSOR_DEVICE_ATTR_2_RW(in3_max, max16065_limit, 0, 3); +static SENSOR_DEVICE_ATTR_2_RW(in4_max, max16065_limit, 0, 4); +static SENSOR_DEVICE_ATTR_2_RW(in5_max, max16065_limit, 0, 5); +static SENSOR_DEVICE_ATTR_2_RW(in6_max, max16065_limit, 0, 6); +static SENSOR_DEVICE_ATTR_2_RW(in7_max, max16065_limit, 0, 7); +static SENSOR_DEVICE_ATTR_2_RW(in8_max, max16065_limit, 0, 8); +static SENSOR_DEVICE_ATTR_2_RW(in9_max, max16065_limit, 0, 9); +static SENSOR_DEVICE_ATTR_2_RW(in10_max, max16065_limit, 0, 10); +static SENSOR_DEVICE_ATTR_2_RW(in11_max, max16065_limit, 0, 11); /* alarms */ -static SENSOR_DEVICE_ATTR_2(in0_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 0); -static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 1); -static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 2); -static SENSOR_DEVICE_ATTR_2(in3_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 3); -static SENSOR_DEVICE_ATTR_2(in4_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 4); -static SENSOR_DEVICE_ATTR_2(in5_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 5); -static SENSOR_DEVICE_ATTR_2(in6_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 6); -static SENSOR_DEVICE_ATTR_2(in7_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 7); -static SENSOR_DEVICE_ATTR_2(in8_alarm, S_IRUGO, max16065_show_alarm, NULL, - 1, 0); -static SENSOR_DEVICE_ATTR_2(in9_alarm, S_IRUGO, max16065_show_alarm, NULL, - 1, 1); -static SENSOR_DEVICE_ATTR_2(in10_alarm, S_IRUGO, max16065_show_alarm, NULL, - 1, 2); -static SENSOR_DEVICE_ATTR_2(in11_alarm, S_IRUGO, max16065_show_alarm, NULL, - 1, 3); +static SENSOR_DEVICE_ATTR_2_RO(in0_alarm, max16065_alarm, 0, 0); +static SENSOR_DEVICE_ATTR_2_RO(in1_alarm, max16065_alarm, 0, 1); +static SENSOR_DEVICE_ATTR_2_RO(in2_alarm, max16065_alarm, 0, 2); +static SENSOR_DEVICE_ATTR_2_RO(in3_alarm, max16065_alarm, 0, 3); +static SENSOR_DEVICE_ATTR_2_RO(in4_alarm, max16065_alarm, 0, 4); +static SENSOR_DEVICE_ATTR_2_RO(in5_alarm, max16065_alarm, 0, 5); +static SENSOR_DEVICE_ATTR_2_RO(in6_alarm, max16065_alarm, 0, 6); +static SENSOR_DEVICE_ATTR_2_RO(in7_alarm, max16065_alarm, 0, 7); +static SENSOR_DEVICE_ATTR_2_RO(in8_alarm, max16065_alarm, 1, 0); +static SENSOR_DEVICE_ATTR_2_RO(in9_alarm, max16065_alarm, 1, 1); +static SENSOR_DEVICE_ATTR_2_RO(in10_alarm, max16065_alarm, 1, 2); +static SENSOR_DEVICE_ATTR_2_RO(in11_alarm, max16065_alarm, 1, 3); /* Current and alarm */ -static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, max16065_show_current, NULL, 0); -static SENSOR_DEVICE_ATTR_2(curr1_alarm, S_IRUGO, max16065_show_alarm, NULL, - 1, 4); +static SENSOR_DEVICE_ATTR_RO(curr1_input, max16065_current, 0); +static SENSOR_DEVICE_ATTR_2_RO(curr1_alarm, max16065_alarm, 1, 4); /* * Finally, construct an array of pointers to members of the above objects, diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c index 76d966932941..94e345fb2a78 100644 --- a/drivers/hwmon/max1619.c +++ b/drivers/hwmon/max1619.c @@ -145,7 +145,7 @@ static struct max1619_data *max1619_update_device(struct device *dev) * Sysfs stuff */ -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, +static ssize_t temp_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -154,8 +154,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, return sprintf(buf, "%d\n", temp_from_reg(data->temp[attr->index])); } -static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t temp_store(struct device *dev, + struct device_attribute *devattr, const char *buf, + size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct max1619_data *data = dev_get_drvdata(dev); @@ -180,7 +181,7 @@ static ssize_t alarms_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", data->alarms); } -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, +static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, char *buf) { int bitnr = to_sensor_dev_attr(attr)->index; @@ -188,22 +189,18 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, t_input1); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, t_input2); -static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp, set_temp, - t_low2); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp, set_temp, - t_high2); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp, set_temp, - t_crit2); -static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp, - set_temp, t_hyst2); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, t_input1); +static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, t_input2); +static SENSOR_DEVICE_ATTR_RW(temp2_min, temp, t_low2); +static SENSOR_DEVICE_ATTR_RW(temp2_max, temp, t_high2); +static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp, t_crit2); +static SENSOR_DEVICE_ATTR_RW(temp2_crit_hyst, temp, t_hyst2); static DEVICE_ATTR_RO(alarms); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 1); +static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 2); +static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, alarm, 3); +static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 4); static struct attribute *max1619_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, diff --git a/drivers/hwmon/max31722.c b/drivers/hwmon/max31722.c index 30a100e70a0d..6d169b4271f7 100644 --- a/drivers/hwmon/max31722.c +++ b/drivers/hwmon/max31722.c @@ -50,9 +50,8 @@ static int max31722_set_mode(struct max31722_data *data, u8 mode) return 0; } -static ssize_t max31722_show_temp(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t max31722_temp_show(struct device *dev, + struct device_attribute *attr, char *buf) { ssize_t ret; struct max31722_data *data = dev_get_drvdata(dev); @@ -64,8 +63,7 @@ static ssize_t max31722_show_temp(struct device *dev, return sprintf(buf, "%d\n", (s16)le16_to_cpu(ret) * 125 / 32); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, - max31722_show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_input, max31722_temp, 0); static struct attribute *max31722_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index 281491cca510..722bcbb9865a 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -252,12 +252,12 @@ static umode_t max31790_fan_is_visible(const void *_data, u32 attr, int channel) case hwmon_fan_fault: if (channel < NR_CHANNEL || (fan_config & MAX31790_FAN_CFG_TACH_INPUT)) - return S_IRUGO; + return 0444; return 0; case hwmon_fan_target: if (channel < NR_CHANNEL && !(fan_config & MAX31790_FAN_CFG_TACH_INPUT)) - return S_IRUGO | S_IWUSR; + return 0644; return 0; default: return 0; @@ -353,7 +353,7 @@ static umode_t max31790_pwm_is_visible(const void *_data, u32 attr, int channel) case hwmon_pwm_input: case hwmon_pwm_enable: if (!(fan_config & MAX31790_FAN_CFG_TACH_INPUT)) - return S_IRUGO | S_IWUSR; + return 0644; return 0; default: return 0; diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c index f98a83c79ff1..fc3ed518f478 100644 --- a/drivers/hwmon/max6639.c +++ b/drivers/hwmon/max6639.c @@ -162,7 +162,7 @@ abort: return ret; } -static ssize_t show_temp_input(struct device *dev, +static ssize_t temp_input_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { long temp; @@ -176,7 +176,7 @@ static ssize_t show_temp_input(struct device *dev, return sprintf(buf, "%ld\n", temp); } -static ssize_t show_temp_fault(struct device *dev, +static ssize_t temp_fault_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct max6639_data *data = max6639_update_device(dev); @@ -188,7 +188,7 @@ static ssize_t show_temp_fault(struct device *dev, return sprintf(buf, "%d\n", data->temp_fault[attr->index]); } -static ssize_t show_temp_max(struct device *dev, +static ssize_t temp_max_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); @@ -197,9 +197,9 @@ static ssize_t show_temp_max(struct device *dev, return sprintf(buf, "%d\n", (data->temp_therm[attr->index] * 1000)); } -static ssize_t set_temp_max(struct device *dev, - struct device_attribute *dev_attr, - const char *buf, size_t count) +static ssize_t temp_max_store(struct device *dev, + struct device_attribute *dev_attr, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); @@ -220,7 +220,7 @@ static ssize_t set_temp_max(struct device *dev, return count; } -static ssize_t show_temp_crit(struct device *dev, +static ssize_t temp_crit_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); @@ -229,9 +229,9 @@ static ssize_t show_temp_crit(struct device *dev, return sprintf(buf, "%d\n", (data->temp_alert[attr->index] * 1000)); } -static ssize_t set_temp_crit(struct device *dev, - struct device_attribute *dev_attr, - const char *buf, size_t count) +static ssize_t temp_crit_store(struct device *dev, + struct device_attribute *dev_attr, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); @@ -252,7 +252,7 @@ static ssize_t set_temp_crit(struct device *dev, return count; } -static ssize_t show_temp_emergency(struct device *dev, +static ssize_t temp_emergency_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { @@ -262,9 +262,9 @@ static ssize_t show_temp_emergency(struct device *dev, return sprintf(buf, "%d\n", (data->temp_ot[attr->index] * 1000)); } -static ssize_t set_temp_emergency(struct device *dev, - struct device_attribute *dev_attr, - const char *buf, size_t count) +static ssize_t temp_emergency_store(struct device *dev, + struct device_attribute *dev_attr, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); @@ -285,8 +285,8 @@ static ssize_t set_temp_emergency(struct device *dev, return count; } -static ssize_t show_pwm(struct device *dev, - struct device_attribute *dev_attr, char *buf) +static ssize_t pwm_show(struct device *dev, struct device_attribute *dev_attr, + char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); @@ -294,9 +294,9 @@ static ssize_t show_pwm(struct device *dev, return sprintf(buf, "%d\n", data->pwm[attr->index] * 255 / 120); } -static ssize_t set_pwm(struct device *dev, - struct device_attribute *dev_attr, - const char *buf, size_t count) +static ssize_t pwm_store(struct device *dev, + struct device_attribute *dev_attr, const char *buf, + size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); @@ -319,7 +319,7 @@ static ssize_t set_pwm(struct device *dev, return count; } -static ssize_t show_fan_input(struct device *dev, +static ssize_t fan_input_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct max6639_data *data = max6639_update_device(dev); @@ -332,7 +332,7 @@ static ssize_t show_fan_input(struct device *dev, data->rpm_range)); } -static ssize_t show_alarm(struct device *dev, +static ssize_t alarm_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct max6639_data *data = max6639_update_device(dev); @@ -344,34 +344,28 @@ static ssize_t show_alarm(struct device *dev, return sprintf(buf, "%d\n", !!(data->status & (1 << attr->index))); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 1); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit, - set_temp_crit, 0); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit, - set_temp_crit, 1); -static SENSOR_DEVICE_ATTR(temp1_emergency, S_IWUSR | S_IRUGO, - show_temp_emergency, set_temp_emergency, 0); -static SENSOR_DEVICE_ATTR(temp2_emergency, S_IWUSR | S_IRUGO, - show_temp_emergency, set_temp_emergency, 1); -static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); -static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp2_emergency_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_input, 1); +static SENSOR_DEVICE_ATTR_RO(temp1_fault, temp_fault, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_fault, temp_fault, 1); +static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1); +static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp_crit, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp_crit, 1); +static SENSOR_DEVICE_ATTR_RW(temp1_emergency, temp_emergency, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_emergency, temp_emergency, 1); +static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0); +static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1); +static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1); +static SENSOR_DEVICE_ATTR_RO(fan1_fault, alarm, 1); +static SENSOR_DEVICE_ATTR_RO(fan2_fault, alarm, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 3); +static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 2); +static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 7); +static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 6); +static SENSOR_DEVICE_ATTR_RO(temp1_emergency_alarm, alarm, 5); +static SENSOR_DEVICE_ATTR_RO(temp2_emergency_alarm, alarm, 4); static struct attribute *max6639_attrs[] = { diff --git a/drivers/hwmon/max6642.c b/drivers/hwmon/max6642.c index 6520bc51d02a..084b2685b7a5 100644 --- a/drivers/hwmon/max6642.c +++ b/drivers/hwmon/max6642.c @@ -206,7 +206,7 @@ static struct max6642_data *max6642_update_device(struct device *dev) * Sysfs stuff */ -static ssize_t show_temp_max10(struct device *dev, +static ssize_t temp_max10_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); @@ -216,8 +216,8 @@ static ssize_t show_temp_max10(struct device *dev, temp_from_reg10(data->temp_input[attr->index])); } -static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t temp_max_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr); struct max6642_data *data = max6642_update_device(dev); @@ -225,8 +225,9 @@ static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", temp_from_reg(data->temp_high[attr2->nr])); } -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t temp_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr); struct max6642_data *data = dev_get_drvdata(dev); @@ -245,7 +246,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, +static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, char *buf) { int bitnr = to_sensor_dev_attr(attr)->index; @@ -253,15 +254,15 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_max10, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_max10, NULL, 1); -static SENSOR_DEVICE_ATTR_2(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 0, MAX6642_REG_W_LOCAL_HIGH); -static SENSOR_DEVICE_ATTR_2(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 1, MAX6642_REG_W_REMOTE_HIGH); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_max10, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_max10, 1); +static SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp_max, 0, + MAX6642_REG_W_LOCAL_HIGH); +static SENSOR_DEVICE_ATTR_2_RW(temp2_max, temp_max, 1, + MAX6642_REG_W_REMOTE_HIGH); +static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 2); +static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6); +static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 4); static struct attribute *max6642_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c index 4752a9ee9645..61135a2d0cff 100644 --- a/drivers/hwmon/max6650.c +++ b/drivers/hwmon/max6650.c @@ -52,9 +52,9 @@ static int prescaler; /* clock: The clock frequency of the chip (max6651 can be clocked externally) */ static int clock = 254000; -module_param(fan_voltage, int, S_IRUGO); -module_param(prescaler, int, S_IRUGO); -module_param(clock, int, S_IRUGO); +module_param(fan_voltage, int, 0444); +module_param(prescaler, int, 0444); +module_param(clock, int, 0444); /* * MAX 6650/6651 registers diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c index 825b922a3f92..ff147e5e1b8c 100644 --- a/drivers/hwmon/mc13783-adc.c +++ b/drivers/hwmon/mc13783-adc.c @@ -63,8 +63,9 @@ static int mc13783_adc_read(struct device *dev, return 0; } -static ssize_t mc13783_adc_read_bp(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t mc13783_adc_bp_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { unsigned val; struct platform_device *pdev = to_platform_device(dev); @@ -86,8 +87,9 @@ static ssize_t mc13783_adc_read_bp(struct device *dev, return sprintf(buf, "%u\n", val); } -static ssize_t mc13783_adc_read_gp(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t mc13783_adc_gp_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { unsigned val; int ret = mc13783_adc_read(dev, devattr, &val); @@ -104,8 +106,9 @@ static ssize_t mc13783_adc_read_gp(struct device *dev, return sprintf(buf, "%u\n", val); } -static ssize_t mc13783_adc_read_uid(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t mc13783_adc_uid_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { unsigned int val; struct platform_device *pdev = to_platform_device(dev); @@ -125,8 +128,9 @@ static ssize_t mc13783_adc_read_uid(struct device *dev, return sprintf(buf, "%u\n", val); } -static ssize_t mc13783_adc_read_temp(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t mc13783_adc_temp_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { unsigned int val; struct platform_device *pdev = to_platform_device(dev); @@ -156,21 +160,20 @@ static ssize_t mc13783_adc_read_temp(struct device *dev, } static DEVICE_ATTR_RO(name); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, mc13783_adc_read_bp, NULL, 2); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, mc13783_adc_read_gp, NULL, 5); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, mc13783_adc_read_gp, NULL, 6); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, mc13783_adc_read_gp, NULL, 7); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, mc13783_adc_read_gp, NULL, 8); -static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, mc13783_adc_read_gp, NULL, 9); -static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, mc13783_adc_read_gp, NULL, 10); -static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, mc13783_adc_read_gp, NULL, 11); -static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, mc13783_adc_read_gp, NULL, 12); -static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, mc13783_adc_read_gp, NULL, 13); -static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, mc13783_adc_read_gp, NULL, 14); -static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, mc13783_adc_read_gp, NULL, 15); -static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, mc13783_adc_read_uid, NULL, 16); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, - mc13783_adc_read_temp, NULL, 17); +static SENSOR_DEVICE_ATTR_RO(in2_input, mc13783_adc_bp, 2); +static SENSOR_DEVICE_ATTR_RO(in5_input, mc13783_adc_gp, 5); +static SENSOR_DEVICE_ATTR_RO(in6_input, mc13783_adc_gp, 6); +static SENSOR_DEVICE_ATTR_RO(in7_input, mc13783_adc_gp, 7); +static SENSOR_DEVICE_ATTR_RO(in8_input, mc13783_adc_gp, 8); +static SENSOR_DEVICE_ATTR_RO(in9_input, mc13783_adc_gp, 9); +static SENSOR_DEVICE_ATTR_RO(in10_input, mc13783_adc_gp, 10); +static SENSOR_DEVICE_ATTR_RO(in11_input, mc13783_adc_gp, 11); +static SENSOR_DEVICE_ATTR_RO(in12_input, mc13783_adc_gp, 12); +static SENSOR_DEVICE_ATTR_RO(in13_input, mc13783_adc_gp, 13); +static SENSOR_DEVICE_ATTR_RO(in14_input, mc13783_adc_gp, 14); +static SENSOR_DEVICE_ATTR_RO(in15_input, mc13783_adc_gp, 15); +static SENSOR_DEVICE_ATTR_RO(in16_input, mc13783_adc_uid, 16); +static SENSOR_DEVICE_ATTR_RO(temp1_input, mc13783_adc_temp, 17); static struct attribute *mc13783_attr_base[] = { &dev_attr_name.attr, diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index c3040079b1cb..59ee01f3d022 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -44,8 +44,8 @@ * nct6796d 14 7 7 2+6 0xd420 0xc1 0x5ca3 * nct6797d 14 7 7 2+6 0xd450 0xc1 0x5ca3 * (0xd451) - * nct6798d 14 7 7 2+6 0xd458 0xc1 0x5ca3 - * (0xd459) + * nct6798d 14 7 7 2+6 0xd428 0xc1 0x5ca3 + * (0xd429) * * #temp lists the number of monitored temperature sources (first value) plus * the number of directly connectable temperature sensors (second value). @@ -138,7 +138,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); #define SIO_NCT6795_ID 0xd350 #define SIO_NCT6796_ID 0xd420 #define SIO_NCT6797_ID 0xd450 -#define SIO_NCT6798_ID 0xd458 +#define SIO_NCT6798_ID 0xd428 #define SIO_ID_MASK 0xFFF8 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; @@ -3594,7 +3594,8 @@ nct6775_check_fan_inputs(struct nct6775_data *data) fan5pin |= cr1b & BIT(5); fan5pin |= creb & BIT(5); - fan6pin = creb & BIT(3); + fan6pin = !dsw_en && (cr2d & BIT(1)); + fan6pin |= creb & BIT(3); pwm5pin |= cr2d & BIT(7); pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0)); @@ -4508,7 +4509,8 @@ static int __maybe_unused nct6775_resume(struct device *dev) if (data->kind == nct6791 || data->kind == nct6792 || data->kind == nct6793 || data->kind == nct6795 || - data->kind == nct6796) + data->kind == nct6796 || data->kind == nct6797 || + data->kind == nct6798) nct6791_enable_io_mapping(sioreg); superio_exit(sioreg); @@ -4644,7 +4646,8 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) if (sio_data->kind == nct6791 || sio_data->kind == nct6792 || sio_data->kind == nct6793 || sio_data->kind == nct6795 || - sio_data->kind == nct6796) + sio_data->kind == nct6796 || sio_data->kind == nct6797 || + sio_data->kind == nct6798) nct6791_enable_io_mapping(sioaddr); superio_exit(sioaddr); diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c index 7815ddf149f6..82c7de7b4639 100644 --- a/drivers/hwmon/nct7904.c +++ b/drivers/hwmon/nct7904.c @@ -182,7 +182,7 @@ static umode_t nct7904_fan_is_visible(const void *_data, u32 attr, int channel) const struct nct7904_data *data = _data; if (attr == hwmon_fan_input && data->fanin_mask & (1 << channel)) - return S_IRUGO; + return 0444; return 0; } @@ -225,7 +225,7 @@ static umode_t nct7904_in_is_visible(const void *_data, u32 attr, int channel) if (channel > 0 && attr == hwmon_in_input && (data->vsen_mask & BIT(index))) - return S_IRUGO; + return 0444; return 0; } @@ -260,10 +260,10 @@ static umode_t nct7904_temp_is_visible(const void *_data, u32 attr, int channel) if (attr == hwmon_temp_input) { if (channel == 0) { if (data->vsen_mask & BIT(17)) - return S_IRUGO; + return 0444; } else { if (data->tcpu_mask & BIT(channel - 1)) - return S_IRUGO; + return 0444; } } @@ -325,7 +325,7 @@ static umode_t nct7904_pwm_is_visible(const void *_data, u32 attr, int channel) switch (attr) { case hwmon_pwm_input: case hwmon_pwm_enable: - return S_IRUGO | S_IWUSR; + return 0644; default: return 0; } diff --git a/drivers/hwmon/nsa320-hwmon.c b/drivers/hwmon/nsa320-hwmon.c index 5a16109cdea8..f952f803faeb 100644 --- a/drivers/hwmon/nsa320-hwmon.c +++ b/drivers/hwmon/nsa320-hwmon.c @@ -114,8 +114,8 @@ static s32 nsa320_hwmon_update(struct device *dev) return mcu_data; } -static ssize_t show_label(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t label_show(struct device *dev, struct device_attribute *attr, + char *buf) { int channel = to_sensor_dev_attr(attr)->index; @@ -144,9 +144,9 @@ static ssize_t fan1_input_show(struct device *dev, return sprintf(buf, "%d\n", ((mcu_data & 0xff0000) >> 16) * 100); } -static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, NSA320_TEMP); +static SENSOR_DEVICE_ATTR_RO(temp1_label, label, NSA320_TEMP); static DEVICE_ATTR_RO(temp1_input); -static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, show_label, NULL, NSA320_FAN); +static SENSOR_DEVICE_ATTR_RO(fan1_label, label, NSA320_FAN); static DEVICE_ATTR_RO(fan1_input); static struct attribute *nsa320_attrs[] = { diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index 2823aff82c82..e4f9f7ce92fa 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c @@ -37,8 +37,6 @@ #include <linux/iio/consumer.h> #include <linux/hwmon.h> -#include <linux/hwmon-sysfs.h> -#include <linux/thermal.h> struct ntc_compensation { int temp_c; @@ -588,55 +586,87 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data) return -EINVAL; } -static int ntc_read_temp(void *data, int *temp) +static int ntc_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) { + struct ntc_data *data = dev_get_drvdata(dev); int ohm; - ohm = ntc_thermistor_get_ohm(data); - if (ohm < 0) - return ohm; - - *temp = get_temp_mc(data, ohm); - - return 0; + switch (type) { + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + ohm = ntc_thermistor_get_ohm(data); + if (ohm < 0) + return ohm; + *val = get_temp_mc(data, ohm); + return 0; + case hwmon_temp_type: + *val = 4; + return 0; + default: + break; + } + break; + default: + break; + } + return -EINVAL; } -static ssize_t ntc_type_show(struct device *dev, - struct device_attribute *attr, char *buf) +static umode_t ntc_is_visible(const void *data, enum hwmon_sensor_types type, + u32 attr, int channel) { - return sprintf(buf, "4\n"); + if (type == hwmon_temp) { + switch (attr) { + case hwmon_temp_input: + case hwmon_temp_type: + return 0444; + default: + break; + } + } + return 0; } -static ssize_t ntc_temp_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ntc_data *data = dev_get_drvdata(dev); - int ohm; +static const u32 ntc_chip_config[] = { + HWMON_C_REGISTER_TZ, + 0 +}; - ohm = ntc_thermistor_get_ohm(data); - if (ohm < 0) - return ohm; +static const struct hwmon_channel_info ntc_chip = { + .type = hwmon_chip, + .config = ntc_chip_config, +}; - return sprintf(buf, "%d\n", get_temp_mc(data, ohm)); -} +static const u32 ntc_temp_config[] = { + HWMON_T_INPUT, HWMON_T_TYPE, + 0 +}; -static SENSOR_DEVICE_ATTR_RO(temp1_type, ntc_type, 0); -static SENSOR_DEVICE_ATTR_RO(temp1_input, ntc_temp, 0); +static const struct hwmon_channel_info ntc_temp = { + .type = hwmon_temp, + .config = ntc_temp_config, +}; -static struct attribute *ntc_attrs[] = { - &sensor_dev_attr_temp1_type.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - NULL, +static const struct hwmon_channel_info *ntc_info[] = { + &ntc_chip, + &ntc_temp, + NULL }; -ATTRIBUTE_GROUPS(ntc); -static const struct thermal_zone_of_device_ops ntc_of_thermal_ops = { - .get_temp = ntc_read_temp, +static const struct hwmon_ops ntc_hwmon_ops = { + .is_visible = ntc_is_visible, + .read = ntc_read, +}; + +static const struct hwmon_chip_info ntc_chip_info = { + .ops = &ntc_hwmon_ops, + .info = ntc_info, }; static int ntc_thermistor_probe(struct platform_device *pdev) { - struct thermal_zone_device *tz; struct device *dev = &pdev->dev; const struct of_device_id *of_id = of_match_device(of_match_ptr(ntc_match), dev); @@ -697,8 +727,9 @@ static int ntc_thermistor_probe(struct platform_device *pdev) data->comp = ntc_type[pdev_id->driver_data].comp; data->n_comp = ntc_type[pdev_id->driver_data].n_comp; - hwmon_dev = devm_hwmon_device_register_with_groups(dev, pdev_id->name, - data, ntc_groups); + hwmon_dev = devm_hwmon_device_register_with_info(dev, pdev_id->name, + data, &ntc_chip_info, + NULL); if (IS_ERR(hwmon_dev)) { dev_err(dev, "unable to register as hwmon device.\n"); return PTR_ERR(hwmon_dev); @@ -707,11 +738,6 @@ static int ntc_thermistor_probe(struct platform_device *pdev) dev_info(dev, "Thermistor type: %s successfully probed.\n", pdev_id->name); - tz = devm_thermal_zone_of_sensor_register(dev, 0, data, - &ntc_of_thermal_ops); - if (IS_ERR(tz)) - dev_dbg(dev, "Failed to register to thermal fw.\n"); - return 0; } diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c index 423903f87955..b91a80abf724 100644 --- a/drivers/hwmon/occ/common.c +++ b/drivers/hwmon/occ/common.c @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0+ +// Copyright IBM Corp 2019 #include <linux/device.h> #include <linux/hwmon.h> @@ -380,8 +381,8 @@ static ssize_t occ_show_power_1(struct device *dev, val *= 1000000ULL; break; case 2: - val = get_unaligned_be32(&power->update_tag) * - occ->powr_sample_time_us; + val = (u64)get_unaligned_be32(&power->update_tag) * + occ->powr_sample_time_us; break; case 3: val = get_unaligned_be16(&power->value) * 1000000ULL; @@ -425,8 +426,8 @@ static ssize_t occ_show_power_2(struct device *dev, &power->update_tag); break; case 2: - val = get_unaligned_be32(&power->update_tag) * - occ->powr_sample_time_us; + val = (u64)get_unaligned_be32(&power->update_tag) * + occ->powr_sample_time_us; break; case 3: val = get_unaligned_be16(&power->value) * 1000000ULL; @@ -463,8 +464,8 @@ static ssize_t occ_show_power_a0(struct device *dev, &power->system.update_tag); break; case 2: - val = get_unaligned_be32(&power->system.update_tag) * - occ->powr_sample_time_us; + val = (u64)get_unaligned_be32(&power->system.update_tag) * + occ->powr_sample_time_us; break; case 3: val = get_unaligned_be16(&power->system.value) * 1000000ULL; @@ -477,8 +478,8 @@ static ssize_t occ_show_power_a0(struct device *dev, &power->proc.update_tag); break; case 6: - val = get_unaligned_be32(&power->proc.update_tag) * - occ->powr_sample_time_us; + val = (u64)get_unaligned_be32(&power->proc.update_tag) * + occ->powr_sample_time_us; break; case 7: val = get_unaligned_be16(&power->proc.value) * 1000000ULL; @@ -491,8 +492,8 @@ static ssize_t occ_show_power_a0(struct device *dev, &power->vdd.update_tag); break; case 10: - val = get_unaligned_be32(&power->vdd.update_tag) * - occ->powr_sample_time_us; + val = (u64)get_unaligned_be32(&power->vdd.update_tag) * + occ->powr_sample_time_us; break; case 11: val = get_unaligned_be16(&power->vdd.value) * 1000000ULL; @@ -505,8 +506,8 @@ static ssize_t occ_show_power_a0(struct device *dev, &power->vdn.update_tag); break; case 14: - val = get_unaligned_be32(&power->vdn.update_tag) * - occ->powr_sample_time_us; + val = (u64)get_unaligned_be32(&power->vdn.update_tag) * + occ->powr_sample_time_us; break; case 15: val = get_unaligned_be16(&power->vdn.value) * 1000000ULL; diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h index 7c44df3f5631..ed2cf4245295 100644 --- a/drivers/hwmon/occ/common.h +++ b/drivers/hwmon/occ/common.h @@ -1,4 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright IBM Corp 2019 */ #ifndef OCC_COMMON_H #define OCC_COMMON_H diff --git a/drivers/hwmon/occ/p8_i2c.c b/drivers/hwmon/occ/p8_i2c.c index b59efc945e54..76fb7870c7d3 100644 --- a/drivers/hwmon/occ/p8_i2c.c +++ b/drivers/hwmon/occ/p8_i2c.c @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0+ +// Copyright IBM Corp 2019 #include <linux/device.h> #include <linux/errno.h> diff --git a/drivers/hwmon/occ/p9_sbe.c b/drivers/hwmon/occ/p9_sbe.c index b65c1d1dfb54..f6387cc0b754 100644 --- a/drivers/hwmon/occ/p9_sbe.c +++ b/drivers/hwmon/occ/p9_sbe.c @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0+ +// Copyright IBM Corp 2019 #include <linux/device.h> #include <linux/errno.h> diff --git a/drivers/hwmon/occ/sysfs.c b/drivers/hwmon/occ/sysfs.c index 743b26ec8e54..fe3d15e416e7 100644 --- a/drivers/hwmon/occ/sysfs.c +++ b/drivers/hwmon/occ/sysfs.c @@ -1,14 +1,5 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * OCC hwmon driver sysfs interface - * - * Copyright (C) IBM Corporation 2018 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright IBM Corp 2019 #include <linux/bitops.h> #include <linux/device.h> diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 7e3697727537..56584f9ab803 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -254,7 +254,7 @@ static struct platform_driver pc87360_driver = { * Sysfs stuff */ -static ssize_t show_fan_input(struct device *dev, +static ssize_t fan_input_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -262,7 +262,7 @@ static ssize_t show_fan_input(struct device *dev, return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[attr->index], FAN_DIV_FROM_REG(data->fan_status[attr->index]))); } -static ssize_t show_fan_min(struct device *dev, +static ssize_t fan_min_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -270,7 +270,7 @@ static ssize_t show_fan_min(struct device *dev, return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[attr->index], FAN_DIV_FROM_REG(data->fan_status[attr->index]))); } -static ssize_t show_fan_div(struct device *dev, +static ssize_t fan_div_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -278,7 +278,7 @@ static ssize_t show_fan_div(struct device *dev, return sprintf(buf, "%u\n", FAN_DIV_FROM_REG(data->fan_status[attr->index])); } -static ssize_t show_fan_status(struct device *dev, +static ssize_t fan_status_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -286,9 +286,9 @@ static ssize_t show_fan_status(struct device *dev, return sprintf(buf, "%u\n", FAN_STATUS_FROM_REG(data->fan_status[attr->index])); } -static ssize_t set_fan_min(struct device *dev, - struct device_attribute *devattr, const char *buf, - size_t count) +static ssize_t fan_min_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct pc87360_data *data = dev_get_drvdata(dev); @@ -325,24 +325,24 @@ static ssize_t set_fan_min(struct device *dev, } static struct sensor_device_attribute fan_input[] = { - SENSOR_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0), - SENSOR_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1), - SENSOR_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2), + SENSOR_ATTR_RO(fan1_input, fan_input, 0), + SENSOR_ATTR_RO(fan2_input, fan_input, 1), + SENSOR_ATTR_RO(fan3_input, fan_input, 2), }; static struct sensor_device_attribute fan_status[] = { - SENSOR_ATTR(fan1_status, S_IRUGO, show_fan_status, NULL, 0), - SENSOR_ATTR(fan2_status, S_IRUGO, show_fan_status, NULL, 1), - SENSOR_ATTR(fan3_status, S_IRUGO, show_fan_status, NULL, 2), + SENSOR_ATTR_RO(fan1_status, fan_status, 0), + SENSOR_ATTR_RO(fan2_status, fan_status, 1), + SENSOR_ATTR_RO(fan3_status, fan_status, 2), }; static struct sensor_device_attribute fan_div[] = { - SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), - SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), - SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), + SENSOR_ATTR_RO(fan1_div, fan_div, 0), + SENSOR_ATTR_RO(fan2_div, fan_div, 1), + SENSOR_ATTR_RO(fan3_div, fan_div, 2), }; static struct sensor_device_attribute fan_min[] = { - SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 0), - SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 1), - SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2), + SENSOR_ATTR_RW(fan1_min, fan_min, 0), + SENSOR_ATTR_RW(fan2_min, fan_min, 1), + SENSOR_ATTR_RW(fan3_min, fan_min, 2), }; #define FAN_UNIT_ATTRS(X) \ @@ -353,7 +353,7 @@ static struct sensor_device_attribute fan_min[] = { NULL \ } -static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, +static ssize_t pwm_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -363,8 +363,8 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, FAN_CONFIG_INVERT(data->fan_conf, attr->index))); } -static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t pwm_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct pc87360_data *data = dev_get_drvdata(dev); @@ -385,9 +385,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, } static struct sensor_device_attribute pwm[] = { - SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0), - SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1), - SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2), + SENSOR_ATTR_RW(pwm1, pwm, 0), + SENSOR_ATTR_RW(pwm2, pwm, 1), + SENSOR_ATTR_RW(pwm3, pwm, 2), }; static struct attribute *pc8736x_fan_attr[][5] = { @@ -402,7 +402,7 @@ static const struct attribute_group pc8736x_fan_attr_group[] = { { .attrs = pc8736x_fan_attr[2], }, }; -static ssize_t show_in_input(struct device *dev, +static ssize_t in_input_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -410,7 +410,7 @@ static ssize_t show_in_input(struct device *dev, return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index], data->in_vref)); } -static ssize_t show_in_min(struct device *dev, +static ssize_t in_min_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -418,7 +418,7 @@ static ssize_t show_in_min(struct device *dev, return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index], data->in_vref)); } -static ssize_t show_in_max(struct device *dev, +static ssize_t in_max_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -426,15 +426,16 @@ static ssize_t show_in_max(struct device *dev, return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index], data->in_vref)); } -static ssize_t show_in_status(struct device *dev, +static ssize_t in_status_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct pc87360_data *data = pc87360_update_device(dev); return sprintf(buf, "%u\n", data->in_status[attr->index]); } -static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t in_min_store(struct device *dev, + struct device_attribute *devattr, const char *buf, + size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct pc87360_data *data = dev_get_drvdata(dev); @@ -452,8 +453,9 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, mutex_unlock(&data->update_lock); return count; } -static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t in_max_store(struct device *dev, + struct device_attribute *devattr, const char *buf, + size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct pc87360_data *data = dev_get_drvdata(dev); @@ -474,56 +476,56 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, } static struct sensor_device_attribute in_input[] = { - SENSOR_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0), - SENSOR_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1), - SENSOR_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2), - SENSOR_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3), - SENSOR_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4), - SENSOR_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5), - SENSOR_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6), - SENSOR_ATTR(in7_input, S_IRUGO, show_in_input, NULL, 7), - SENSOR_ATTR(in8_input, S_IRUGO, show_in_input, NULL, 8), - SENSOR_ATTR(in9_input, S_IRUGO, show_in_input, NULL, 9), - SENSOR_ATTR(in10_input, S_IRUGO, show_in_input, NULL, 10), + SENSOR_ATTR_RO(in0_input, in_input, 0), + SENSOR_ATTR_RO(in1_input, in_input, 1), + SENSOR_ATTR_RO(in2_input, in_input, 2), + SENSOR_ATTR_RO(in3_input, in_input, 3), + SENSOR_ATTR_RO(in4_input, in_input, 4), + SENSOR_ATTR_RO(in5_input, in_input, 5), + SENSOR_ATTR_RO(in6_input, in_input, 6), + SENSOR_ATTR_RO(in7_input, in_input, 7), + SENSOR_ATTR_RO(in8_input, in_input, 8), + SENSOR_ATTR_RO(in9_input, in_input, 9), + SENSOR_ATTR_RO(in10_input, in_input, 10), }; static struct sensor_device_attribute in_status[] = { - SENSOR_ATTR(in0_status, S_IRUGO, show_in_status, NULL, 0), - SENSOR_ATTR(in1_status, S_IRUGO, show_in_status, NULL, 1), - SENSOR_ATTR(in2_status, S_IRUGO, show_in_status, NULL, 2), - SENSOR_ATTR(in3_status, S_IRUGO, show_in_status, NULL, 3), - SENSOR_ATTR(in4_status, S_IRUGO, show_in_status, NULL, 4), - SENSOR_ATTR(in5_status, S_IRUGO, show_in_status, NULL, 5), - SENSOR_ATTR(in6_status, S_IRUGO, show_in_status, NULL, 6), - SENSOR_ATTR(in7_status, S_IRUGO, show_in_status, NULL, 7), - SENSOR_ATTR(in8_status, S_IRUGO, show_in_status, NULL, 8), - SENSOR_ATTR(in9_status, S_IRUGO, show_in_status, NULL, 9), - SENSOR_ATTR(in10_status, S_IRUGO, show_in_status, NULL, 10), + SENSOR_ATTR_RO(in0_status, in_status, 0), + SENSOR_ATTR_RO(in1_status, in_status, 1), + SENSOR_ATTR_RO(in2_status, in_status, 2), + SENSOR_ATTR_RO(in3_status, in_status, 3), + SENSOR_ATTR_RO(in4_status, in_status, 4), + SENSOR_ATTR_RO(in5_status, in_status, 5), + SENSOR_ATTR_RO(in6_status, in_status, 6), + SENSOR_ATTR_RO(in7_status, in_status, 7), + SENSOR_ATTR_RO(in8_status, in_status, 8), + SENSOR_ATTR_RO(in9_status, in_status, 9), + SENSOR_ATTR_RO(in10_status, in_status, 10), }; static struct sensor_device_attribute in_min[] = { - SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 0), - SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 1), - SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 2), - SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 3), - SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 4), - SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 5), - SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 6), - SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 7), - SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 8), - SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 9), - SENSOR_ATTR(in10_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 10), + SENSOR_ATTR_RW(in0_min, in_min, 0), + SENSOR_ATTR_RW(in1_min, in_min, 1), + SENSOR_ATTR_RW(in2_min, in_min, 2), + SENSOR_ATTR_RW(in3_min, in_min, 3), + SENSOR_ATTR_RW(in4_min, in_min, 4), + SENSOR_ATTR_RW(in5_min, in_min, 5), + SENSOR_ATTR_RW(in6_min, in_min, 6), + SENSOR_ATTR_RW(in7_min, in_min, 7), + SENSOR_ATTR_RW(in8_min, in_min, 8), + SENSOR_ATTR_RW(in9_min, in_min, 9), + SENSOR_ATTR_RW(in10_min, in_min, 10), }; static struct sensor_device_attribute in_max[] = { - SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 0), - SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 1), - SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 2), - SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 3), - SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 4), - SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 5), - SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 6), - SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 7), - SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 8), - SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 9), - SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10), + SENSOR_ATTR_RW(in0_max, in_max, 0), + SENSOR_ATTR_RW(in1_max, in_max, 1), + SENSOR_ATTR_RW(in2_max, in_max, 2), + SENSOR_ATTR_RW(in3_max, in_max, 3), + SENSOR_ATTR_RW(in4_max, in_max, 4), + SENSOR_ATTR_RW(in5_max, in_max, 5), + SENSOR_ATTR_RW(in6_max, in_max, 6), + SENSOR_ATTR_RW(in7_max, in_max, 7), + SENSOR_ATTR_RW(in8_max, in_max, 8), + SENSOR_ATTR_RW(in9_max, in_max, 9), + SENSOR_ATTR_RW(in10_max, in_max, 10), }; /* (temp & vin) channel status register alarm bits (pdf sec.11.5.12) */ @@ -537,16 +539,16 @@ static struct sensor_device_attribute in_max[] = { * 11.5.2) that (legacy) show_in_alarm() resds (via data->in_alarms) */ -static ssize_t show_in_min_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t in_min_alarm_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87360_data *data = pc87360_update_device(dev); unsigned nr = to_sensor_dev_attr(devattr)->index; return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MIN)); } -static ssize_t show_in_max_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t in_max_alarm_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87360_data *data = pc87360_update_device(dev); unsigned nr = to_sensor_dev_attr(devattr)->index; @@ -555,30 +557,30 @@ static ssize_t show_in_max_alarm(struct device *dev, } static struct sensor_device_attribute in_min_alarm[] = { - SENSOR_ATTR(in0_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 0), - SENSOR_ATTR(in1_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 1), - SENSOR_ATTR(in2_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 2), - SENSOR_ATTR(in3_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 3), - SENSOR_ATTR(in4_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 4), - SENSOR_ATTR(in5_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 5), - SENSOR_ATTR(in6_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 6), - SENSOR_ATTR(in7_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 7), - SENSOR_ATTR(in8_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 8), - SENSOR_ATTR(in9_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 9), - SENSOR_ATTR(in10_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 10), + SENSOR_ATTR_RO(in0_min_alarm, in_min_alarm, 0), + SENSOR_ATTR_RO(in1_min_alarm, in_min_alarm, 1), + SENSOR_ATTR_RO(in2_min_alarm, in_min_alarm, 2), + SENSOR_ATTR_RO(in3_min_alarm, in_min_alarm, 3), + SENSOR_ATTR_RO(in4_min_alarm, in_min_alarm, 4), + SENSOR_ATTR_RO(in5_min_alarm, in_min_alarm, 5), + SENSOR_ATTR_RO(in6_min_alarm, in_min_alarm, 6), + SENSOR_ATTR_RO(in7_min_alarm, in_min_alarm, 7), + SENSOR_ATTR_RO(in8_min_alarm, in_min_alarm, 8), + SENSOR_ATTR_RO(in9_min_alarm, in_min_alarm, 9), + SENSOR_ATTR_RO(in10_min_alarm, in_min_alarm, 10), }; static struct sensor_device_attribute in_max_alarm[] = { - SENSOR_ATTR(in0_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 0), - SENSOR_ATTR(in1_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 1), - SENSOR_ATTR(in2_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 2), - SENSOR_ATTR(in3_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 3), - SENSOR_ATTR(in4_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 4), - SENSOR_ATTR(in5_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 5), - SENSOR_ATTR(in6_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 6), - SENSOR_ATTR(in7_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 7), - SENSOR_ATTR(in8_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 8), - SENSOR_ATTR(in9_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 9), - SENSOR_ATTR(in10_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 10), + SENSOR_ATTR_RO(in0_max_alarm, in_max_alarm, 0), + SENSOR_ATTR_RO(in1_max_alarm, in_max_alarm, 1), + SENSOR_ATTR_RO(in2_max_alarm, in_max_alarm, 2), + SENSOR_ATTR_RO(in3_max_alarm, in_max_alarm, 3), + SENSOR_ATTR_RO(in4_max_alarm, in_max_alarm, 4), + SENSOR_ATTR_RO(in5_max_alarm, in_max_alarm, 5), + SENSOR_ATTR_RO(in6_max_alarm, in_max_alarm, 6), + SENSOR_ATTR_RO(in7_max_alarm, in_max_alarm, 7), + SENSOR_ATTR_RO(in8_max_alarm, in_max_alarm, 8), + SENSOR_ATTR_RO(in9_max_alarm, in_max_alarm, 9), + SENSOR_ATTR_RO(in10_max_alarm, in_max_alarm, 10), }; #define VIN_UNIT_ATTRS(X) \ @@ -651,7 +653,7 @@ static const struct attribute_group pc8736x_vin_group = { .attrs = pc8736x_vin_attr_array, }; -static ssize_t show_therm_input(struct device *dev, +static ssize_t therm_input_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -659,7 +661,7 @@ static ssize_t show_therm_input(struct device *dev, return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index], data->in_vref)); } -static ssize_t show_therm_min(struct device *dev, +static ssize_t therm_min_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -667,7 +669,7 @@ static ssize_t show_therm_min(struct device *dev, return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index], data->in_vref)); } -static ssize_t show_therm_max(struct device *dev, +static ssize_t therm_max_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -675,7 +677,7 @@ static ssize_t show_therm_max(struct device *dev, return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index], data->in_vref)); } -static ssize_t show_therm_crit(struct device *dev, +static ssize_t therm_crit_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -683,7 +685,7 @@ static ssize_t show_therm_crit(struct device *dev, return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[attr->index-11], data->in_vref)); } -static ssize_t show_therm_status(struct device *dev, +static ssize_t therm_status_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -691,9 +693,9 @@ static ssize_t show_therm_status(struct device *dev, return sprintf(buf, "%u\n", data->in_status[attr->index]); } -static ssize_t set_therm_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t therm_min_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct pc87360_data *data = dev_get_drvdata(dev); @@ -712,9 +714,9 @@ static ssize_t set_therm_min(struct device *dev, return count; } -static ssize_t set_therm_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t therm_max_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct pc87360_data *data = dev_get_drvdata(dev); @@ -732,9 +734,9 @@ static ssize_t set_therm_max(struct device *dev, mutex_unlock(&data->update_lock); return count; } -static ssize_t set_therm_crit(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t therm_crit_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct pc87360_data *data = dev_get_drvdata(dev); @@ -758,38 +760,29 @@ static ssize_t set_therm_crit(struct device *dev, * used in the chip to measure voltage across the thermistors */ static struct sensor_device_attribute therm_input[] = { - SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0 + 11), - SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1 + 11), - SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2 + 11), + SENSOR_ATTR_RO(temp4_input, therm_input, 0 + 11), + SENSOR_ATTR_RO(temp5_input, therm_input, 1 + 11), + SENSOR_ATTR_RO(temp6_input, therm_input, 2 + 11), }; static struct sensor_device_attribute therm_status[] = { - SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0 + 11), - SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1 + 11), - SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2 + 11), + SENSOR_ATTR_RO(temp4_status, therm_status, 0 + 11), + SENSOR_ATTR_RO(temp5_status, therm_status, 1 + 11), + SENSOR_ATTR_RO(temp6_status, therm_status, 2 + 11), }; static struct sensor_device_attribute therm_min[] = { - SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR, - show_therm_min, set_therm_min, 0 + 11), - SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR, - show_therm_min, set_therm_min, 1 + 11), - SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR, - show_therm_min, set_therm_min, 2 + 11), + SENSOR_ATTR_RW(temp4_min, therm_min, 0 + 11), + SENSOR_ATTR_RW(temp5_min, therm_min, 1 + 11), + SENSOR_ATTR_RW(temp6_min, therm_min, 2 + 11), }; static struct sensor_device_attribute therm_max[] = { - SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR, - show_therm_max, set_therm_max, 0 + 11), - SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR, - show_therm_max, set_therm_max, 1 + 11), - SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR, - show_therm_max, set_therm_max, 2 + 11), + SENSOR_ATTR_RW(temp4_max, therm_max, 0 + 11), + SENSOR_ATTR_RW(temp5_max, therm_max, 1 + 11), + SENSOR_ATTR_RW(temp6_max, therm_max, 2 + 11), }; static struct sensor_device_attribute therm_crit[] = { - SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR, - show_therm_crit, set_therm_crit, 0 + 11), - SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR, - show_therm_crit, set_therm_crit, 1 + 11), - SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR, - show_therm_crit, set_therm_crit, 2 + 11), + SENSOR_ATTR_RW(temp4_crit, therm_crit, 0 + 11), + SENSOR_ATTR_RW(temp5_crit, therm_crit, 1 + 11), + SENSOR_ATTR_RW(temp6_crit, therm_crit, 2 + 11), }; /* @@ -797,24 +790,27 @@ static struct sensor_device_attribute therm_crit[] = { * status register (sec 11.5.12) */ -static ssize_t show_therm_min_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t therm_min_alarm_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { struct pc87360_data *data = pc87360_update_device(dev); unsigned nr = to_sensor_dev_attr(devattr)->index; return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MIN)); } -static ssize_t show_therm_max_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t therm_max_alarm_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { struct pc87360_data *data = pc87360_update_device(dev); unsigned nr = to_sensor_dev_attr(devattr)->index; return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MAX)); } -static ssize_t show_therm_crit_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t therm_crit_alarm_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { struct pc87360_data *data = pc87360_update_device(dev); unsigned nr = to_sensor_dev_attr(devattr)->index; @@ -823,28 +819,19 @@ static ssize_t show_therm_crit_alarm(struct device *dev, } static struct sensor_device_attribute therm_min_alarm[] = { - SENSOR_ATTR(temp4_min_alarm, S_IRUGO, - show_therm_min_alarm, NULL, 0 + 11), - SENSOR_ATTR(temp5_min_alarm, S_IRUGO, - show_therm_min_alarm, NULL, 1 + 11), - SENSOR_ATTR(temp6_min_alarm, S_IRUGO, - show_therm_min_alarm, NULL, 2 + 11), + SENSOR_ATTR_RO(temp4_min_alarm, therm_min_alarm, 0 + 11), + SENSOR_ATTR_RO(temp5_min_alarm, therm_min_alarm, 1 + 11), + SENSOR_ATTR_RO(temp6_min_alarm, therm_min_alarm, 2 + 11), }; static struct sensor_device_attribute therm_max_alarm[] = { - SENSOR_ATTR(temp4_max_alarm, S_IRUGO, - show_therm_max_alarm, NULL, 0 + 11), - SENSOR_ATTR(temp5_max_alarm, S_IRUGO, - show_therm_max_alarm, NULL, 1 + 11), - SENSOR_ATTR(temp6_max_alarm, S_IRUGO, - show_therm_max_alarm, NULL, 2 + 11), + SENSOR_ATTR_RO(temp4_max_alarm, therm_max_alarm, 0 + 11), + SENSOR_ATTR_RO(temp5_max_alarm, therm_max_alarm, 1 + 11), + SENSOR_ATTR_RO(temp6_max_alarm, therm_max_alarm, 2 + 11), }; static struct sensor_device_attribute therm_crit_alarm[] = { - SENSOR_ATTR(temp4_crit_alarm, S_IRUGO, - show_therm_crit_alarm, NULL, 0 + 11), - SENSOR_ATTR(temp5_crit_alarm, S_IRUGO, - show_therm_crit_alarm, NULL, 1 + 11), - SENSOR_ATTR(temp6_crit_alarm, S_IRUGO, - show_therm_crit_alarm, NULL, 2 + 11), + SENSOR_ATTR_RO(temp4_crit_alarm, therm_crit_alarm, 0 + 11), + SENSOR_ATTR_RO(temp5_crit_alarm, therm_crit_alarm, 1 + 11), + SENSOR_ATTR_RO(temp6_crit_alarm, therm_crit_alarm, 2 + 11), }; #define THERM_UNIT_ATTRS(X) \ @@ -867,7 +854,7 @@ static const struct attribute_group pc8736x_therm_group = { .attrs = pc8736x_therm_attr_array, }; -static ssize_t show_temp_input(struct device *dev, +static ssize_t temp_input_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -875,7 +862,7 @@ static ssize_t show_temp_input(struct device *dev, return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); } -static ssize_t show_temp_min(struct device *dev, +static ssize_t temp_min_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -883,7 +870,7 @@ static ssize_t show_temp_min(struct device *dev, return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[attr->index])); } -static ssize_t show_temp_max(struct device *dev, +static ssize_t temp_max_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -891,7 +878,7 @@ static ssize_t show_temp_max(struct device *dev, return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[attr->index])); } -static ssize_t show_temp_crit(struct device *dev, +static ssize_t temp_crit_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -900,7 +887,7 @@ static ssize_t show_temp_crit(struct device *dev, TEMP_FROM_REG(data->temp_crit[attr->index])); } -static ssize_t show_temp_status(struct device *dev, +static ssize_t temp_status_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -908,9 +895,9 @@ static ssize_t show_temp_status(struct device *dev, return sprintf(buf, "%d\n", data->temp_status[attr->index]); } -static ssize_t set_temp_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t temp_min_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct pc87360_data *data = dev_get_drvdata(dev); @@ -929,9 +916,9 @@ static ssize_t set_temp_min(struct device *dev, return count; } -static ssize_t set_temp_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t temp_max_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct pc87360_data *data = dev_get_drvdata(dev); @@ -950,9 +937,9 @@ static ssize_t set_temp_max(struct device *dev, return count; } -static ssize_t set_temp_crit(struct device *dev, - struct device_attribute *devattr, const char *buf, - size_t count) +static ssize_t temp_crit_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct pc87360_data *data = dev_get_drvdata(dev); @@ -972,38 +959,29 @@ static ssize_t set_temp_crit(struct device *dev, } static struct sensor_device_attribute temp_input[] = { - SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0), - SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1), - SENSOR_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2), + SENSOR_ATTR_RO(temp1_input, temp_input, 0), + SENSOR_ATTR_RO(temp2_input, temp_input, 1), + SENSOR_ATTR_RO(temp3_input, temp_input, 2), }; static struct sensor_device_attribute temp_status[] = { - SENSOR_ATTR(temp1_status, S_IRUGO, show_temp_status, NULL, 0), - SENSOR_ATTR(temp2_status, S_IRUGO, show_temp_status, NULL, 1), - SENSOR_ATTR(temp3_status, S_IRUGO, show_temp_status, NULL, 2), + SENSOR_ATTR_RO(temp1_status, temp_status, 0), + SENSOR_ATTR_RO(temp2_status, temp_status, 1), + SENSOR_ATTR_RO(temp3_status, temp_status, 2), }; static struct sensor_device_attribute temp_min[] = { - SENSOR_ATTR(temp1_min, S_IRUGO | S_IWUSR, - show_temp_min, set_temp_min, 0), - SENSOR_ATTR(temp2_min, S_IRUGO | S_IWUSR, - show_temp_min, set_temp_min, 1), - SENSOR_ATTR(temp3_min, S_IRUGO | S_IWUSR, - show_temp_min, set_temp_min, 2), + SENSOR_ATTR_RW(temp1_min, temp_min, 0), + SENSOR_ATTR_RW(temp2_min, temp_min, 1), + SENSOR_ATTR_RW(temp3_min, temp_min, 2), }; static struct sensor_device_attribute temp_max[] = { - SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, - show_temp_max, set_temp_max, 0), - SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, - show_temp_max, set_temp_max, 1), - SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, - show_temp_max, set_temp_max, 2), + SENSOR_ATTR_RW(temp1_max, temp_max, 0), + SENSOR_ATTR_RW(temp2_max, temp_max, 1), + SENSOR_ATTR_RW(temp3_max, temp_max, 2), }; static struct sensor_device_attribute temp_crit[] = { - SENSOR_ATTR(temp1_crit, S_IRUGO | S_IWUSR, - show_temp_crit, set_temp_crit, 0), - SENSOR_ATTR(temp2_crit, S_IRUGO | S_IWUSR, - show_temp_crit, set_temp_crit, 1), - SENSOR_ATTR(temp3_crit, S_IRUGO | S_IWUSR, - show_temp_crit, set_temp_crit, 2), + SENSOR_ATTR_RW(temp1_crit, temp_crit, 0), + SENSOR_ATTR_RW(temp2_crit, temp_crit, 1), + SENSOR_ATTR_RW(temp3_crit, temp_crit, 2), }; static ssize_t alarms_temp_show(struct device *dev, @@ -1021,8 +999,9 @@ static DEVICE_ATTR_RO(alarms_temp); * 12.3.2) that show_temp_alarm() reads (via data->temp_alarms) */ -static ssize_t show_temp_min_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t temp_min_alarm_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { struct pc87360_data *data = pc87360_update_device(dev); unsigned nr = to_sensor_dev_attr(devattr)->index; @@ -1030,8 +1009,9 @@ static ssize_t show_temp_min_alarm(struct device *dev, return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MIN)); } -static ssize_t show_temp_max_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t temp_max_alarm_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { struct pc87360_data *data = pc87360_update_device(dev); unsigned nr = to_sensor_dev_attr(devattr)->index; @@ -1039,8 +1019,9 @@ static ssize_t show_temp_max_alarm(struct device *dev, return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MAX)); } -static ssize_t show_temp_crit_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t temp_crit_alarm_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { struct pc87360_data *data = pc87360_update_device(dev); unsigned nr = to_sensor_dev_attr(devattr)->index; @@ -1049,26 +1030,26 @@ static ssize_t show_temp_crit_alarm(struct device *dev, } static struct sensor_device_attribute temp_min_alarm[] = { - SENSOR_ATTR(temp1_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 0), - SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 1), - SENSOR_ATTR(temp3_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 2), + SENSOR_ATTR_RO(temp1_min_alarm, temp_min_alarm, 0), + SENSOR_ATTR_RO(temp2_min_alarm, temp_min_alarm, 1), + SENSOR_ATTR_RO(temp3_min_alarm, temp_min_alarm, 2), }; static struct sensor_device_attribute temp_max_alarm[] = { - SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 0), - SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 1), - SENSOR_ATTR(temp3_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 2), + SENSOR_ATTR_RO(temp1_max_alarm, temp_max_alarm, 0), + SENSOR_ATTR_RO(temp2_max_alarm, temp_max_alarm, 1), + SENSOR_ATTR_RO(temp3_max_alarm, temp_max_alarm, 2), }; static struct sensor_device_attribute temp_crit_alarm[] = { - SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 0), - SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 1), - SENSOR_ATTR(temp3_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 2), + SENSOR_ATTR_RO(temp1_crit_alarm, temp_crit_alarm, 0), + SENSOR_ATTR_RO(temp2_crit_alarm, temp_crit_alarm, 1), + SENSOR_ATTR_RO(temp3_crit_alarm, temp_crit_alarm, 2), }; #define TEMP_FAULT 0x40 /* open diode */ -static ssize_t show_temp_fault(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t temp_fault_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87360_data *data = pc87360_update_device(dev); unsigned nr = to_sensor_dev_attr(devattr)->index; @@ -1076,9 +1057,9 @@ static ssize_t show_temp_fault(struct device *dev, return sprintf(buf, "%u\n", !!(data->temp_status[nr] & TEMP_FAULT)); } static struct sensor_device_attribute temp_fault[] = { - SENSOR_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0), - SENSOR_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1), - SENSOR_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2), + SENSOR_ATTR_RO(temp1_fault, temp_fault, 0), + SENSOR_ATTR_RO(temp2_fault, temp_fault, 1), + SENSOR_ATTR_RO(temp3_fault, temp_fault, 2), }; #define TEMP_UNIT_ATTRS(X) \ diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index dc5a9d5ada51..d1a3f2040c00 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c @@ -384,8 +384,8 @@ done: return data; } -static ssize_t show_fan_input(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t fan_input_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -393,8 +393,8 @@ static ssize_t show_fan_input(struct device *dev, struct device_attribute return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr])); } -static ssize_t show_fan_min(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t fan_min_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -402,8 +402,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr])); } -static ssize_t show_fan_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t fan_alarm_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -412,8 +412,8 @@ static ssize_t show_fan_alarm(struct device *dev, struct device_attribute & FAN_STATUS_LOSPD)); } -static ssize_t show_fan_fault(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t fan_fault_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -422,8 +422,9 @@ static ssize_t show_fan_fault(struct device *dev, struct device_attribute & FAN_STATUS_STALL)); } -static ssize_t set_fan_min(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) +static ssize_t fan_min_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { struct pc87427_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -449,49 +450,41 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute return count; } -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3); -static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_input, NULL, 4); -static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_input, NULL, 5); -static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_input, NULL, 6); -static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_input, NULL, 7); - -static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 2); -static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 3); -static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 4); -static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 5); -static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 6); -static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 7); - -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7); - -static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3); -static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4); -static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5); -static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6); -static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7); +static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1); +static SENSOR_DEVICE_ATTR_RO(fan3_input, fan_input, 2); +static SENSOR_DEVICE_ATTR_RO(fan4_input, fan_input, 3); +static SENSOR_DEVICE_ATTR_RO(fan5_input, fan_input, 4); +static SENSOR_DEVICE_ATTR_RO(fan6_input, fan_input, 5); +static SENSOR_DEVICE_ATTR_RO(fan7_input, fan_input, 6); +static SENSOR_DEVICE_ATTR_RO(fan8_input, fan_input, 7); + +static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0); +static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1); +static SENSOR_DEVICE_ATTR_RW(fan3_min, fan_min, 2); +static SENSOR_DEVICE_ATTR_RW(fan4_min, fan_min, 3); +static SENSOR_DEVICE_ATTR_RW(fan5_min, fan_min, 4); +static SENSOR_DEVICE_ATTR_RW(fan6_min, fan_min, 5); +static SENSOR_DEVICE_ATTR_RW(fan7_min, fan_min, 6); +static SENSOR_DEVICE_ATTR_RW(fan8_min, fan_min, 7); + +static SENSOR_DEVICE_ATTR_RO(fan1_alarm, fan_alarm, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_alarm, fan_alarm, 1); +static SENSOR_DEVICE_ATTR_RO(fan3_alarm, fan_alarm, 2); +static SENSOR_DEVICE_ATTR_RO(fan4_alarm, fan_alarm, 3); +static SENSOR_DEVICE_ATTR_RO(fan5_alarm, fan_alarm, 4); +static SENSOR_DEVICE_ATTR_RO(fan6_alarm, fan_alarm, 5); +static SENSOR_DEVICE_ATTR_RO(fan7_alarm, fan_alarm, 6); +static SENSOR_DEVICE_ATTR_RO(fan8_alarm, fan_alarm, 7); + +static SENSOR_DEVICE_ATTR_RO(fan1_fault, fan_fault, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_fault, fan_fault, 1); +static SENSOR_DEVICE_ATTR_RO(fan3_fault, fan_fault, 2); +static SENSOR_DEVICE_ATTR_RO(fan4_fault, fan_fault, 3); +static SENSOR_DEVICE_ATTR_RO(fan5_fault, fan_fault, 4); +static SENSOR_DEVICE_ATTR_RO(fan6_fault, fan_fault, 5); +static SENSOR_DEVICE_ATTR_RO(fan7_fault, fan_fault, 6); +static SENSOR_DEVICE_ATTR_RO(fan8_fault, fan_fault, 7); static struct attribute *pc87427_attributes_fan[8][5] = { { @@ -568,8 +561,8 @@ static void update_pwm_enable(struct pc87427_data *data, int nr, u8 mode) outb(data->pwm_enable[nr], iobase + PC87427_REG_PWM_ENABLE); } -static ssize_t show_pwm_enable(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t pwm_enable_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -581,8 +574,9 @@ static ssize_t show_pwm_enable(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", pwm_enable); } -static ssize_t set_pwm_enable(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) +static ssize_t pwm_enable_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { struct pc87427_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -602,8 +596,8 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute return count; } -static ssize_t show_pwm(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t pwm_show(struct device *dev, struct device_attribute *devattr, + char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -611,8 +605,8 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", (int)data->pwm[nr]); } -static ssize_t set_pwm(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) +static ssize_t pwm_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) { struct pc87427_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -657,19 +651,15 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute return count; } -static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, - show_pwm_enable, set_pwm_enable, 0); -static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, - show_pwm_enable, set_pwm_enable, 1); -static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, - show_pwm_enable, set_pwm_enable, 2); -static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, - show_pwm_enable, set_pwm_enable, 3); +static SENSOR_DEVICE_ATTR_RW(pwm1_enable, pwm_enable, 0); +static SENSOR_DEVICE_ATTR_RW(pwm2_enable, pwm_enable, 1); +static SENSOR_DEVICE_ATTR_RW(pwm3_enable, pwm_enable, 2); +static SENSOR_DEVICE_ATTR_RW(pwm4_enable, pwm_enable, 3); -static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); -static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); -static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); +static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0); +static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1); +static SENSOR_DEVICE_ATTR_RW(pwm3, pwm, 2); +static SENSOR_DEVICE_ATTR_RW(pwm4, pwm, 3); static struct attribute *pc87427_attributes_pwm[4][3] = { { @@ -698,8 +688,8 @@ static const struct attribute_group pc87427_group_pwm[4] = { { .attrs = pc87427_attributes_pwm[3] }, }; -static ssize_t show_temp_input(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_input_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -707,8 +697,8 @@ static ssize_t show_temp_input(struct device *dev, struct device_attribute return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr])); } -static ssize_t show_temp_min(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_min_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -716,8 +706,8 @@ static ssize_t show_temp_min(struct device *dev, struct device_attribute return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_min[nr])); } -static ssize_t show_temp_max(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_max_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -725,8 +715,8 @@ static ssize_t show_temp_max(struct device *dev, struct device_attribute return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_max[nr])); } -static ssize_t show_temp_crit(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_crit_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -734,8 +724,8 @@ static ssize_t show_temp_crit(struct device *dev, struct device_attribute return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_crit[nr])); } -static ssize_t show_temp_type(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_type_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -743,8 +733,9 @@ static ssize_t show_temp_type(struct device *dev, struct device_attribute return sprintf(buf, "%u\n", temp_type_from_reg(data->temp_type[nr])); } -static ssize_t show_temp_min_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_min_alarm_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -753,8 +744,9 @@ static ssize_t show_temp_min_alarm(struct device *dev, struct device_attribute & TEMP_STATUS_LOWFLG)); } -static ssize_t show_temp_max_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_max_alarm_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -763,8 +755,9 @@ static ssize_t show_temp_max_alarm(struct device *dev, struct device_attribute & TEMP_STATUS_HIGHFLG)); } -static ssize_t show_temp_crit_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_crit_alarm_show(struct device *dev, + struct device_attribute *devattr, + char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -773,8 +766,8 @@ static ssize_t show_temp_crit_alarm(struct device *dev, struct device_attribute & TEMP_STATUS_CRITFLG)); } -static ssize_t show_temp_fault(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_fault_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct pc87427_data *data = pc87427_update_device(dev); int nr = to_sensor_dev_attr(devattr)->index; @@ -783,86 +776,68 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute & TEMP_STATUS_SENSERR)); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_min, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_min, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_min, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_min, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_min, S_IRUGO, show_temp_min, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_min, S_IRUGO, show_temp_min, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_type, S_IRUGO, show_temp_type, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_type, S_IRUGO, show_temp_type, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_type, S_IRUGO, show_temp_type, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, - show_temp_min_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, - show_temp_min_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, - show_temp_min_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, - show_temp_min_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO, - show_temp_min_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_min_alarm, S_IRUGO, - show_temp_min_alarm, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, - show_temp_max_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, - show_temp_max_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, - show_temp_max_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, - show_temp_max_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, - show_temp_max_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO, - show_temp_max_alarm, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, - show_temp_crit_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, - show_temp_crit_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, - show_temp_crit_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, - show_temp_crit_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, - show_temp_crit_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO, - show_temp_crit_alarm, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_input, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_input, temp_input, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_input, temp_input, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_input, temp_input, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_input, temp_input, 5); + +static SENSOR_DEVICE_ATTR_RO(temp1_min, temp_min, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_min, temp_min, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_min, temp_min, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_min, temp_min, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_min, temp_min, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_min, temp_min, 5); + +static SENSOR_DEVICE_ATTR_RO(temp1_max, temp_max, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_max, temp_max, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_max, temp_max, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_max, temp_max, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_max, temp_max, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_max, temp_max, 5); + +static SENSOR_DEVICE_ATTR_RO(temp1_crit, temp_crit, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_crit, temp_crit, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_crit, temp_crit, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_crit, temp_crit, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_crit, temp_crit, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_crit, temp_crit, 5); + +static SENSOR_DEVICE_ATTR_RO(temp1_type, temp_type, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_type, temp_type, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_type, temp_type, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_type, temp_type, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_type, temp_type, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_type, temp_type, 5); + +static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, temp_min_alarm, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, temp_min_alarm, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_min_alarm, temp_min_alarm, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_min_alarm, temp_min_alarm, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_min_alarm, temp_min_alarm, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_min_alarm, temp_min_alarm, 5); + +static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, temp_max_alarm, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, temp_max_alarm, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, temp_max_alarm, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_max_alarm, temp_max_alarm, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_max_alarm, temp_max_alarm, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_max_alarm, temp_max_alarm, 5); + +static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, temp_crit_alarm, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, temp_crit_alarm, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, temp_crit_alarm, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_crit_alarm, temp_crit_alarm, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_crit_alarm, temp_crit_alarm, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_crit_alarm, temp_crit_alarm, 5); + +static SENSOR_DEVICE_ATTR_RO(temp1_fault, temp_fault, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_fault, temp_fault, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_fault, temp_fault, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_fault, temp_fault, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_fault, temp_fault, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_fault, temp_fault, 5); static struct attribute *pc87427_attributes_temp[6][10] = { { diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c index 7688dab32f6e..f05eaa50535e 100644 --- a/drivers/hwmon/pmbus/pmbus.c +++ b/drivers/hwmon/pmbus/pmbus.c @@ -28,6 +28,11 @@ #include <linux/pmbus.h> #include "pmbus.h" +struct pmbus_device_info { + int pages; + u32 flags; +}; + /* * Find sensor groups and status registers on each page. */ @@ -172,13 +177,14 @@ static int pmbus_probe(struct i2c_client *client, struct pmbus_driver_info *info; struct pmbus_platform_data *pdata = NULL; struct device *dev = &client->dev; + struct pmbus_device_info *device_info; info = devm_kzalloc(dev, sizeof(struct pmbus_driver_info), GFP_KERNEL); if (!info) return -ENOMEM; - if (!strcmp(id->name, "dps460") || !strcmp(id->name, "dps800") || - !strcmp(id->name, "sgd009")) { + device_info = (struct pmbus_device_info *)id->driver_data; + if (device_info->flags & PMBUS_SKIP_STATUS_CHECK) { pdata = devm_kzalloc(dev, sizeof(struct pmbus_platform_data), GFP_KERNEL); if (!pdata) @@ -187,36 +193,50 @@ static int pmbus_probe(struct i2c_client *client, pdata->flags = PMBUS_SKIP_STATUS_CHECK; } - info->pages = id->driver_data; + info->pages = device_info->pages; info->identify = pmbus_identify; dev->platform_data = pdata; return pmbus_do_probe(client, id, info); } +static const struct pmbus_device_info pmbus_info_one = { + .pages = 1, + .flags = 0 +}; +static const struct pmbus_device_info pmbus_info_zero = { + .pages = 0, + .flags = 0 +}; +static const struct pmbus_device_info pmbus_info_one_skip = { + .pages = 1, + .flags = PMBUS_SKIP_STATUS_CHECK +}; + /* * Use driver_data to set the number of pages supported by the chip. */ static const struct i2c_device_id pmbus_id[] = { - {"adp4000", 1}, - {"bmr453", 1}, - {"bmr454", 1}, - {"dps460", 1}, - {"dps800", 1}, - {"mdt040", 1}, - {"ncp4200", 1}, - {"ncp4208", 1}, - {"pdt003", 1}, - {"pdt006", 1}, - {"pdt012", 1}, - {"pmbus", 0}, - {"sgd009", 1}, - {"tps40400", 1}, - {"tps544b20", 1}, - {"tps544b25", 1}, - {"tps544c20", 1}, - {"tps544c25", 1}, - {"udt020", 1}, + {"adp4000", (kernel_ulong_t)&pmbus_info_one}, + {"bmr453", (kernel_ulong_t)&pmbus_info_one}, + {"bmr454", (kernel_ulong_t)&pmbus_info_one}, + {"dps460", (kernel_ulong_t)&pmbus_info_one_skip}, + {"dps650ab", (kernel_ulong_t)&pmbus_info_one_skip}, + {"dps800", (kernel_ulong_t)&pmbus_info_one_skip}, + {"mdt040", (kernel_ulong_t)&pmbus_info_one}, + {"ncp4200", (kernel_ulong_t)&pmbus_info_one}, + {"ncp4208", (kernel_ulong_t)&pmbus_info_one}, + {"pdt003", (kernel_ulong_t)&pmbus_info_one}, + {"pdt006", (kernel_ulong_t)&pmbus_info_one}, + {"pdt012", (kernel_ulong_t)&pmbus_info_one}, + {"pmbus", (kernel_ulong_t)&pmbus_info_zero}, + {"sgd009", (kernel_ulong_t)&pmbus_info_one_skip}, + {"tps40400", (kernel_ulong_t)&pmbus_info_one}, + {"tps544b20", (kernel_ulong_t)&pmbus_info_one}, + {"tps544b25", (kernel_ulong_t)&pmbus_info_one}, + {"tps544c20", (kernel_ulong_t)&pmbus_info_one}, + {"tps544c25", (kernel_ulong_t)&pmbus_info_one}, + {"udt020", (kernel_ulong_t)&pmbus_info_one}, {} }; diff --git a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c index 85b515cd9df0..2bc352c5357f 100644 --- a/drivers/hwmon/pmbus/tps53679.c +++ b/drivers/hwmon/pmbus/tps53679.c @@ -80,7 +80,14 @@ static struct pmbus_driver_info tps53679_info = { static int tps53679_probe(struct i2c_client *client, const struct i2c_device_id *id) { - return pmbus_do_probe(client, id, &tps53679_info); + struct pmbus_driver_info *info; + + info = devm_kmemdup(&client->dev, &tps53679_info, sizeof(*info), + GFP_KERNEL); + if (!info) + return -ENOMEM; + + return pmbus_do_probe(client, id, info); } static const struct i2c_device_id tps53679_id[] = { diff --git a/drivers/hwmon/powr1220.c b/drivers/hwmon/powr1220.c index 3014e4ac741e..16c1c98e0e18 100644 --- a/drivers/hwmon/powr1220.c +++ b/drivers/hwmon/powr1220.c @@ -177,8 +177,9 @@ exit: } /* Shows the voltage associated with the specified ADC channel */ -static ssize_t powr1220_show_voltage(struct device *dev, - struct device_attribute *dev_attr, char *buf) +static ssize_t powr1220_voltage_show(struct device *dev, + struct device_attribute *dev_attr, + char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); int adc_val = powr1220_read_adc(dev, attr->index); @@ -190,8 +191,8 @@ static ssize_t powr1220_show_voltage(struct device *dev, } /* Shows the maximum setting associated with the specified ADC channel */ -static ssize_t powr1220_show_max(struct device *dev, - struct device_attribute *dev_attr, char *buf) +static ssize_t powr1220_max_show(struct device *dev, + struct device_attribute *dev_attr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct powr1220_data *data = dev_get_drvdata(dev); @@ -200,100 +201,59 @@ static ssize_t powr1220_show_max(struct device *dev, } /* Shows the label associated with the specified ADC channel */ -static ssize_t powr1220_show_label(struct device *dev, - struct device_attribute *dev_attr, char *buf) +static ssize_t powr1220_label_show(struct device *dev, + struct device_attribute *dev_attr, + char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); return sprintf(buf, "%s\n", input_names[attr->index]); } -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, powr1220_show_voltage, NULL, - VMON1); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, powr1220_show_voltage, NULL, - VMON2); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, powr1220_show_voltage, NULL, - VMON3); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, powr1220_show_voltage, NULL, - VMON4); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, powr1220_show_voltage, NULL, - VMON5); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, powr1220_show_voltage, NULL, - VMON6); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, powr1220_show_voltage, NULL, - VMON7); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, powr1220_show_voltage, NULL, - VMON8); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, powr1220_show_voltage, NULL, - VMON9); -static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, powr1220_show_voltage, NULL, - VMON10); -static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, powr1220_show_voltage, NULL, - VMON11); -static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, powr1220_show_voltage, NULL, - VMON12); -static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, powr1220_show_voltage, NULL, - VCCA); -static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, powr1220_show_voltage, NULL, - VCCINP); - -static SENSOR_DEVICE_ATTR(in0_highest, S_IRUGO, powr1220_show_max, NULL, - VMON1); -static SENSOR_DEVICE_ATTR(in1_highest, S_IRUGO, powr1220_show_max, NULL, - VMON2); -static SENSOR_DEVICE_ATTR(in2_highest, S_IRUGO, powr1220_show_max, NULL, - VMON3); -static SENSOR_DEVICE_ATTR(in3_highest, S_IRUGO, powr1220_show_max, NULL, - VMON4); -static SENSOR_DEVICE_ATTR(in4_highest, S_IRUGO, powr1220_show_max, NULL, - VMON5); -static SENSOR_DEVICE_ATTR(in5_highest, S_IRUGO, powr1220_show_max, NULL, - VMON6); -static SENSOR_DEVICE_ATTR(in6_highest, S_IRUGO, powr1220_show_max, NULL, - VMON7); -static SENSOR_DEVICE_ATTR(in7_highest, S_IRUGO, powr1220_show_max, NULL, - VMON8); -static SENSOR_DEVICE_ATTR(in8_highest, S_IRUGO, powr1220_show_max, NULL, - VMON9); -static SENSOR_DEVICE_ATTR(in9_highest, S_IRUGO, powr1220_show_max, NULL, - VMON10); -static SENSOR_DEVICE_ATTR(in10_highest, S_IRUGO, powr1220_show_max, NULL, - VMON11); -static SENSOR_DEVICE_ATTR(in11_highest, S_IRUGO, powr1220_show_max, NULL, - VMON12); -static SENSOR_DEVICE_ATTR(in12_highest, S_IRUGO, powr1220_show_max, NULL, - VCCA); -static SENSOR_DEVICE_ATTR(in13_highest, S_IRUGO, powr1220_show_max, NULL, - VCCINP); - -static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, powr1220_show_label, NULL, - VMON1); -static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, powr1220_show_label, NULL, - VMON2); -static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, powr1220_show_label, NULL, - VMON3); -static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, powr1220_show_label, NULL, - VMON4); -static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, powr1220_show_label, NULL, - VMON5); -static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, powr1220_show_label, NULL, - VMON6); -static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, powr1220_show_label, NULL, - VMON7); -static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, powr1220_show_label, NULL, - VMON8); -static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, powr1220_show_label, NULL, - VMON9); -static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, powr1220_show_label, NULL, - VMON10); -static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, powr1220_show_label, NULL, - VMON11); -static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, powr1220_show_label, NULL, - VMON12); -static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, powr1220_show_label, NULL, - VCCA); -static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, powr1220_show_label, NULL, - VCCINP); +static SENSOR_DEVICE_ATTR_RO(in0_input, powr1220_voltage, VMON1); +static SENSOR_DEVICE_ATTR_RO(in1_input, powr1220_voltage, VMON2); +static SENSOR_DEVICE_ATTR_RO(in2_input, powr1220_voltage, VMON3); +static SENSOR_DEVICE_ATTR_RO(in3_input, powr1220_voltage, VMON4); +static SENSOR_DEVICE_ATTR_RO(in4_input, powr1220_voltage, VMON5); +static SENSOR_DEVICE_ATTR_RO(in5_input, powr1220_voltage, VMON6); +static SENSOR_DEVICE_ATTR_RO(in6_input, powr1220_voltage, VMON7); +static SENSOR_DEVICE_ATTR_RO(in7_input, powr1220_voltage, VMON8); +static SENSOR_DEVICE_ATTR_RO(in8_input, powr1220_voltage, VMON9); +static SENSOR_DEVICE_ATTR_RO(in9_input, powr1220_voltage, VMON10); +static SENSOR_DEVICE_ATTR_RO(in10_input, powr1220_voltage, VMON11); +static SENSOR_DEVICE_ATTR_RO(in11_input, powr1220_voltage, VMON12); +static SENSOR_DEVICE_ATTR_RO(in12_input, powr1220_voltage, VCCA); +static SENSOR_DEVICE_ATTR_RO(in13_input, powr1220_voltage, VCCINP); + +static SENSOR_DEVICE_ATTR_RO(in0_highest, powr1220_max, VMON1); +static SENSOR_DEVICE_ATTR_RO(in1_highest, powr1220_max, VMON2); +static SENSOR_DEVICE_ATTR_RO(in2_highest, powr1220_max, VMON3); +static SENSOR_DEVICE_ATTR_RO(in3_highest, powr1220_max, VMON4); +static SENSOR_DEVICE_ATTR_RO(in4_highest, powr1220_max, VMON5); +static SENSOR_DEVICE_ATTR_RO(in5_highest, powr1220_max, VMON6); +static SENSOR_DEVICE_ATTR_RO(in6_highest, powr1220_max, VMON7); +static SENSOR_DEVICE_ATTR_RO(in7_highest, powr1220_max, VMON8); +static SENSOR_DEVICE_ATTR_RO(in8_highest, powr1220_max, VMON9); +static SENSOR_DEVICE_ATTR_RO(in9_highest, powr1220_max, VMON10); +static SENSOR_DEVICE_ATTR_RO(in10_highest, powr1220_max, VMON11); +static SENSOR_DEVICE_ATTR_RO(in11_highest, powr1220_max, VMON12); +static SENSOR_DEVICE_ATTR_RO(in12_highest, powr1220_max, VCCA); +static SENSOR_DEVICE_ATTR_RO(in13_highest, powr1220_max, VCCINP); + +static SENSOR_DEVICE_ATTR_RO(in0_label, powr1220_label, VMON1); +static SENSOR_DEVICE_ATTR_RO(in1_label, powr1220_label, VMON2); +static SENSOR_DEVICE_ATTR_RO(in2_label, powr1220_label, VMON3); +static SENSOR_DEVICE_ATTR_RO(in3_label, powr1220_label, VMON4); +static SENSOR_DEVICE_ATTR_RO(in4_label, powr1220_label, VMON5); +static SENSOR_DEVICE_ATTR_RO(in5_label, powr1220_label, VMON6); +static SENSOR_DEVICE_ATTR_RO(in6_label, powr1220_label, VMON7); +static SENSOR_DEVICE_ATTR_RO(in7_label, powr1220_label, VMON8); +static SENSOR_DEVICE_ATTR_RO(in8_label, powr1220_label, VMON9); +static SENSOR_DEVICE_ATTR_RO(in9_label, powr1220_label, VMON10); +static SENSOR_DEVICE_ATTR_RO(in10_label, powr1220_label, VMON11); +static SENSOR_DEVICE_ATTR_RO(in11_label, powr1220_label, VMON12); +static SENSOR_DEVICE_ATTR_RO(in12_label, powr1220_label, VCCA); +static SENSOR_DEVICE_ATTR_RO(in13_label, powr1220_label, VCCINP); static struct attribute *powr1220_attrs[] = { &sensor_dev_attr_in0_input.dev_attr.attr, diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c index 2c944825026f..167221c7628a 100644 --- a/drivers/hwmon/pwm-fan.c +++ b/drivers/hwmon/pwm-fan.c @@ -23,6 +23,7 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pwm.h> +#include <linux/regulator/consumer.h> #include <linux/sysfs.h> #include <linux/thermal.h> @@ -31,6 +32,7 @@ struct pwm_fan_ctx { struct mutex lock; struct pwm_device *pwm; + struct regulator *reg_en; unsigned int pwm_value; unsigned int pwm_fan_state; unsigned int pwm_fan_max_state; @@ -231,6 +233,21 @@ static int pwm_fan_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ctx); + ctx->reg_en = devm_regulator_get_optional(&pdev->dev, "fan"); + if (IS_ERR(ctx->reg_en)) { + if (PTR_ERR(ctx->reg_en) != -ENODEV) + return PTR_ERR(ctx->reg_en); + + ctx->reg_en = NULL; + } else { + ret = regulator_enable(ctx->reg_en); + if (ret) { + dev_err(&pdev->dev, + "Failed to enable fan supply: %d\n", ret); + return ret; + } + } + ctx->pwm_value = MAX_PWM; /* Set duty cycle to maximum allowed and enable PWM output */ @@ -241,7 +258,7 @@ static int pwm_fan_probe(struct platform_device *pdev) ret = pwm_apply_state(ctx->pwm, &state); if (ret) { dev_err(&pdev->dev, "Failed to configure PWM\n"); - return ret; + goto err_reg_disable; } hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, "pwmfan", @@ -277,6 +294,10 @@ err_pwm_disable: state.enabled = false; pwm_apply_state(ctx->pwm, &state); +err_reg_disable: + if (ctx->reg_en) + regulator_disable(ctx->reg_en); + return ret; } @@ -287,6 +308,10 @@ static int pwm_fan_remove(struct platform_device *pdev) thermal_cooling_device_unregister(ctx->cdev); if (ctx->pwm_value) pwm_disable(ctx->pwm); + + if (ctx->reg_en) + regulator_disable(ctx->reg_en); + return 0; } @@ -307,6 +332,14 @@ static int pwm_fan_suspend(struct device *dev) pwm_disable(ctx->pwm); } + if (ctx->reg_en) { + ret = regulator_disable(ctx->reg_en); + if (ret) { + dev_err(dev, "Failed to disable fan supply: %d\n", ret); + return ret; + } + } + return 0; } @@ -317,6 +350,14 @@ static int pwm_fan_resume(struct device *dev) unsigned long duty; int ret; + if (ctx->reg_en) { + ret = regulator_enable(ctx->reg_en); + if (ret) { + dev_err(dev, "Failed to enable fan supply: %d\n", ret); + return ret; + } + } + if (ctx->pwm_value == 0) return 0; diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c index 91544f2312e6..63cfbc5a86ed 100644 --- a/drivers/hwmon/sch5627.c +++ b/drivers/hwmon/sch5627.c @@ -211,8 +211,8 @@ static ssize_t name_show(struct device *dev, struct device_attribute *devattr, return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME); } -static ssize_t show_temp(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_show(struct device *dev, struct device_attribute *devattr, + char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5627_data *data = sch5627_update_device(dev); @@ -225,8 +225,8 @@ static ssize_t show_temp(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", val); } -static ssize_t show_temp_fault(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_fault_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5627_data *data = sch5627_update_device(dev); @@ -237,8 +237,8 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", data->temp[attr->index] == 0); } -static ssize_t show_temp_max(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_max_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5627_data *data = dev_get_drvdata(dev); @@ -248,8 +248,8 @@ static ssize_t show_temp_max(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", val); } -static ssize_t show_temp_crit(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_crit_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5627_data *data = dev_get_drvdata(dev); @@ -259,8 +259,8 @@ static ssize_t show_temp_crit(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", val); } -static ssize_t show_fan(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t fan_show(struct device *dev, struct device_attribute *devattr, + char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5627_data *data = sch5627_update_device(dev); @@ -276,8 +276,8 @@ static ssize_t show_fan(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", val); } -static ssize_t show_fan_fault(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t fan_fault_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5627_data *data = sch5627_update_device(dev); @@ -289,8 +289,8 @@ static ssize_t show_fan_fault(struct device *dev, struct device_attribute data->fan[attr->index] == 0xffff); } -static ssize_t show_fan_min(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t fan_min_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5627_data *data = dev_get_drvdata(dev); @@ -301,8 +301,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", val); } -static ssize_t show_in(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t in_show(struct device *dev, struct device_attribute *devattr, + char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5627_data *data = sch5627_update_device(dev); @@ -317,8 +317,8 @@ static ssize_t show_in(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", val); } -static ssize_t show_in_label(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t in_label_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -327,61 +327,61 @@ static ssize_t show_in_label(struct device *dev, struct device_attribute } static DEVICE_ATTR_RO(name); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5); -static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6); -static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7); -static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5); -static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_temp_fault, NULL, 6); -static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_temp_fault, NULL, 7); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5); -static SENSOR_DEVICE_ATTR(temp7_max, S_IRUGO, show_temp_max, NULL, 6); -static SENSOR_DEVICE_ATTR(temp8_max, S_IRUGO, show_temp_max, NULL, 7); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5); -static SENSOR_DEVICE_ATTR(temp7_crit, S_IRUGO, show_temp_crit, NULL, 6); -static SENSOR_DEVICE_ATTR(temp8_crit, S_IRUGO, show_temp_crit, NULL, 7); - -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); -static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3); -static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan_min, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan_min, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO, show_fan_min, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_min, S_IRUGO, show_fan_min, NULL, 3); - -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4); -static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_in_label, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_in_label, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_in_label, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_in_label, NULL, 3); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_input, temp, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_input, temp, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_input, temp, 5); +static SENSOR_DEVICE_ATTR_RO(temp7_input, temp, 6); +static SENSOR_DEVICE_ATTR_RO(temp8_input, temp, 7); +static SENSOR_DEVICE_ATTR_RO(temp1_fault, temp_fault, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_fault, temp_fault, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_fault, temp_fault, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_fault, temp_fault, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_fault, temp_fault, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_fault, temp_fault, 5); +static SENSOR_DEVICE_ATTR_RO(temp7_fault, temp_fault, 6); +static SENSOR_DEVICE_ATTR_RO(temp8_fault, temp_fault, 7); +static SENSOR_DEVICE_ATTR_RO(temp1_max, temp_max, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_max, temp_max, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_max, temp_max, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_max, temp_max, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_max, temp_max, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_max, temp_max, 5); +static SENSOR_DEVICE_ATTR_RO(temp7_max, temp_max, 6); +static SENSOR_DEVICE_ATTR_RO(temp8_max, temp_max, 7); +static SENSOR_DEVICE_ATTR_RO(temp1_crit, temp_crit, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_crit, temp_crit, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_crit, temp_crit, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_crit, temp_crit, 3); +static SENSOR_DEVICE_ATTR_RO(temp5_crit, temp_crit, 4); +static SENSOR_DEVICE_ATTR_RO(temp6_crit, temp_crit, 5); +static SENSOR_DEVICE_ATTR_RO(temp7_crit, temp_crit, 6); +static SENSOR_DEVICE_ATTR_RO(temp8_crit, temp_crit, 7); + +static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1); +static SENSOR_DEVICE_ATTR_RO(fan3_input, fan, 2); +static SENSOR_DEVICE_ATTR_RO(fan4_input, fan, 3); +static SENSOR_DEVICE_ATTR_RO(fan1_fault, fan_fault, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_fault, fan_fault, 1); +static SENSOR_DEVICE_ATTR_RO(fan3_fault, fan_fault, 2); +static SENSOR_DEVICE_ATTR_RO(fan4_fault, fan_fault, 3); +static SENSOR_DEVICE_ATTR_RO(fan1_min, fan_min, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_min, fan_min, 1); +static SENSOR_DEVICE_ATTR_RO(fan3_min, fan_min, 2); +static SENSOR_DEVICE_ATTR_RO(fan4_min, fan_min, 3); + +static SENSOR_DEVICE_ATTR_RO(in0_input, in, 0); +static SENSOR_DEVICE_ATTR_RO(in1_input, in, 1); +static SENSOR_DEVICE_ATTR_RO(in2_input, in, 2); +static SENSOR_DEVICE_ATTR_RO(in3_input, in, 3); +static SENSOR_DEVICE_ATTR_RO(in4_input, in, 4); +static SENSOR_DEVICE_ATTR_RO(in0_label, in_label, 0); +static SENSOR_DEVICE_ATTR_RO(in1_label, in_label, 1); +static SENSOR_DEVICE_ATTR_RO(in2_label, in_label, 2); +static SENSOR_DEVICE_ATTR_RO(in3_label, in_label, 3); static struct attribute *sch5627_attributes[] = { &dev_attr_name.attr, diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c index d24d7b6047f2..2a3825603a77 100644 --- a/drivers/hwmon/sch5636.c +++ b/drivers/hwmon/sch5636.c @@ -170,14 +170,14 @@ static int reg_to_rpm(u16 reg) return 5400540 / reg; } -static ssize_t show_name(struct device *dev, struct device_attribute *devattr, - char *buf) +static ssize_t name_show(struct device *dev, struct device_attribute *devattr, + char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME); } -static ssize_t show_in_value(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t in_value_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5636_data *data = sch5636_update_device(dev); @@ -192,8 +192,8 @@ static ssize_t show_in_value(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", val); } -static ssize_t show_in_label(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t in_label_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -201,8 +201,8 @@ static ssize_t show_in_label(struct device *dev, struct device_attribute SCH5636_IN_LABELS[attr->index]); } -static ssize_t show_temp_value(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_value_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5636_data *data = sch5636_update_device(dev); @@ -215,8 +215,8 @@ static ssize_t show_temp_value(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", val); } -static ssize_t show_temp_fault(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_fault_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5636_data *data = sch5636_update_device(dev); @@ -229,8 +229,8 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", val); } -static ssize_t show_temp_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_alarm_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5636_data *data = sch5636_update_device(dev); @@ -243,8 +243,8 @@ static ssize_t show_temp_alarm(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", val); } -static ssize_t show_fan_value(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t fan_value_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5636_data *data = sch5636_update_device(dev); @@ -260,8 +260,8 @@ static ssize_t show_fan_value(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", val); } -static ssize_t show_fan_fault(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t fan_fault_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5636_data *data = sch5636_update_device(dev); @@ -274,8 +274,8 @@ static ssize_t show_fan_fault(struct device *dev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", val); } -static ssize_t show_fan_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t fan_alarm_show(struct device *dev, + struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sch5636_data *data = sch5636_update_device(dev); @@ -289,95 +289,95 @@ static ssize_t show_fan_alarm(struct device *dev, struct device_attribute } static struct sensor_device_attribute sch5636_attr[] = { - SENSOR_ATTR(name, 0444, show_name, NULL, 0), - SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0), - SENSOR_ATTR(in0_label, 0444, show_in_label, NULL, 0), - SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1), - SENSOR_ATTR(in1_label, 0444, show_in_label, NULL, 1), - SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2), - SENSOR_ATTR(in2_label, 0444, show_in_label, NULL, 2), - SENSOR_ATTR(in3_input, 0444, show_in_value, NULL, 3), - SENSOR_ATTR(in3_label, 0444, show_in_label, NULL, 3), - SENSOR_ATTR(in4_input, 0444, show_in_value, NULL, 4), - SENSOR_ATTR(in4_label, 0444, show_in_label, NULL, 4), + SENSOR_ATTR_RO(name, name, 0), + SENSOR_ATTR_RO(in0_input, in_value, 0), + SENSOR_ATTR_RO(in0_label, in_label, 0), + SENSOR_ATTR_RO(in1_input, in_value, 1), + SENSOR_ATTR_RO(in1_label, in_label, 1), + SENSOR_ATTR_RO(in2_input, in_value, 2), + SENSOR_ATTR_RO(in2_label, in_label, 2), + SENSOR_ATTR_RO(in3_input, in_value, 3), + SENSOR_ATTR_RO(in3_label, in_label, 3), + SENSOR_ATTR_RO(in4_input, in_value, 4), + SENSOR_ATTR_RO(in4_label, in_label, 4), }; static struct sensor_device_attribute sch5636_temp_attr[] = { - SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0), - SENSOR_ATTR(temp1_fault, 0444, show_temp_fault, NULL, 0), - SENSOR_ATTR(temp1_alarm, 0444, show_temp_alarm, NULL, 0), - SENSOR_ATTR(temp2_input, 0444, show_temp_value, NULL, 1), - SENSOR_ATTR(temp2_fault, 0444, show_temp_fault, NULL, 1), - SENSOR_ATTR(temp2_alarm, 0444, show_temp_alarm, NULL, 1), - SENSOR_ATTR(temp3_input, 0444, show_temp_value, NULL, 2), - SENSOR_ATTR(temp3_fault, 0444, show_temp_fault, NULL, 2), - SENSOR_ATTR(temp3_alarm, 0444, show_temp_alarm, NULL, 2), - SENSOR_ATTR(temp4_input, 0444, show_temp_value, NULL, 3), - SENSOR_ATTR(temp4_fault, 0444, show_temp_fault, NULL, 3), - SENSOR_ATTR(temp4_alarm, 0444, show_temp_alarm, NULL, 3), - SENSOR_ATTR(temp5_input, 0444, show_temp_value, NULL, 4), - SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4), - SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4), - SENSOR_ATTR(temp6_input, 0444, show_temp_value, NULL, 5), - SENSOR_ATTR(temp6_fault, 0444, show_temp_fault, NULL, 5), - SENSOR_ATTR(temp6_alarm, 0444, show_temp_alarm, NULL, 5), - SENSOR_ATTR(temp7_input, 0444, show_temp_value, NULL, 6), - SENSOR_ATTR(temp7_fault, 0444, show_temp_fault, NULL, 6), - SENSOR_ATTR(temp7_alarm, 0444, show_temp_alarm, NULL, 6), - SENSOR_ATTR(temp8_input, 0444, show_temp_value, NULL, 7), - SENSOR_ATTR(temp8_fault, 0444, show_temp_fault, NULL, 7), - SENSOR_ATTR(temp8_alarm, 0444, show_temp_alarm, NULL, 7), - SENSOR_ATTR(temp9_input, 0444, show_temp_value, NULL, 8), - SENSOR_ATTR(temp9_fault, 0444, show_temp_fault, NULL, 8), - SENSOR_ATTR(temp9_alarm, 0444, show_temp_alarm, NULL, 8), - SENSOR_ATTR(temp10_input, 0444, show_temp_value, NULL, 9), - SENSOR_ATTR(temp10_fault, 0444, show_temp_fault, NULL, 9), - SENSOR_ATTR(temp10_alarm, 0444, show_temp_alarm, NULL, 9), - SENSOR_ATTR(temp11_input, 0444, show_temp_value, NULL, 10), - SENSOR_ATTR(temp11_fault, 0444, show_temp_fault, NULL, 10), - SENSOR_ATTR(temp11_alarm, 0444, show_temp_alarm, NULL, 10), - SENSOR_ATTR(temp12_input, 0444, show_temp_value, NULL, 11), - SENSOR_ATTR(temp12_fault, 0444, show_temp_fault, NULL, 11), - SENSOR_ATTR(temp12_alarm, 0444, show_temp_alarm, NULL, 11), - SENSOR_ATTR(temp13_input, 0444, show_temp_value, NULL, 12), - SENSOR_ATTR(temp13_fault, 0444, show_temp_fault, NULL, 12), - SENSOR_ATTR(temp13_alarm, 0444, show_temp_alarm, NULL, 12), - SENSOR_ATTR(temp14_input, 0444, show_temp_value, NULL, 13), - SENSOR_ATTR(temp14_fault, 0444, show_temp_fault, NULL, 13), - SENSOR_ATTR(temp14_alarm, 0444, show_temp_alarm, NULL, 13), - SENSOR_ATTR(temp15_input, 0444, show_temp_value, NULL, 14), - SENSOR_ATTR(temp15_fault, 0444, show_temp_fault, NULL, 14), - SENSOR_ATTR(temp15_alarm, 0444, show_temp_alarm, NULL, 14), - SENSOR_ATTR(temp16_input, 0444, show_temp_value, NULL, 15), - SENSOR_ATTR(temp16_fault, 0444, show_temp_fault, NULL, 15), - SENSOR_ATTR(temp16_alarm, 0444, show_temp_alarm, NULL, 15), + SENSOR_ATTR_RO(temp1_input, temp_value, 0), + SENSOR_ATTR_RO(temp1_fault, temp_fault, 0), + SENSOR_ATTR_RO(temp1_alarm, temp_alarm, 0), + SENSOR_ATTR_RO(temp2_input, temp_value, 1), + SENSOR_ATTR_RO(temp2_fault, temp_fault, 1), + SENSOR_ATTR_RO(temp2_alarm, temp_alarm, 1), + SENSOR_ATTR_RO(temp3_input, temp_value, 2), + SENSOR_ATTR_RO(temp3_fault, temp_fault, 2), + SENSOR_ATTR_RO(temp3_alarm, temp_alarm, 2), + SENSOR_ATTR_RO(temp4_input, temp_value, 3), + SENSOR_ATTR_RO(temp4_fault, temp_fault, 3), + SENSOR_ATTR_RO(temp4_alarm, temp_alarm, 3), + SENSOR_ATTR_RO(temp5_input, temp_value, 4), + SENSOR_ATTR_RO(temp5_fault, temp_fault, 4), + SENSOR_ATTR_RO(temp5_alarm, temp_alarm, 4), + SENSOR_ATTR_RO(temp6_input, temp_value, 5), + SENSOR_ATTR_RO(temp6_fault, temp_fault, 5), + SENSOR_ATTR_RO(temp6_alarm, temp_alarm, 5), + SENSOR_ATTR_RO(temp7_input, temp_value, 6), + SENSOR_ATTR_RO(temp7_fault, temp_fault, 6), + SENSOR_ATTR_RO(temp7_alarm, temp_alarm, 6), + SENSOR_ATTR_RO(temp8_input, temp_value, 7), + SENSOR_ATTR_RO(temp8_fault, temp_fault, 7), + SENSOR_ATTR_RO(temp8_alarm, temp_alarm, 7), + SENSOR_ATTR_RO(temp9_input, temp_value, 8), + SENSOR_ATTR_RO(temp9_fault, temp_fault, 8), + SENSOR_ATTR_RO(temp9_alarm, temp_alarm, 8), + SENSOR_ATTR_RO(temp10_input, temp_value, 9), + SENSOR_ATTR_RO(temp10_fault, temp_fault, 9), + SENSOR_ATTR_RO(temp10_alarm, temp_alarm, 9), + SENSOR_ATTR_RO(temp11_input, temp_value, 10), + SENSOR_ATTR_RO(temp11_fault, temp_fault, 10), + SENSOR_ATTR_RO(temp11_alarm, temp_alarm, 10), + SENSOR_ATTR_RO(temp12_input, temp_value, 11), + SENSOR_ATTR_RO(temp12_fault, temp_fault, 11), + SENSOR_ATTR_RO(temp12_alarm, temp_alarm, 11), + SENSOR_ATTR_RO(temp13_input, temp_value, 12), + SENSOR_ATTR_RO(temp13_fault, temp_fault, 12), + SENSOR_ATTR_RO(temp13_alarm, temp_alarm, 12), + SENSOR_ATTR_RO(temp14_input, temp_value, 13), + SENSOR_ATTR_RO(temp14_fault, temp_fault, 13), + SENSOR_ATTR_RO(temp14_alarm, temp_alarm, 13), + SENSOR_ATTR_RO(temp15_input, temp_value, 14), + SENSOR_ATTR_RO(temp15_fault, temp_fault, 14), + SENSOR_ATTR_RO(temp15_alarm, temp_alarm, 14), + SENSOR_ATTR_RO(temp16_input, temp_value, 15), + SENSOR_ATTR_RO(temp16_fault, temp_fault, 15), + SENSOR_ATTR_RO(temp16_alarm, temp_alarm, 15), }; static struct sensor_device_attribute sch5636_fan_attr[] = { - SENSOR_ATTR(fan1_input, 0444, show_fan_value, NULL, 0), - SENSOR_ATTR(fan1_fault, 0444, show_fan_fault, NULL, 0), - SENSOR_ATTR(fan1_alarm, 0444, show_fan_alarm, NULL, 0), - SENSOR_ATTR(fan2_input, 0444, show_fan_value, NULL, 1), - SENSOR_ATTR(fan2_fault, 0444, show_fan_fault, NULL, 1), - SENSOR_ATTR(fan2_alarm, 0444, show_fan_alarm, NULL, 1), - SENSOR_ATTR(fan3_input, 0444, show_fan_value, NULL, 2), - SENSOR_ATTR(fan3_fault, 0444, show_fan_fault, NULL, 2), - SENSOR_ATTR(fan3_alarm, 0444, show_fan_alarm, NULL, 2), - SENSOR_ATTR(fan4_input, 0444, show_fan_value, NULL, 3), - SENSOR_ATTR(fan4_fault, 0444, show_fan_fault, NULL, 3), - SENSOR_ATTR(fan4_alarm, 0444, show_fan_alarm, NULL, 3), - SENSOR_ATTR(fan5_input, 0444, show_fan_value, NULL, 4), - SENSOR_ATTR(fan5_fault, 0444, show_fan_fault, NULL, 4), - SENSOR_ATTR(fan5_alarm, 0444, show_fan_alarm, NULL, 4), - SENSOR_ATTR(fan6_input, 0444, show_fan_value, NULL, 5), - SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5), - SENSOR_ATTR(fan6_alarm, 0444, show_fan_alarm, NULL, 5), - SENSOR_ATTR(fan7_input, 0444, show_fan_value, NULL, 6), - SENSOR_ATTR(fan7_fault, 0444, show_fan_fault, NULL, 6), - SENSOR_ATTR(fan7_alarm, 0444, show_fan_alarm, NULL, 6), - SENSOR_ATTR(fan8_input, 0444, show_fan_value, NULL, 7), - SENSOR_ATTR(fan8_fault, 0444, show_fan_fault, NULL, 7), - SENSOR_ATTR(fan8_alarm, 0444, show_fan_alarm, NULL, 7), + SENSOR_ATTR_RO(fan1_input, fan_value, 0), + SENSOR_ATTR_RO(fan1_fault, fan_fault, 0), + SENSOR_ATTR_RO(fan1_alarm, fan_alarm, 0), + SENSOR_ATTR_RO(fan2_input, fan_value, 1), + SENSOR_ATTR_RO(fan2_fault, fan_fault, 1), + SENSOR_ATTR_RO(fan2_alarm, fan_alarm, 1), + SENSOR_ATTR_RO(fan3_input, fan_value, 2), + SENSOR_ATTR_RO(fan3_fault, fan_fault, 2), + SENSOR_ATTR_RO(fan3_alarm, fan_alarm, 2), + SENSOR_ATTR_RO(fan4_input, fan_value, 3), + SENSOR_ATTR_RO(fan4_fault, fan_fault, 3), + SENSOR_ATTR_RO(fan4_alarm, fan_alarm, 3), + SENSOR_ATTR_RO(fan5_input, fan_value, 4), + SENSOR_ATTR_RO(fan5_fault, fan_fault, 4), + SENSOR_ATTR_RO(fan5_alarm, fan_alarm, 4), + SENSOR_ATTR_RO(fan6_input, fan_value, 5), + SENSOR_ATTR_RO(fan6_fault, fan_fault, 5), + SENSOR_ATTR_RO(fan6_alarm, fan_alarm, 5), + SENSOR_ATTR_RO(fan7_input, fan_value, 6), + SENSOR_ATTR_RO(fan7_fault, fan_fault, 6), + SENSOR_ATTR_RO(fan7_alarm, fan_alarm, 6), + SENSOR_ATTR_RO(fan8_input, fan_value, 7), + SENSOR_ATTR_RO(fan8_fault, fan_fault, 7), + SENSOR_ATTR_RO(fan8_alarm, fan_alarm, 7), }; static int sch5636_remove(struct platform_device *pdev) diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c index 2e005edee0c9..a80183a488c5 100644 --- a/drivers/hwmon/scmi-hwmon.c +++ b/drivers/hwmon/scmi-hwmon.c @@ -57,7 +57,7 @@ scmi_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type, sensor = *(scmi_sensors->info[type] + channel); if (sensor) - return S_IRUGO; + return 0444; return 0; } diff --git a/drivers/hwmon/scpi-hwmon.c b/drivers/hwmon/scpi-hwmon.c index 111d521e2189..9bfa228d0eb0 100644 --- a/drivers/hwmon/scpi-hwmon.c +++ b/drivers/hwmon/scpi-hwmon.c @@ -226,11 +226,11 @@ static int scpi_hwmon_probe(struct platform_device *pdev) sensor->scale = scale[sensor->info.class]; - sensor->dev_attr_input.attr.mode = S_IRUGO; + sensor->dev_attr_input.attr.mode = 0444; sensor->dev_attr_input.show = scpi_show_sensor; sensor->dev_attr_input.attr.name = sensor->input; - sensor->dev_attr_label.attr.mode = S_IRUGO; + sensor->dev_attr_label.attr.mode = 0444; sensor->dev_attr_label.show = scpi_show_label; sensor->dev_attr_label.attr.name = sensor->label; diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index c878242f3486..39b41e35c2bf 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c @@ -677,9 +677,8 @@ static inline int sht15_calc_humid(struct sht15_data *data) * and heater_enable sysfs attributes. * Returns number of bytes written into buffer, negative errno on error. */ -static ssize_t sht15_show_status(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t sht15_status_show(struct device *dev, + struct device_attribute *attr, char *buf) { int ret; struct sht15_data *data = dev_get_drvdata(dev); @@ -700,7 +699,7 @@ static ssize_t sht15_show_status(struct device *dev, * Will be called on write access to heater_enable sysfs attribute. * Returns number of bytes actually decoded, negative errno on error. */ -static ssize_t sht15_store_heater(struct device *dev, +static ssize_t sht15_status_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -734,9 +733,8 @@ static ssize_t sht15_store_heater(struct device *dev, * Will be called on read access to temp1_input sysfs attribute. * Returns number of bytes written into buffer, negative errno on error. */ -static ssize_t sht15_show_temp(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t sht15_temp_show(struct device *dev, + struct device_attribute *attr, char *buf) { int ret; struct sht15_data *data = dev_get_drvdata(dev); @@ -757,9 +755,8 @@ static ssize_t sht15_show_temp(struct device *dev, * Will be called on read access to humidity1_input sysfs attribute. * Returns number of bytes written into buffer, negative errno on error. */ -static ssize_t sht15_show_humidity(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t sht15_humidity_show(struct device *dev, + struct device_attribute *attr, char *buf) { int ret; struct sht15_data *data = dev_get_drvdata(dev); @@ -777,16 +774,13 @@ static ssize_t name_show(struct device *dev, return sprintf(buf, "%s\n", pdev->name); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, - sht15_show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, - sht15_show_humidity, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, sht15_show_status, NULL, - SHT15_STATUS_LOW_BATTERY); -static SENSOR_DEVICE_ATTR(humidity1_fault, S_IRUGO, sht15_show_status, NULL, - SHT15_STATUS_LOW_BATTERY); -static SENSOR_DEVICE_ATTR(heater_enable, S_IRUGO | S_IWUSR, sht15_show_status, - sht15_store_heater, SHT15_STATUS_HEATER); +static SENSOR_DEVICE_ATTR_RO(temp1_input, sht15_temp, 0); +static SENSOR_DEVICE_ATTR_RO(humidity1_input, sht15_humidity, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_fault, sht15_status, + SHT15_STATUS_LOW_BATTERY); +static SENSOR_DEVICE_ATTR_RO(humidity1_fault, sht15_status, + SHT15_STATUS_LOW_BATTERY); +static SENSOR_DEVICE_ATTR_RW(heater_enable, sht15_status, SHT15_STATUS_HEATER); static DEVICE_ATTR_RO(name); static struct attribute *sht15_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c index 2c7ba70921f5..df112b73b635 100644 --- a/drivers/hwmon/sht21.c +++ b/drivers/hwmon/sht21.c @@ -135,9 +135,9 @@ out: * Will be called on read access to temp1_input sysfs attribute. * Returns number of bytes written into buffer, negative errno on error. */ -static ssize_t sht21_show_temperature(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t sht21_temperature_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct sht21 *sht21 = dev_get_drvdata(dev); int ret; @@ -157,9 +157,8 @@ static ssize_t sht21_show_temperature(struct device *dev, * Will be called on read access to humidity1_input sysfs attribute. * Returns number of bytes written into buffer, negative errno on error. */ -static ssize_t sht21_show_humidity(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t sht21_humidity_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct sht21 *sht21 = dev_get_drvdata(dev); int ret; @@ -251,10 +250,8 @@ static ssize_t eic_show(struct device *dev, } /* sysfs attributes */ -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sht21_show_temperature, - NULL, 0); -static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity, - NULL, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_input, sht21_temperature, 0); +static SENSOR_DEVICE_ATTR_RO(humidity1_input, sht21_humidity, 0); static DEVICE_ATTR_RO(eic); static struct attribute *sht21_attrs[] = { diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c index 370b57dafab7..81ebc96cdec9 100644 --- a/drivers/hwmon/sht3x.c +++ b/drivers/hwmon/sht3x.c @@ -629,40 +629,22 @@ out: return count; } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, temp1_input_show, NULL, 0); -static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, humidity1_input_show, - NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, - temp1_limit_show, temp1_limit_store, - limit_max); -static SENSOR_DEVICE_ATTR(humidity1_max, S_IRUGO | S_IWUSR, - humidity1_limit_show, humidity1_limit_store, - limit_max); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, - temp1_limit_show, temp1_limit_store, - limit_max_hyst); -static SENSOR_DEVICE_ATTR(humidity1_max_hyst, S_IRUGO | S_IWUSR, - humidity1_limit_show, humidity1_limit_store, - limit_max_hyst); -static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, - temp1_limit_show, temp1_limit_store, - limit_min); -static SENSOR_DEVICE_ATTR(humidity1_min, S_IRUGO | S_IWUSR, - humidity1_limit_show, humidity1_limit_store, - limit_min); -static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO | S_IWUSR, - temp1_limit_show, temp1_limit_store, - limit_min_hyst); -static SENSOR_DEVICE_ATTR(humidity1_min_hyst, S_IRUGO | S_IWUSR, - humidity1_limit_show, humidity1_limit_store, - limit_min_hyst); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, temp1_alarm_show, NULL, 0); -static SENSOR_DEVICE_ATTR(humidity1_alarm, S_IRUGO, humidity1_alarm_show, - NULL, 0); -static SENSOR_DEVICE_ATTR(heater_enable, S_IRUGO | S_IWUSR, - heater_enable_show, heater_enable_store, 0); -static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, - update_interval_show, update_interval_store, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp1_input, 0); +static SENSOR_DEVICE_ATTR_RO(humidity1_input, humidity1_input, 0); +static SENSOR_DEVICE_ATTR_RW(temp1_max, temp1_limit, limit_max); +static SENSOR_DEVICE_ATTR_RW(humidity1_max, humidity1_limit, limit_max); +static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp1_limit, limit_max_hyst); +static SENSOR_DEVICE_ATTR_RW(humidity1_max_hyst, humidity1_limit, + limit_max_hyst); +static SENSOR_DEVICE_ATTR_RW(temp1_min, temp1_limit, limit_min); +static SENSOR_DEVICE_ATTR_RW(humidity1_min, humidity1_limit, limit_min); +static SENSOR_DEVICE_ATTR_RW(temp1_min_hyst, temp1_limit, limit_min_hyst); +static SENSOR_DEVICE_ATTR_RW(humidity1_min_hyst, humidity1_limit, + limit_min_hyst); +static SENSOR_DEVICE_ATTR_RO(temp1_alarm, temp1_alarm, 0); +static SENSOR_DEVICE_ATTR_RO(humidity1_alarm, humidity1_alarm, 0); +static SENSOR_DEVICE_ATTR_RW(heater_enable, heater_enable, 0); +static SENSOR_DEVICE_ATTR_RW(update_interval, update_interval, 0); static struct attribute *sht3x_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index 6bd200756560..c0775084dde0 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c @@ -164,18 +164,18 @@ static int temp_from_reg(u8 reg) return (s8)reg * 1000; } -static ssize_t show_temp(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t temp_show(struct device *dev, struct device_attribute *devattr, + char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct smsc47b397_data *data = smsc47b397_update_device(dev); return sprintf(buf, "%d\n", temp_from_reg(data->temp[attr->index])); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2); +static SENSOR_DEVICE_ATTR_RO(temp4_input, temp, 3); /* * FAN: 1 RPM/bit @@ -188,17 +188,17 @@ static int fan_from_reg(u16 reg) return 90000 * 60 / reg; } -static ssize_t show_fan(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t fan_show(struct device *dev, struct device_attribute *devattr, + char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct smsc47b397_data *data = smsc47b397_update_device(dev); return sprintf(buf, "%d\n", fan_from_reg(data->fan[attr->index])); } -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); +static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1); +static SENSOR_DEVICE_ATTR_RO(fan3_input, fan, 2); +static SENSOR_DEVICE_ATTR_RO(fan4_input, fan, 3); static struct attribute *smsc47b397_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c index 7fe152d92350..90b60297f2f7 100644 --- a/drivers/hwmon/stts751.c +++ b/drivers/hwmon/stts751.c @@ -382,8 +382,8 @@ static int stts751_update(struct stts751_priv *priv) return 0; } -static ssize_t show_max_alarm(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t max_alarm_show(struct device *dev, + struct device_attribute *attr, char *buf) { int ret; struct stts751_priv *priv = dev_get_drvdata(dev); @@ -399,8 +399,8 @@ static ssize_t show_max_alarm(struct device *dev, struct device_attribute *attr, return snprintf(buf, PAGE_SIZE, "%d\n", priv->max_alert); } -static ssize_t show_min_alarm(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t min_alarm_show(struct device *dev, + struct device_attribute *attr, char *buf) { int ret; struct stts751_priv *priv = dev_get_drvdata(dev); @@ -416,7 +416,7 @@ static ssize_t show_min_alarm(struct device *dev, struct device_attribute *attr, return snprintf(buf, PAGE_SIZE, "%d\n", priv->min_alert); } -static ssize_t show_input(struct device *dev, struct device_attribute *attr, +static ssize_t input_show(struct device *dev, struct device_attribute *attr, char *buf) { int ret; @@ -431,7 +431,7 @@ static ssize_t show_input(struct device *dev, struct device_attribute *attr, return snprintf(buf, PAGE_SIZE, "%d\n", priv->temp); } -static ssize_t show_therm(struct device *dev, struct device_attribute *attr, +static ssize_t therm_show(struct device *dev, struct device_attribute *attr, char *buf) { struct stts751_priv *priv = dev_get_drvdata(dev); @@ -439,8 +439,8 @@ static ssize_t show_therm(struct device *dev, struct device_attribute *attr, return snprintf(buf, PAGE_SIZE, "%d\n", priv->therm); } -static ssize_t set_therm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t therm_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { int ret; long temp; @@ -473,7 +473,7 @@ exit: return count; } -static ssize_t show_hyst(struct device *dev, struct device_attribute *attr, +static ssize_t hyst_show(struct device *dev, struct device_attribute *attr, char *buf) { struct stts751_priv *priv = dev_get_drvdata(dev); @@ -481,8 +481,8 @@ static ssize_t show_hyst(struct device *dev, struct device_attribute *attr, return snprintf(buf, PAGE_SIZE, "%d\n", priv->hyst); } -static ssize_t set_hyst(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t hyst_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { int ret; long temp; @@ -506,7 +506,7 @@ static ssize_t set_hyst(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t show_therm_trip(struct device *dev, +static ssize_t therm_trip_show(struct device *dev, struct device_attribute *attr, char *buf) { int ret; @@ -521,7 +521,7 @@ static ssize_t show_therm_trip(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", priv->therm_trip); } -static ssize_t show_max(struct device *dev, struct device_attribute *attr, +static ssize_t max_show(struct device *dev, struct device_attribute *attr, char *buf) { struct stts751_priv *priv = dev_get_drvdata(dev); @@ -529,8 +529,8 @@ static ssize_t show_max(struct device *dev, struct device_attribute *attr, return snprintf(buf, PAGE_SIZE, "%d\n", priv->event_max); } -static ssize_t set_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t max_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { int ret; long temp; @@ -555,7 +555,7 @@ exit: return ret; } -static ssize_t show_min(struct device *dev, struct device_attribute *attr, +static ssize_t min_show(struct device *dev, struct device_attribute *attr, char *buf) { struct stts751_priv *priv = dev_get_drvdata(dev); @@ -563,8 +563,8 @@ static ssize_t show_min(struct device *dev, struct device_attribute *attr, return snprintf(buf, PAGE_SIZE, "%d\n", priv->event_min); } -static ssize_t set_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t min_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { int ret; long temp; @@ -589,8 +589,8 @@ exit: return ret; } -static ssize_t show_interval(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t interval_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct stts751_priv *priv = dev_get_drvdata(dev); @@ -598,8 +598,9 @@ static ssize_t show_interval(struct device *dev, struct device_attribute *attr, stts751_intervals[priv->interval]); } -static ssize_t set_interval(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t interval_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { unsigned long val; int idx; @@ -746,16 +747,15 @@ static int stts751_read_chip_config(struct stts751_priv *priv) return 0; } -static SENSOR_DEVICE_ATTR(temp1_input, 0444, show_input, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_min, 0644, show_min, set_min, 0); -static SENSOR_DEVICE_ATTR(temp1_max, 0644, show_max, set_max, 0); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, 0444, show_min_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, 0444, show_max_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_crit, 0644, show_therm, set_therm, 0); -static SENSOR_DEVICE_ATTR(temp1_crit_hyst, 0644, show_hyst, set_hyst, 0); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, 0444, show_therm_trip, NULL, 0); -static SENSOR_DEVICE_ATTR(update_interval, 0644, - show_interval, set_interval, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_input, input, 0); +static SENSOR_DEVICE_ATTR_RW(temp1_min, min, 0); +static SENSOR_DEVICE_ATTR_RW(temp1_max, max, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, min_alarm, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, max_alarm, 0); +static SENSOR_DEVICE_ATTR_RW(temp1_crit, therm, 0); +static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, hyst, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, therm_trip, 0); +static SENSOR_DEVICE_ATTR_RW(update_interval, interval, 0); static struct attribute *stts751_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, diff --git a/drivers/hwmon/tc654.c b/drivers/hwmon/tc654.c index 18136e1f95fd..81dd229d7db4 100644 --- a/drivers/hwmon/tc654.c +++ b/drivers/hwmon/tc654.c @@ -200,7 +200,7 @@ out: * sysfs attributes */ -static ssize_t show_fan(struct device *dev, struct device_attribute *da, +static ssize_t fan_show(struct device *dev, struct device_attribute *da, char *buf) { int nr = to_sensor_dev_attr(da)->index; @@ -218,7 +218,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *da, return sprintf(buf, "%d\n", val); } -static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, +static ssize_t fan_min_show(struct device *dev, struct device_attribute *da, char *buf) { int nr = to_sensor_dev_attr(da)->index; @@ -231,8 +231,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, TC654_FAN_FAULT_FROM_REG(data->fan_fault[nr])); } -static ssize_t set_fan_min(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) +static ssize_t fan_min_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { int nr = to_sensor_dev_attr(da)->index; struct tc654_data *data = dev_get_drvdata(dev); @@ -255,7 +255,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *da, return ret < 0 ? ret : count; } -static ssize_t show_fan_alarm(struct device *dev, struct device_attribute *da, +static ssize_t fan_alarm_show(struct device *dev, struct device_attribute *da, char *buf) { int nr = to_sensor_dev_attr(da)->index; @@ -275,8 +275,8 @@ static ssize_t show_fan_alarm(struct device *dev, struct device_attribute *da, static const u8 TC654_FAN_PULSE_SHIFT[] = { 1, 3 }; -static ssize_t show_fan_pulses(struct device *dev, struct device_attribute *da, - char *buf) +static ssize_t fan_pulses_show(struct device *dev, + struct device_attribute *da, char *buf) { int nr = to_sensor_dev_attr(da)->index; struct tc654_data *data = tc654_update_client(dev); @@ -289,8 +289,9 @@ static ssize_t show_fan_pulses(struct device *dev, struct device_attribute *da, return sprintf(buf, "%d\n", val); } -static ssize_t set_fan_pulses(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) +static ssize_t fan_pulses_store(struct device *dev, + struct device_attribute *da, const char *buf, + size_t count) { int nr = to_sensor_dev_attr(da)->index; struct tc654_data *data = dev_get_drvdata(dev); @@ -329,8 +330,8 @@ static ssize_t set_fan_pulses(struct device *dev, struct device_attribute *da, return ret < 0 ? ret : count; } -static ssize_t show_pwm_mode(struct device *dev, - struct device_attribute *da, char *buf) +static ssize_t pwm_mode_show(struct device *dev, struct device_attribute *da, + char *buf) { struct tc654_data *data = tc654_update_client(dev); @@ -340,9 +341,8 @@ static ssize_t show_pwm_mode(struct device *dev, return sprintf(buf, "%d\n", !!(data->config & TC654_REG_CONFIG_DUTYC)); } -static ssize_t set_pwm_mode(struct device *dev, - struct device_attribute *da, - const char *buf, size_t count) +static ssize_t pwm_mode_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { struct tc654_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -371,7 +371,7 @@ static ssize_t set_pwm_mode(struct device *dev, static const int tc654_pwm_map[16] = { 77, 88, 102, 112, 124, 136, 148, 160, 172, 184, 196, 207, 219, 231, 243, 255}; -static ssize_t show_pwm(struct device *dev, struct device_attribute *da, +static ssize_t pwm_show(struct device *dev, struct device_attribute *da, char *buf) { struct tc654_data *data = tc654_update_client(dev); @@ -388,8 +388,8 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *da, return sprintf(buf, "%d\n", pwm); } -static ssize_t set_pwm(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) +static ssize_t pwm_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { struct tc654_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; @@ -423,22 +423,16 @@ out: return ret < 0 ? ret : count; } -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(fan1_pulses, S_IWUSR | S_IRUGO, show_fan_pulses, - set_fan_pulses, 0); -static SENSOR_DEVICE_ATTR(fan2_pulses, S_IWUSR | S_IRUGO, show_fan_pulses, - set_fan_pulses, 1); -static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, - show_pwm_mode, set_pwm_mode, 0); -static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, - set_pwm, 0); +static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1); +static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0); +static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1); +static SENSOR_DEVICE_ATTR_RO(fan1_alarm, fan_alarm, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_alarm, fan_alarm, 1); +static SENSOR_DEVICE_ATTR_RW(fan1_pulses, fan_pulses, 0); +static SENSOR_DEVICE_ATTR_RW(fan2_pulses, fan_pulses, 1); +static SENSOR_DEVICE_ATTR_RW(pwm1_mode, pwm_mode, 0); +static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0); /* Driver data */ static struct attribute *tc654_attrs[] = { diff --git a/drivers/hwmon/tc74.c b/drivers/hwmon/tc74.c index d95165158800..fa306bb681bb 100644 --- a/drivers/hwmon/tc74.c +++ b/drivers/hwmon/tc74.c @@ -86,7 +86,7 @@ ret_unlock: return ret; } -static ssize_t show_temp_input(struct device *dev, +static ssize_t temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) { struct tc74_data *data = dev_get_drvdata(dev); @@ -98,7 +98,7 @@ static ssize_t show_temp_input(struct device *dev, return sprintf(buf, "%d\n", data->temp_input * 1000); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0); static struct attribute *tc74_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index 6778283e36f9..35523d315f25 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c @@ -141,10 +141,10 @@ static umode_t tmp102_is_visible(const void *data, enum hwmon_sensor_types type, switch (attr) { case hwmon_temp_input: - return S_IRUGO; + return 0444; case hwmon_temp_max_hyst: case hwmon_temp_max: - return S_IRUGO | S_IWUSR; + return 0644; default: return 0; } diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c index 7f85b14544df..bda0fdc1eb53 100644 --- a/drivers/hwmon/tmp103.c +++ b/drivers/hwmon/tmp103.c @@ -61,9 +61,8 @@ static inline u8 tmp103_mc_to_reg(int val) return DIV_ROUND_CLOSEST(val, 1000); } -static ssize_t tmp103_show_temp(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t tmp103_temp_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); struct regmap *regmap = dev_get_drvdata(dev); @@ -77,9 +76,9 @@ static ssize_t tmp103_show_temp(struct device *dev, return sprintf(buf, "%d\n", tmp103_reg_to_mc(regval)); } -static ssize_t tmp103_set_temp(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t tmp103_temp_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); struct regmap *regmap = dev_get_drvdata(dev); @@ -94,14 +93,11 @@ static ssize_t tmp103_set_temp(struct device *dev, return ret ? ret : count; } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp103_show_temp, NULL , - TMP103_TEMP_REG); +static SENSOR_DEVICE_ATTR_RO(temp1_input, tmp103_temp, TMP103_TEMP_REG); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, tmp103_show_temp, - tmp103_set_temp, TMP103_TLOW_REG); +static SENSOR_DEVICE_ATTR_RW(temp1_min, tmp103_temp, TMP103_TLOW_REG); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp103_show_temp, - tmp103_set_temp, TMP103_THIGH_REG); +static SENSOR_DEVICE_ATTR_RW(temp1_max, tmp103_temp, TMP103_THIGH_REG); static struct attribute *tmp103_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 8844c9565d2a..2732a71f3b39 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -88,7 +88,7 @@ static const struct of_device_id tmp421_of_match[] = { .data = (void *)2 }, { - .compatible = "ti,tmp422", + .compatible = "ti,tmp442", .data = (void *)3 }, { }, @@ -187,9 +187,9 @@ static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type, case hwmon_temp_fault: if (channel == 0) return 0; - return S_IRUGO; + return 0444; case hwmon_temp_input: - return S_IRUGO; + return 0444; default: return 0; } diff --git a/drivers/hwmon/vexpress-hwmon.c b/drivers/hwmon/vexpress-hwmon.c index 8ba419d343f8..0b84adb5e88e 100644 --- a/drivers/hwmon/vexpress-hwmon.c +++ b/drivers/hwmon/vexpress-hwmon.c @@ -92,9 +92,8 @@ struct vexpress_hwmon_type { }; #if !defined(CONFIG_REGULATOR_VEXPRESS) -static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show, - NULL, 1000); +static DEVICE_ATTR(in1_label, 0444, vexpress_hwmon_label_show, NULL); +static SENSOR_DEVICE_ATTR_RO(in1_input, vexpress_hwmon_u32, 1000); static struct attribute *vexpress_hwmon_attrs_volt[] = { &dev_attr_in1_label.attr, &sensor_dev_attr_in1_input.dev_attr.attr, @@ -113,9 +112,8 @@ static struct vexpress_hwmon_type vexpress_hwmon_volt = { }; #endif -static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); -static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show, - NULL, 1000); +static DEVICE_ATTR(curr1_label, 0444, vexpress_hwmon_label_show, NULL); +static SENSOR_DEVICE_ATTR_RO(curr1_input, vexpress_hwmon_u32, 1000); static struct attribute *vexpress_hwmon_attrs_amp[] = { &dev_attr_curr1_label.attr, &sensor_dev_attr_curr1_input.dev_attr.attr, @@ -133,9 +131,8 @@ static struct vexpress_hwmon_type vexpress_hwmon_amp = { }, }; -static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show, - NULL, 1000); +static DEVICE_ATTR(temp1_label, 0444, vexpress_hwmon_label_show, NULL); +static SENSOR_DEVICE_ATTR_RO(temp1_input, vexpress_hwmon_u32, 1000); static struct attribute *vexpress_hwmon_attrs_temp[] = { &dev_attr_temp1_label.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, @@ -153,9 +150,8 @@ static struct vexpress_hwmon_type vexpress_hwmon_temp = { }, }; -static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); -static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show, - NULL, 1); +static DEVICE_ATTR(power1_label, 0444, vexpress_hwmon_label_show, NULL); +static SENSOR_DEVICE_ATTR_RO(power1_input, vexpress_hwmon_u32, 1); static struct attribute *vexpress_hwmon_attrs_power[] = { &dev_attr_power1_label.attr, &sensor_dev_attr_power1_input.dev_attr.attr, @@ -173,9 +169,8 @@ static struct vexpress_hwmon_type vexpress_hwmon_power = { }, }; -static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); -static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show, - NULL, 1); +static DEVICE_ATTR(energy1_label, 0444, vexpress_hwmon_label_show, NULL); +static SENSOR_DEVICE_ATTR_RO(energy1_input, vexpress_hwmon_u64, 1); static struct attribute *vexpress_hwmon_attrs_energy[] = { &dev_attr_energy1_label.attr, &sensor_dev_attr_energy1_input.dev_attr.attr, diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index 0e81f287d305..cb94e4880014 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c @@ -60,8 +60,8 @@ struct via_cputemp_data { * Sysfs stuff */ -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t name_show(struct device *dev, struct device_attribute *devattr, + char *buf) { int ret; struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -74,8 +74,8 @@ static ssize_t show_name(struct device *dev, struct device_attribute return ret; } -static ssize_t show_temp(struct device *dev, - struct device_attribute *devattr, char *buf) +static ssize_t temp_show(struct device *dev, struct device_attribute *devattr, + char *buf) { struct via_cputemp_data *data = dev_get_drvdata(dev); u32 eax, edx; @@ -102,10 +102,9 @@ static ssize_t cpu0_vid_show(struct device *dev, return sprintf(buf, "%d\n", vid_from_reg(~edx & 0x7f, data->vrm)); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, - SHOW_TEMP); -static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL); -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME); +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, SHOW_TEMP); +static SENSOR_DEVICE_ATTR_RO(temp1_label, name, SHOW_LABEL); +static SENSOR_DEVICE_ATTR_RO(name, name, SHOW_NAME); static struct attribute *via_cputemp_attributes[] = { &sensor_dev_attr_name.dev_attr.attr, diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index ec6e69aa3a8e..d2fbb4bb4a43 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -183,6 +183,15 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); } +static void bcm2835_i2c_finish_transfer(struct bcm2835_i2c_dev *i2c_dev) +{ + i2c_dev->curr_msg = NULL; + i2c_dev->num_msgs = 0; + + i2c_dev->msg_buf = NULL; + i2c_dev->msg_buf_remaining = 0; +} + /* * Note about I2C_C_CLEAR on error: * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in @@ -283,6 +292,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], time_left = wait_for_completion_timeout(&i2c_dev->completion, adap->timeout); + + bcm2835_i2c_finish_transfer(i2c_dev); + if (!time_left) { bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index b13605718291..d917cefc5a19 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -382,8 +382,10 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id) * Check for the message size against FIFO depth and set the * 'hold bus' bit if it is greater than FIFO depth. */ - if (id->recv_count > CDNS_I2C_FIFO_DEPTH) + if ((id->recv_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag) ctrl_reg |= CDNS_I2C_CR_HOLD; + else + ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD; cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); @@ -440,8 +442,11 @@ static void cdns_i2c_msend(struct cdns_i2c *id) * Check for the message size against FIFO depth and set the * 'hold bus' bit if it is greater than FIFO depth. */ - if (id->send_count > CDNS_I2C_FIFO_DEPTH) + if ((id->send_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag) ctrl_reg |= CDNS_I2C_CR_HOLD; + else + ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD; + cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); /* Clear the interrupts in interrupt status register. */ diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index b1086bfb0465..cd9c65f3d404 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1500,8 +1500,7 @@ static int omap_i2c_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int omap_i2c_runtime_suspend(struct device *dev) +static int __maybe_unused omap_i2c_runtime_suspend(struct device *dev) { struct omap_i2c_dev *omap = dev_get_drvdata(dev); @@ -1527,7 +1526,7 @@ static int omap_i2c_runtime_suspend(struct device *dev) return 0; } -static int omap_i2c_runtime_resume(struct device *dev) +static int __maybe_unused omap_i2c_runtime_resume(struct device *dev) { struct omap_i2c_dev *omap = dev_get_drvdata(dev); @@ -1542,20 +1541,18 @@ static int omap_i2c_runtime_resume(struct device *dev) } static const struct dev_pm_ops omap_i2c_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend, omap_i2c_runtime_resume, NULL) }; -#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops) -#else -#define OMAP_I2C_PM_OPS NULL -#endif /* CONFIG_PM */ static struct platform_driver omap_i2c_driver = { .probe = omap_i2c_probe, .remove = omap_i2c_remove, .driver = { .name = "omap_i2c", - .pm = OMAP_I2C_PM_OPS, + .pm = &omap_i2c_pm_ops, .of_match_table = of_match_ptr(omap_i2c_of_match), }, }; diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index e417ebf7628c..c77adbbea0c7 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -155,6 +155,8 @@ enum msg_end_type { * @has_mst_fifo: The I2C controller contains the new MST FIFO interface that * provides additional features and allows for longer messages to * be transferred in one go. + * @quirks: i2c adapter quirks for limiting write/read transfer size and not + * allowing 0 length transfers. */ struct tegra_i2c_hw_feature { bool has_continue_xfer_support; @@ -167,6 +169,7 @@ struct tegra_i2c_hw_feature { bool has_multi_master_mode; bool has_slcg_override_reg; bool has_mst_fifo; + const struct i2c_adapter_quirks *quirks; }; /** @@ -837,6 +840,10 @@ static const struct i2c_adapter_quirks tegra_i2c_quirks = { .max_write_len = 4096, }; +static const struct i2c_adapter_quirks tegra194_i2c_quirks = { + .flags = I2C_AQ_NO_ZERO_LEN, +}; + static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { .has_continue_xfer_support = false, .has_per_pkt_xfer_complete_irq = false, @@ -848,6 +855,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { .has_multi_master_mode = false, .has_slcg_override_reg = false, .has_mst_fifo = false, + .quirks = &tegra_i2c_quirks, }; static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { @@ -861,6 +869,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { .has_multi_master_mode = false, .has_slcg_override_reg = false, .has_mst_fifo = false, + .quirks = &tegra_i2c_quirks, }; static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { @@ -874,6 +883,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { .has_multi_master_mode = false, .has_slcg_override_reg = false, .has_mst_fifo = false, + .quirks = &tegra_i2c_quirks, }; static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { @@ -887,6 +897,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { .has_multi_master_mode = false, .has_slcg_override_reg = true, .has_mst_fifo = false, + .quirks = &tegra_i2c_quirks, }; static const struct tegra_i2c_hw_feature tegra210_i2c_hw = { @@ -900,6 +911,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = { .has_multi_master_mode = true, .has_slcg_override_reg = true, .has_mst_fifo = false, + .quirks = &tegra_i2c_quirks, }; static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { @@ -913,6 +925,7 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { .has_multi_master_mode = true, .has_slcg_override_reg = true, .has_mst_fifo = true, + .quirks = &tegra194_i2c_quirks, }; /* Match table for of_platform binding */ @@ -964,7 +977,6 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->base = base; i2c_dev->div_clk = div_clk; i2c_dev->adapter.algo = &tegra_i2c_algo; - i2c_dev->adapter.quirks = &tegra_i2c_quirks; i2c_dev->irq = irq; i2c_dev->cont_id = pdev->id; i2c_dev->dev = &pdev->dev; @@ -980,6 +992,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->hw = of_device_get_match_data(&pdev->dev); i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node, "nvidia,tegra20-i2c-dvc"); + i2c_dev->adapter.quirks = i2c_dev->hw->quirks; init_completion(&i2c_dev->msg_complete); spin_lock_init(&i2c_dev->xfer_lock); diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 1aca742fde4a..ccd76c71af09 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -470,9 +470,15 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) data_arg.data); } case I2C_RETRIES: + if (arg > INT_MAX) + return -EINVAL; + client->adapter->retries = arg; break; case I2C_TIMEOUT: + if (arg > INT_MAX) + return -EINVAL; + /* For historical reasons, user-space sets the timeout * value in units of 10 ms. */ diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index c39f89d2deba..2dc628d4f1ae 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -1828,7 +1828,7 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master, ret = i3c_master_retrieve_dev_info(newdev); if (ret) - goto err_free_dev; + goto err_detach_dev; olddev = i3c_master_search_i3c_dev_duplicate(newdev); if (olddev) { diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c index b532e2c9cf5c..59279224e07f 100644 --- a/drivers/i3c/master/dw-i3c-master.c +++ b/drivers/i3c/master/dw-i3c-master.c @@ -419,12 +419,9 @@ static void dw_i3c_master_enqueue_xfer(struct dw_i3c_master *master, spin_unlock_irqrestore(&master->xferqueue.lock, flags); } -static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master, - struct dw_i3c_xfer *xfer) +static void dw_i3c_master_dequeue_xfer_locked(struct dw_i3c_master *master, + struct dw_i3c_xfer *xfer) { - unsigned long flags; - - spin_lock_irqsave(&master->xferqueue.lock, flags); if (master->xferqueue.cur == xfer) { u32 status; @@ -439,6 +436,15 @@ static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master, } else { list_del_init(&xfer->node); } +} + +static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master, + struct dw_i3c_xfer *xfer) +{ + unsigned long flags; + + spin_lock_irqsave(&master->xferqueue.lock, flags); + dw_i3c_master_dequeue_xfer_locked(master, xfer); spin_unlock_irqrestore(&master->xferqueue.lock, flags); } @@ -494,7 +500,7 @@ static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr) complete(&xfer->comp); if (ret < 0) { - dw_i3c_master_dequeue_xfer(master, xfer); + dw_i3c_master_dequeue_xfer_locked(master, xfer); writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_RESUME, master->regs + DEVICE_CTRL); } @@ -596,6 +602,7 @@ static int dw_i3c_master_bus_init(struct i3c_master_controller *m) ret = dw_i2c_clk_cfg(master); if (ret) return ret; + /* fall through */ case I3C_BUS_MODE_PURE: ret = dw_i3c_clk_cfg(master); if (ret) @@ -901,9 +908,6 @@ static int dw_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev, master->regs + DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); - if (!old_dyn_addr) - return 0; - master->addrs[data->index] = dev->info.dyn_addr; return 0; @@ -925,11 +929,11 @@ static int dw_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev) return -ENOMEM; data->index = pos; - master->addrs[pos] = dev->info.dyn_addr; + master->addrs[pos] = dev->info.dyn_addr ? : dev->info.static_addr; master->free_pos &= ~BIT(pos); i3c_dev_set_master_data(dev, data); - writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(dev->info.dyn_addr), + writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->addrs[pos]), master->regs + DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c index bbd79b8b1a80..8889a4fdb454 100644 --- a/drivers/i3c/master/i3c-master-cdns.c +++ b/drivers/i3c/master/i3c-master-cdns.c @@ -1556,8 +1556,8 @@ static int cdns_i3c_master_probe(struct platform_device *pdev) return PTR_ERR(master->pclk); master->sysclk = devm_clk_get(&pdev->dev, "sysclk"); - if (IS_ERR(master->pclk)) - return PTR_ERR(master->pclk); + if (IS_ERR(master->sysclk)) + return PTR_ERR(master->sysclk); irq = platform_get_irq(pdev, 0); if (irq < 0) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index da58020a144e..33a28cde126c 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -235,21 +235,28 @@ EXPORT_SYMBOL_GPL(ide_prep_sense); int ide_queue_sense_rq(ide_drive_t *drive, void *special) { - struct request *sense_rq = drive->sense_rq; + ide_hwif_t *hwif = drive->hwif; + struct request *sense_rq; + unsigned long flags; + + spin_lock_irqsave(&hwif->lock, flags); /* deferred failure from ide_prep_sense() */ if (!drive->sense_rq_armed) { printk(KERN_WARNING PFX "%s: error queuing a sense request\n", drive->name); + spin_unlock_irqrestore(&hwif->lock, flags); return -ENOMEM; } + sense_rq = drive->sense_rq; ide_req(sense_rq)->special = special; drive->sense_rq_armed = false; drive->hwif->rq = NULL; ide_insert_request_head(drive, sense_rq); + spin_unlock_irqrestore(&hwif->lock, flags); return 0; } EXPORT_SYMBOL_GPL(ide_queue_sense_rq); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 8445b484ae69..b137f27a34d5 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -68,8 +68,10 @@ int ide_end_rq(ide_drive_t *drive, struct request *rq, blk_status_t error, } if (!blk_update_request(rq, error, nr_bytes)) { - if (rq == drive->sense_rq) + if (rq == drive->sense_rq) { drive->sense_rq = NULL; + drive->sense_rq_active = false; + } __blk_mq_end_request(rq, error); return 0; @@ -451,16 +453,11 @@ void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq) blk_mq_delay_run_hw_queue(q->queue_hw_ctx[0], 3); } -/* - * Issue a new request to a device. - */ -blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx, - const struct blk_mq_queue_data *bd) +blk_status_t ide_issue_rq(ide_drive_t *drive, struct request *rq, + bool local_requeue) { - ide_drive_t *drive = hctx->queue->queuedata; - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = drive->hwif; struct ide_host *host = hwif->host; - struct request *rq = bd->rq; ide_startstop_t startstop; if (!blk_rq_is_passthrough(rq) && !(rq->rq_flags & RQF_DONTPREP)) { @@ -474,8 +471,6 @@ blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx, if (ide_lock_host(host, hwif)) return BLK_STS_DEV_RESOURCE; - blk_mq_start_request(rq); - spin_lock_irq(&hwif->lock); if (!ide_lock_port(hwif)) { @@ -511,18 +506,6 @@ repeat: drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); /* - * we know that the queue isn't empty, but this can happen - * if ->prep_rq() decides to kill a request - */ - if (!rq) { - rq = bd->rq; - if (!rq) { - ide_unlock_port(hwif); - goto out; - } - } - - /* * Sanity: don't accept a request that isn't a PM request * if we are currently power managed. This is very important as * blk_stop_queue() doesn't prevent the blk_fetch_request() @@ -560,9 +543,12 @@ repeat: } } else { plug_device: + if (local_requeue) + list_add(&rq->queuelist, &drive->rq_list); spin_unlock_irq(&hwif->lock); ide_unlock_host(host); - ide_requeue_and_plug(drive, rq); + if (!local_requeue) + ide_requeue_and_plug(drive, rq); return BLK_STS_OK; } @@ -573,6 +559,26 @@ out: return BLK_STS_OK; } +/* + * Issue a new request to a device. + */ +blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) +{ + ide_drive_t *drive = hctx->queue->queuedata; + ide_hwif_t *hwif = drive->hwif; + + spin_lock_irq(&hwif->lock); + if (drive->sense_rq_active) { + spin_unlock_irq(&hwif->lock); + return BLK_STS_DEV_RESOURCE; + } + spin_unlock_irq(&hwif->lock); + + blk_mq_start_request(bd->rq); + return ide_issue_rq(drive, bd->rq, false); +} + static int drive_is_ready(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; @@ -893,13 +899,8 @@ EXPORT_SYMBOL_GPL(ide_pad_transfer); void ide_insert_request_head(ide_drive_t *drive, struct request *rq) { - ide_hwif_t *hwif = drive->hwif; - unsigned long flags; - - spin_lock_irqsave(&hwif->lock, flags); + drive->sense_rq_active = true; list_add_tail(&rq->queuelist, &drive->rq_list); - spin_unlock_irqrestore(&hwif->lock, flags); - kblockd_schedule_work(&drive->rq_work); } EXPORT_SYMBOL_GPL(ide_insert_request_head); diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c index 102aa3bc3e7f..8af7af6001eb 100644 --- a/drivers/ide/ide-park.c +++ b/drivers/ide/ide-park.c @@ -54,7 +54,9 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) scsi_req(rq)->cmd[0] = REQ_UNPARK_HEADS; scsi_req(rq)->cmd_len = 1; ide_req(rq)->type = ATA_PRIV_MISC; + spin_lock_irq(&hwif->lock); ide_insert_request_head(drive, rq); + spin_unlock_irq(&hwif->lock); out: return; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 63627be0811a..5aeaca24a28f 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1159,18 +1159,27 @@ static void drive_rq_insert_work(struct work_struct *work) ide_drive_t *drive = container_of(work, ide_drive_t, rq_work); ide_hwif_t *hwif = drive->hwif; struct request *rq; + blk_status_t ret; LIST_HEAD(list); - spin_lock_irq(&hwif->lock); - if (!list_empty(&drive->rq_list)) - list_splice_init(&drive->rq_list, &list); - spin_unlock_irq(&hwif->lock); + blk_mq_quiesce_queue(drive->queue); - while (!list_empty(&list)) { - rq = list_first_entry(&list, struct request, queuelist); + ret = BLK_STS_OK; + spin_lock_irq(&hwif->lock); + while (!list_empty(&drive->rq_list)) { + rq = list_first_entry(&drive->rq_list, struct request, queuelist); list_del_init(&rq->queuelist); - blk_execute_rq_nowait(drive->queue, rq->rq_disk, rq, true, NULL); + + spin_unlock_irq(&hwif->lock); + ret = ide_issue_rq(drive, rq, true); + spin_lock_irq(&hwif->lock); } + spin_unlock_irq(&hwif->lock); + + blk_mq_unquiesce_queue(drive->queue); + + if (ret != BLK_STS_OK) + kblockd_schedule_work(&drive->rq_work); } static const u8 ide_hwif_to_major[] = diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 4c8c7a620d08..a5dc13576394 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -544,7 +544,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif) drive->proc = proc_mkdir(drive->name, parent); if (drive->proc) { ide_add_proc_entries(drive->proc, generic_drive_entries, drive); - proc_create_data("setting", S_IFREG|S_IRUSR|S_IWUSR, + proc_create_data("settings", S_IFREG|S_IRUSR|S_IWUSR, drive->proc, &ide_settings_proc_fops, drive); } diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 031d568b4972..4e339cfd0c54 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -27,9 +27,18 @@ #include <linux/iio/machine.h> #include <linux/iio/driver.h> -#define AXP288_ADC_EN_MASK 0xF1 -#define AXP288_ADC_TS_PIN_GPADC 0xF2 -#define AXP288_ADC_TS_PIN_ON 0xF3 +/* + * This mask enables all ADCs except for the battery temp-sensor (TS), that is + * left as-is to avoid breaking charging on devices without a temp-sensor. + */ +#define AXP288_ADC_EN_MASK 0xF0 +#define AXP288_ADC_TS_ENABLE 0x01 + +#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK GENMASK(1, 0) +#define AXP288_ADC_TS_CURRENT_OFF (0 << 0) +#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING (1 << 0) +#define AXP288_ADC_TS_CURRENT_ON_ONDEMAND (2 << 0) +#define AXP288_ADC_TS_CURRENT_ON (3 << 0) enum axp288_adc_id { AXP288_ADC_TS, @@ -44,6 +53,7 @@ enum axp288_adc_id { struct axp288_adc_info { int irq; struct regmap *regmap; + bool ts_enabled; }; static const struct iio_chan_spec axp288_adc_channels[] = { @@ -115,21 +125,33 @@ static int axp288_adc_read_channel(int *val, unsigned long address, return IIO_VAL_INT; } -static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode, - unsigned long address) +/* + * The current-source used for the battery temp-sensor (TS) is shared + * with the GPADC. For proper fuel-gauge and charger operation the TS + * current-source needs to be permanently on. But to read the GPADC we + * need to temporary switch the TS current-source to ondemand, so that + * the GPADC can use it, otherwise we will always read an all 0 value. + */ +static int axp288_adc_set_ts(struct axp288_adc_info *info, + unsigned int mode, unsigned long address) { int ret; - /* channels other than GPADC do not need to switch TS pin */ + /* No need to switch the current-source if the TS pin is disabled */ + if (!info->ts_enabled) + return 0; + + /* Channels other than GPADC do not need the current source */ if (address != AXP288_GP_ADC_H) return 0; - ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode); + ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL, + AXP288_ADC_TS_CURRENT_ON_OFF_MASK, mode); if (ret) return ret; /* When switching to the GPADC pin give things some time to settle */ - if (mode == AXP288_ADC_TS_PIN_GPADC) + if (mode == AXP288_ADC_TS_CURRENT_ON_ONDEMAND) usleep_range(6000, 10000); return 0; @@ -145,14 +167,14 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, mutex_lock(&indio_dev->mlock); switch (mask) { case IIO_CHAN_INFO_RAW: - if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC, + if (axp288_adc_set_ts(info, AXP288_ADC_TS_CURRENT_ON_ONDEMAND, chan->address)) { dev_err(&indio_dev->dev, "GPADC mode\n"); ret = -EINVAL; break; } ret = axp288_adc_read_channel(val, chan->address, info->regmap); - if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON, + if (axp288_adc_set_ts(info, AXP288_ADC_TS_CURRENT_ON, chan->address)) dev_err(&indio_dev->dev, "TS pin restore\n"); break; @@ -164,13 +186,35 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, return ret; } -static int axp288_adc_set_state(struct regmap *regmap) +static int axp288_adc_initialize(struct axp288_adc_info *info) { - /* ADC should be always enabled for internal FG to function */ - if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON)) - return -EIO; + int ret, adc_enable_val; + + /* + * Determine if the TS pin is enabled and set the TS current-source + * accordingly. + */ + ret = regmap_read(info->regmap, AXP20X_ADC_EN1, &adc_enable_val); + if (ret) + return ret; + + if (adc_enable_val & AXP288_ADC_TS_ENABLE) { + info->ts_enabled = true; + ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL, + AXP288_ADC_TS_CURRENT_ON_OFF_MASK, + AXP288_ADC_TS_CURRENT_ON); + } else { + info->ts_enabled = false; + ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL, + AXP288_ADC_TS_CURRENT_ON_OFF_MASK, + AXP288_ADC_TS_CURRENT_OFF); + } + if (ret) + return ret; - return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); + /* Turn on the ADC for all channels except TS, leave TS as is */ + return regmap_update_bits(info->regmap, AXP20X_ADC_EN1, + AXP288_ADC_EN_MASK, AXP288_ADC_EN_MASK); } static const struct iio_info axp288_adc_iio_info = { @@ -200,7 +244,7 @@ static int axp288_adc_probe(struct platform_device *pdev) * Set ADC to enabled state at all time, including system suspend. * otherwise internal fuel gauge functionality may be affected. */ - ret = axp288_adc_set_state(axp20x->regmap); + ret = axp288_adc_initialize(info); if (ret) { dev_err(&pdev->dev, "unable to enable ADC device\n"); return ret; diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index 184d686ebd99..8b4568edd5cb 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -41,6 +41,7 @@ #define ADS8688_VREF_MV 4096 #define ADS8688_REALBITS 16 +#define ADS8688_MAX_CHANNELS 8 /* * enum ads8688_range - ADS8688 reference voltage range @@ -385,7 +386,7 @@ static irqreturn_t ads8688_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; - u16 buffer[8]; + u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)]; int i, j = 0; for (i = 0; i < indio_dev->masklength; i++) { diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index cafb1dcadc48..9d984f2a8ba7 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -142,7 +142,10 @@ static void tiadc_step_config(struct iio_dev *indio_dev) stepconfig |= STEPCONFIG_MODE_SWCNT; tiadc_writel(adc_dev, REG_STEPCONFIG(steps), - stepconfig | STEPCONFIG_INP(chan)); + stepconfig | STEPCONFIG_INP(chan) | + STEPCONFIG_INM_ADCREFM | + STEPCONFIG_RFP_VREFP | + STEPCONFIG_RFM_VREFN); if (adc_dev->open_delay[i] > STEPDELAY_OPEN_MASK) { dev_warn(dev, "chan %d open delay truncating to 0x3FFFF\n", diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c index a406ad31b096..3a20cb5d9bff 100644 --- a/drivers/iio/chemical/atlas-ph-sensor.c +++ b/drivers/iio/chemical/atlas-ph-sensor.c @@ -444,9 +444,8 @@ static int atlas_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_TEMP: - *val = 1; /* 0.01 */ - *val2 = 100; - break; + *val = 10; + return IIO_VAL_INT; case IIO_PH: *val = 1; /* 0.001 */ *val2 = 1000; @@ -477,7 +476,7 @@ static int atlas_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct atlas_data *data = iio_priv(indio_dev); - __be32 reg = cpu_to_be32(val); + __be32 reg = cpu_to_be32(val / 10); if (val2 != 0 || val < 0 || val > 20000) return -EINVAL; diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 63a7cc00bae0..84f077b2b90a 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -494,7 +494,10 @@ static void _cma_attach_to_dev(struct rdma_id_private *id_priv, id_priv->id.route.addr.dev_addr.transport = rdma_node_get_transport(cma_dev->device->node_type); list_add_tail(&id_priv->list, &cma_dev->id_list); - rdma_restrack_kadd(&id_priv->res); + if (id_priv->res.kern_name) + rdma_restrack_kadd(&id_priv->res); + else + rdma_restrack_uadd(&id_priv->res); } static void cma_attach_to_dev(struct rdma_id_private *id_priv, diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h index 3cd830d52967..616734313f0c 100644 --- a/drivers/infiniband/core/core_priv.h +++ b/drivers/infiniband/core/core_priv.h @@ -267,7 +267,6 @@ static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map, #endif struct ib_device *ib_device_get_by_index(u32 ifindex); -void ib_device_put(struct ib_device *device); /* RDMA device netlink */ void nldev_init(void); void nldev_exit(void); diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 8872453e26c0..238ec42778ef 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -156,19 +156,26 @@ struct ib_device *ib_device_get_by_index(u32 index) down_read(&lists_rwsem); device = __ib_device_get_by_index(index); if (device) { - /* Do not return a device if unregistration has started. */ - if (!refcount_inc_not_zero(&device->refcount)) + if (!ib_device_try_get(device)) device = NULL; } up_read(&lists_rwsem); return device; } +/** + * ib_device_put - Release IB device reference + * @device: device whose reference to be released + * + * ib_device_put() releases reference to the IB device to allow it to be + * unregistered and eventually free. + */ void ib_device_put(struct ib_device *device) { if (refcount_dec_and_test(&device->refcount)) complete(&device->unreg_completion); } +EXPORT_SYMBOL(ib_device_put); static struct ib_device *__ib_device_get_by_name(const char *name) { @@ -303,7 +310,6 @@ struct ib_device *ib_alloc_device(size_t size) rwlock_init(&device->client_data_lock); INIT_LIST_HEAD(&device->client_data_list); INIT_LIST_HEAD(&device->port_list); - refcount_set(&device->refcount, 1); init_completion(&device->unreg_completion); return device; @@ -620,6 +626,7 @@ int ib_register_device(struct ib_device *device, const char *name, goto cg_cleanup; } + refcount_set(&device->refcount, 1); device->reg_state = IB_DEV_REGISTERED; list_for_each_entry(client, &client_list, list) diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c index e600fc23ae62..3c97a8b6bf1e 100644 --- a/drivers/infiniband/core/nldev.c +++ b/drivers/infiniband/core/nldev.c @@ -584,10 +584,6 @@ static int fill_res_pd_entry(struct sk_buff *msg, struct netlink_callback *cb, if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_USECNT, atomic_read(&pd->usecnt), RDMA_NLDEV_ATTR_PAD)) goto err; - if ((pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY) && - nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY, - pd->unsafe_global_rkey)) - goto err; if (fill_res_name_pid(msg, res)) goto err; diff --git a/drivers/infiniband/core/rdma_core.h b/drivers/infiniband/core/rdma_core.h index be6b8e1257d0..69f8db66925e 100644 --- a/drivers/infiniband/core/rdma_core.h +++ b/drivers/infiniband/core/rdma_core.h @@ -106,6 +106,8 @@ int uverbs_finalize_object(struct ib_uobject *uobj, enum uverbs_obj_access access, bool commit); +int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx); + void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile); void release_ufile_idr_uobject(struct ib_uverbs_file *ufile); diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c index a4ec43093cb3..acb882f279cb 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c @@ -352,6 +352,8 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_ucontext_per_mm *per_mm, umem->writable = 1; umem->is_odp = 1; odp_data->per_mm = per_mm; + umem->owning_mm = per_mm->mm; + mmgrab(umem->owning_mm); mutex_init(&odp_data->umem_mutex); init_completion(&odp_data->notifier_completion); @@ -384,6 +386,7 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_ucontext_per_mm *per_mm, out_page_list: vfree(odp_data->page_list); out_odp_data: + mmdrop(umem->owning_mm); kfree(odp_data); return ERR_PTR(ret); } diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 6b12cc5f97b2..3317300ab036 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -60,6 +60,10 @@ static int uverbs_response(struct uverbs_attr_bundle *attrs, const void *resp, { int ret; + if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT)) + return uverbs_copy_to_struct_or_zero( + attrs, UVERBS_ATTR_CORE_OUT, resp, resp_len); + if (copy_to_user(attrs->ucore.outbuf, resp, min(attrs->ucore.outlen, resp_len))) return -EFAULT; @@ -1181,6 +1185,9 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs) goto out_put; } + if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT)) + ret = uverbs_output_written(attrs, UVERBS_ATTR_CORE_OUT); + ret = 0; out_put: @@ -2012,8 +2019,10 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs) return -ENOMEM; qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); - if (!qp) + if (!qp) { + ret = -EINVAL; goto out; + } is_ud = qp->qp_type == IB_QPT_UD; sg_ind = 0; diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c index 8c81ff698052..0ca04d224015 100644 --- a/drivers/infiniband/core/uverbs_ioctl.c +++ b/drivers/infiniband/core/uverbs_ioctl.c @@ -144,6 +144,21 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr, 0, uattr->len - len); } +static int uverbs_set_output(const struct uverbs_attr_bundle *bundle, + const struct uverbs_attr *attr) +{ + struct bundle_priv *pbundle = + container_of(bundle, struct bundle_priv, bundle); + u16 flags; + + flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags | + UVERBS_ATTR_F_VALID_OUTPUT; + if (put_user(flags, + &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags)) + return -EFAULT; + return 0; +} + static int uverbs_process_idrs_array(struct bundle_priv *pbundle, const struct uverbs_api_attr *attr_uapi, struct uverbs_objs_arr_attr *attr, @@ -456,6 +471,19 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle, } /* + * Until the drivers are revised to use the bundle directly we have to + * assume that the driver wrote to its UHW_OUT and flag userspace + * appropriately. + */ + if (!ret && pbundle->method_elm->has_udata) { + const struct uverbs_attr *attr = + uverbs_attr_get(&pbundle->bundle, UVERBS_ATTR_UHW_OUT); + + if (!IS_ERR(attr)) + ret = uverbs_set_output(&pbundle->bundle, attr); + } + + /* * EPROTONOSUPPORT is ONLY to be returned if the ioctl framework can * not invoke the method because the request is not supported. No * other cases should return this code. @@ -706,10 +734,7 @@ void uverbs_fill_udata(struct uverbs_attr_bundle *bundle, int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx, const void *from, size_t size) { - struct bundle_priv *pbundle = - container_of(bundle, struct bundle_priv, bundle); const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx); - u16 flags; size_t min_size; if (IS_ERR(attr)) @@ -719,16 +744,25 @@ int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx, if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size)) return -EFAULT; - flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags | - UVERBS_ATTR_F_VALID_OUTPUT; - if (put_user(flags, - &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags)) - return -EFAULT; - - return 0; + return uverbs_set_output(bundle, attr); } EXPORT_SYMBOL(uverbs_copy_to); + +/* + * This is only used if the caller has directly used copy_to_use to write the + * data. It signals to user space that the buffer is filled in. + */ +int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx) +{ + const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx); + + if (IS_ERR(attr)) + return PTR_ERR(attr); + + return uverbs_set_output(bundle, attr); +} + int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle, size_t idx, s64 lower_bound, u64 upper_bound, s64 *def_val) @@ -757,8 +791,10 @@ int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle, { const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx); - if (clear_user(u64_to_user_ptr(attr->ptr_attr.data), - attr->ptr_attr.len)) - return -EFAULT; + if (size < attr->ptr_attr.len) { + if (clear_user(u64_to_user_ptr(attr->ptr_attr.data) + size, + attr->ptr_attr.len - size)) + return -EFAULT; + } return uverbs_copy_to(bundle, idx, from, size); } diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index fb0007aa0c27..5f366838b7ff 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -204,6 +204,9 @@ void ib_uverbs_release_file(struct kref *ref) if (atomic_dec_and_test(&file->device->refcount)) ib_uverbs_comp_dev(file->device); + if (file->async_file) + kref_put(&file->async_file->ref, + ib_uverbs_release_async_event_file); put_device(&file->device->dev); kfree(file); } @@ -690,6 +693,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, buf += sizeof(hdr); + memset(bundle.attr_present, 0, sizeof(bundle.attr_present)); bundle.ufile = file; if (!method_elm->is_ex) { size_t in_len = hdr.in_words * 4 - sizeof(hdr); @@ -963,11 +967,19 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile) /* Get an arbitrary mm pointer that hasn't been cleaned yet */ mutex_lock(&ufile->umap_lock); - if (!list_empty(&ufile->umaps)) { - mm = list_first_entry(&ufile->umaps, - struct rdma_umap_priv, list) - ->vma->vm_mm; - mmget(mm); + while (!list_empty(&ufile->umaps)) { + int ret; + + priv = list_first_entry(&ufile->umaps, + struct rdma_umap_priv, list); + mm = priv->vma->vm_mm; + ret = mmget_not_zero(mm); + if (!ret) { + list_del_init(&priv->list); + mm = NULL; + continue; + } + break; } mutex_unlock(&ufile->umap_lock); if (!mm) @@ -1095,10 +1107,6 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp) list_del_init(&file->list); mutex_unlock(&file->device->lists_mutex); - if (file->async_file) - kref_put(&file->async_file->ref, - ib_uverbs_release_async_event_file); - kref_put(&file->ref, ib_uverbs_release_file); return 0; diff --git a/drivers/infiniband/core/uverbs_std_types_device.c b/drivers/infiniband/core/uverbs_std_types_device.c index 5030ec480370..2a3f2f01028d 100644 --- a/drivers/infiniband/core/uverbs_std_types_device.c +++ b/drivers/infiniband/core/uverbs_std_types_device.c @@ -168,12 +168,18 @@ void copy_port_attr_to_resp(struct ib_port_attr *attr, static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_PORT)( struct uverbs_attr_bundle *attrs) { - struct ib_device *ib_dev = attrs->ufile->device->ib_dev; + struct ib_device *ib_dev; struct ib_port_attr attr = {}; struct ib_uverbs_query_port_resp_ex resp = {}; + struct ib_ucontext *ucontext; int ret; u8 port_num; + ucontext = ib_uverbs_get_ucontext(attrs); + if (IS_ERR(ucontext)) + return PTR_ERR(ucontext); + ib_dev = ucontext->device; + /* FIXME: Extend the UAPI_DEF_OBJ_NEEDS_FN stuff.. */ if (!ib_dev->ops.query_port) return -EOPNOTSUPP; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c index 326805461265..19551aa43850 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c @@ -766,8 +766,8 @@ struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf( return NULL; sbuf->size = size; - sbuf->sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf->size, - &sbuf->dma_addr, GFP_ATOMIC); + sbuf->sb = dma_alloc_coherent(&rcfw->pdev->dev, sbuf->size, + &sbuf->dma_addr, GFP_ATOMIC); if (!sbuf->sb) goto bail; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c index 59eeac55626f..57d4951679cb 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_res.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c @@ -105,10 +105,10 @@ static int __alloc_pbl(struct pci_dev *pdev, struct bnxt_qplib_pbl *pbl, if (!sghead) { for (i = 0; i < pages; i++) { - pbl->pg_arr[i] = dma_zalloc_coherent(&pdev->dev, - pbl->pg_size, - &pbl->pg_map_arr[i], - GFP_KERNEL); + pbl->pg_arr[i] = dma_alloc_coherent(&pdev->dev, + pbl->pg_size, + &pbl->pg_map_arr[i], + GFP_KERNEL); if (!pbl->pg_arr[i]) goto fail; pbl->pg_count++; diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c index df4f7a3f043d..8ac72ac7cbac 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.c +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c @@ -291,9 +291,9 @@ int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain, if (!wq->sq) goto err3; - wq->queue = dma_zalloc_coherent(&(rdev_p->rnic_info.pdev->dev), - depth * sizeof(union t3_wr), - &(wq->dma_addr), GFP_KERNEL); + wq->queue = dma_alloc_coherent(&(rdev_p->rnic_info.pdev->dev), + depth * sizeof(union t3_wr), + &(wq->dma_addr), GFP_KERNEL); if (!wq->queue) goto err4; diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index c13c0ba30f63..d499cd61c0e8 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c @@ -783,6 +783,7 @@ void c4iw_init_dev_ucontext(struct c4iw_rdev *rdev, static int c4iw_rdev_open(struct c4iw_rdev *rdev) { int err; + unsigned int factor; c4iw_init_dev_ucontext(rdev, &rdev->uctx); @@ -806,8 +807,18 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev) return -EINVAL; } - rdev->qpmask = rdev->lldi.udb_density - 1; - rdev->cqmask = rdev->lldi.ucq_density - 1; + /* This implementation requires a sge_host_page_size <= PAGE_SIZE. */ + if (rdev->lldi.sge_host_page_size > PAGE_SIZE) { + pr_err("%s: unsupported sge host page size %u\n", + pci_name(rdev->lldi.pdev), + rdev->lldi.sge_host_page_size); + return -EINVAL; + } + + factor = PAGE_SIZE / rdev->lldi.sge_host_page_size; + rdev->qpmask = (rdev->lldi.udb_density * factor) - 1; + rdev->cqmask = (rdev->lldi.ucq_density * factor) - 1; + pr_debug("dev %s stag start 0x%0x size 0x%0x num stags %d pbl start 0x%0x size 0x%0x rq start 0x%0x size 0x%0x qp qid start %u size %u cq qid start %u size %u srq size %u\n", pci_name(rdev->lldi.pdev), rdev->lldi.vr->stag.start, rdev->lldi.vr->stag.size, c4iw_num_stags(rdev), diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 981ff5cfb5d1..504cf525508f 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -2564,9 +2564,8 @@ static int alloc_srq_queue(struct c4iw_srq *srq, struct c4iw_dev_ucontext *uctx, wq->rqt_abs_idx = (wq->rqt_hwaddr - rdev->lldi.vr->rq.start) >> T4_RQT_ENTRY_SHIFT; - wq->queue = dma_zalloc_coherent(&rdev->lldi.pdev->dev, - wq->memsize, &wq->dma_addr, - GFP_KERNEL); + wq->queue = dma_alloc_coherent(&rdev->lldi.pdev->dev, wq->memsize, + &wq->dma_addr, GFP_KERNEL); if (!wq->queue) goto err_free_rqtpool; diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c index c22ebc774a6a..f9a7e9d29c8b 100644 --- a/drivers/infiniband/hw/hfi1/file_ops.c +++ b/drivers/infiniband/hw/hfi1/file_ops.c @@ -488,7 +488,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma) vmf = 1; break; case STATUS: - if (flags & (unsigned long)(VM_WRITE | VM_EXEC)) { + if (flags & VM_WRITE) { ret = -EPERM; goto done; } diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c index 09044905284f..7835eb52e7c5 100644 --- a/drivers/infiniband/hw/hfi1/init.c +++ b/drivers/infiniband/hw/hfi1/init.c @@ -899,10 +899,10 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit) goto done; /* allocate dummy tail memory for all receive contexts */ - dd->rcvhdrtail_dummy_kvaddr = dma_zalloc_coherent( - &dd->pcidev->dev, sizeof(u64), - &dd->rcvhdrtail_dummy_dma, - GFP_KERNEL); + dd->rcvhdrtail_dummy_kvaddr = dma_alloc_coherent(&dd->pcidev->dev, + sizeof(u64), + &dd->rcvhdrtail_dummy_dma, + GFP_KERNEL); if (!dd->rcvhdrtail_dummy_kvaddr) { dd_dev_err(dd, "cannot allocate dummy tail memory\n"); @@ -1863,9 +1863,9 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd) gfp_flags = GFP_KERNEL; else gfp_flags = GFP_USER; - rcd->rcvhdrq = dma_zalloc_coherent( - &dd->pcidev->dev, amt, &rcd->rcvhdrq_dma, - gfp_flags | __GFP_COMP); + rcd->rcvhdrq = dma_alloc_coherent(&dd->pcidev->dev, amt, + &rcd->rcvhdrq_dma, + gfp_flags | __GFP_COMP); if (!rcd->rcvhdrq) { dd_dev_err(dd, @@ -1876,9 +1876,10 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd) if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL) || HFI1_CAP_UGET_MASK(rcd->flags, DMA_RTAIL)) { - rcd->rcvhdrtail_kvaddr = dma_zalloc_coherent( - &dd->pcidev->dev, PAGE_SIZE, - &rcd->rcvhdrqtailaddr_dma, gfp_flags); + rcd->rcvhdrtail_kvaddr = dma_alloc_coherent(&dd->pcidev->dev, + PAGE_SIZE, + &rcd->rcvhdrqtailaddr_dma, + gfp_flags); if (!rcd->rcvhdrtail_kvaddr) goto bail_free; } @@ -1974,10 +1975,10 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd) while (alloced_bytes < rcd->egrbufs.size && rcd->egrbufs.alloced < rcd->egrbufs.count) { rcd->egrbufs.buffers[idx].addr = - dma_zalloc_coherent(&dd->pcidev->dev, - rcd->egrbufs.rcvtid_size, - &rcd->egrbufs.buffers[idx].dma, - gfp_flags); + dma_alloc_coherent(&dd->pcidev->dev, + rcd->egrbufs.rcvtid_size, + &rcd->egrbufs.buffers[idx].dma, + gfp_flags); if (rcd->egrbufs.buffers[idx].addr) { rcd->egrbufs.buffers[idx].len = rcd->egrbufs.rcvtid_size; diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c index dd5a5c030066..04126d7e318d 100644 --- a/drivers/infiniband/hw/hfi1/pio.c +++ b/drivers/infiniband/hw/hfi1/pio.c @@ -2098,11 +2098,10 @@ int init_credit_return(struct hfi1_devdata *dd) int bytes = TXE_NUM_CONTEXTS * sizeof(struct credit_return); set_dev_node(&dd->pcidev->dev, i); - dd->cr_base[i].va = dma_zalloc_coherent( - &dd->pcidev->dev, - bytes, - &dd->cr_base[i].dma, - GFP_KERNEL); + dd->cr_base[i].va = dma_alloc_coherent(&dd->pcidev->dev, + bytes, + &dd->cr_base[i].dma, + GFP_KERNEL); if (!dd->cr_base[i].va) { set_dev_node(&dd->pcidev->dev, dd->node); dd_dev_err(dd, diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c index b84356e1a4c1..96897a91fb0a 100644 --- a/drivers/infiniband/hw/hfi1/sdma.c +++ b/drivers/infiniband/hw/hfi1/sdma.c @@ -1453,12 +1453,9 @@ int sdma_init(struct hfi1_devdata *dd, u8 port) timer_setup(&sde->err_progress_check_timer, sdma_err_progress_check, 0); - sde->descq = dma_zalloc_coherent( - &dd->pcidev->dev, - descq_cnt * sizeof(u64[2]), - &sde->descq_phys, - GFP_KERNEL - ); + sde->descq = dma_alloc_coherent(&dd->pcidev->dev, + descq_cnt * sizeof(u64[2]), + &sde->descq_phys, GFP_KERNEL); if (!sde->descq) goto bail; sde->tx_ring = @@ -1471,24 +1468,18 @@ int sdma_init(struct hfi1_devdata *dd, u8 port) dd->sdma_heads_size = L1_CACHE_BYTES * num_engines; /* Allocate memory for DMA of head registers to memory */ - dd->sdma_heads_dma = dma_zalloc_coherent( - &dd->pcidev->dev, - dd->sdma_heads_size, - &dd->sdma_heads_phys, - GFP_KERNEL - ); + dd->sdma_heads_dma = dma_alloc_coherent(&dd->pcidev->dev, + dd->sdma_heads_size, + &dd->sdma_heads_phys, + GFP_KERNEL); if (!dd->sdma_heads_dma) { dd_dev_err(dd, "failed to allocate SendDMA head memory\n"); goto bail; } /* Allocate memory for pad */ - dd->sdma_pad_dma = dma_zalloc_coherent( - &dd->pcidev->dev, - sizeof(u32), - &dd->sdma_pad_phys, - GFP_KERNEL - ); + dd->sdma_pad_dma = dma_alloc_coherent(&dd->pcidev->dev, sizeof(u32), + &dd->sdma_pad_phys, GFP_KERNEL); if (!dd->sdma_pad_dma) { dd_dev_err(dd, "failed to allocate SendDMA pad memory\n"); goto bail; diff --git a/drivers/infiniband/hw/hfi1/ud.c b/drivers/infiniband/hw/hfi1/ud.c index 88242fe95eaa..bf96067876c9 100644 --- a/drivers/infiniband/hw/hfi1/ud.c +++ b/drivers/infiniband/hw/hfi1/ud.c @@ -987,7 +987,6 @@ void hfi1_ud_rcv(struct hfi1_packet *packet) opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) { wc.ex.imm_data = packet->ohdr->u.ud.imm_data; wc.wc_flags = IB_WC_WITH_IMM; - tlen -= sizeof(u32); } else if (opcode == IB_OPCODE_UD_SEND_ONLY) { wc.ex.imm_data = 0; wc.wc_flags = 0; diff --git a/drivers/infiniband/hw/hns/hns_roce_alloc.c b/drivers/infiniband/hw/hns/hns_roce_alloc.c index 6300033a448f..dac058d3df53 100644 --- a/drivers/infiniband/hw/hns/hns_roce_alloc.c +++ b/drivers/infiniband/hw/hns/hns_roce_alloc.c @@ -197,8 +197,8 @@ int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct, buf->npages = 1 << order; buf->page_shift = page_shift; /* MTT PA must be recorded in 4k alignment, t is 4k aligned */ - buf->direct.buf = dma_zalloc_coherent(dev, - size, &t, GFP_KERNEL); + buf->direct.buf = dma_alloc_coherent(dev, size, &t, + GFP_KERNEL); if (!buf->direct.buf) return -ENOMEM; @@ -219,9 +219,10 @@ int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct, return -ENOMEM; for (i = 0; i < buf->nbufs; ++i) { - buf->page_list[i].buf = dma_zalloc_coherent(dev, - page_size, &t, - GFP_KERNEL); + buf->page_list[i].buf = dma_alloc_coherent(dev, + page_size, + &t, + GFP_KERNEL); if (!buf->page_list[i].buf) goto err_free; diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 3a669451cf86..543fa1504cd3 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -5091,7 +5091,7 @@ static int hns_roce_mhop_alloc_eq(struct hns_roce_dev *hr_dev, eqe_alloc = i * (buf_chk_sz / eq->eqe_size); size = (eq->entries - eqe_alloc) * eq->eqe_size; } - eq->buf[i] = dma_zalloc_coherent(dev, size, + eq->buf[i] = dma_alloc_coherent(dev, size, &(eq->buf_dma[i]), GFP_KERNEL); if (!eq->buf[i]) @@ -5126,9 +5126,9 @@ static int hns_roce_mhop_alloc_eq(struct hns_roce_dev *hr_dev, size = (eq->entries - eqe_alloc) * eq->eqe_size; } - eq->buf[idx] = dma_zalloc_coherent(dev, size, - &(eq->buf_dma[idx]), - GFP_KERNEL); + eq->buf[idx] = dma_alloc_coherent(dev, size, + &(eq->buf_dma[idx]), + GFP_KERNEL); if (!eq->buf[idx]) goto err_dma_alloc_buf; @@ -5241,7 +5241,7 @@ static int hns_roce_v2_create_eq(struct hns_roce_dev *hr_dev, goto free_cmd_mbox; } - eq->buf_list->buf = dma_zalloc_coherent(dev, buf_chk_sz, + eq->buf_list->buf = dma_alloc_coherent(dev, buf_chk_sz, &(eq->buf_list->map), GFP_KERNEL); if (!eq->buf_list->buf) { diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c index 960b1946c365..12deacf442cf 100644 --- a/drivers/infiniband/hw/hns/hns_roce_srq.c +++ b/drivers/infiniband/hw/hns/hns_roce_srq.c @@ -210,6 +210,7 @@ struct ib_srq *hns_roce_create_srq(struct ib_pd *pd, struct ib_udata *udata) { struct hns_roce_dev *hr_dev = to_hr_dev(pd->device); + struct hns_roce_ib_create_srq_resp resp = {}; struct hns_roce_srq *srq; int srq_desc_size; int srq_buf_size; @@ -378,16 +379,21 @@ struct ib_srq *hns_roce_create_srq(struct ib_pd *pd, srq->event = hns_roce_ib_srq_event; srq->ibsrq.ext.xrc.srq_num = srq->srqn; + resp.srqn = srq->srqn; if (udata) { - if (ib_copy_to_udata(udata, &srq->srqn, sizeof(__u32))) { + if (ib_copy_to_udata(udata, &resp, + min(udata->outlen, sizeof(resp)))) { ret = -EFAULT; - goto err_wrid; + goto err_srqc_alloc; } } return &srq->ibsrq; +err_srqc_alloc: + hns_roce_srq_free(hr_dev, srq); + err_wrid: kvfree(srq->wrid); diff --git a/drivers/infiniband/hw/i40iw/i40iw_utils.c b/drivers/infiniband/hw/i40iw/i40iw_utils.c index a9ea966877f2..59e978141ad4 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_utils.c +++ b/drivers/infiniband/hw/i40iw/i40iw_utils.c @@ -745,8 +745,8 @@ enum i40iw_status_code i40iw_allocate_dma_mem(struct i40iw_hw *hw, if (!mem) return I40IW_ERR_PARAM; mem->size = ALIGN(size, alignment); - mem->va = dma_zalloc_coherent(&pcidev->dev, mem->size, - (dma_addr_t *)&mem->pa, GFP_KERNEL); + mem->va = dma_alloc_coherent(&pcidev->dev, mem->size, + (dma_addr_t *)&mem->pa, GFP_KERNEL); if (!mem->va) return I40IW_ERR_NO_MEMORY; return 0; diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 25439da8976c..936ee1314bcd 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -1411,7 +1411,7 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port, sqp_mad = (struct mlx4_mad_snd_buf *) (sqp->tx_ring[wire_tx_ix].buf.addr); if (sqp->tx_ring[wire_tx_ix].ah) - rdma_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0); + mlx4_ib_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0); sqp->tx_ring[wire_tx_ix].ah = ah; ib_dma_sync_single_for_cpu(&dev->ib_dev, sqp->tx_ring[wire_tx_ix].buf.map, @@ -1902,7 +1902,7 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work) if (wc.status == IB_WC_SUCCESS) { switch (wc.opcode) { case IB_WC_SEND: - rdma_destroy_ah(sqp->tx_ring[wc.wr_id & + mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0); sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah = NULL; @@ -1931,7 +1931,7 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work) " status = %d, wrid = 0x%llx\n", ctx->slave, wc.status, wc.wr_id); if (!MLX4_TUN_IS_RECV(wc.wr_id)) { - rdma_destroy_ah(sqp->tx_ring[wc.wr_id & + mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0); sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah = NULL; diff --git a/drivers/infiniband/hw/mlx5/flow.c b/drivers/infiniband/hw/mlx5/flow.c index e8a1e4498e3f..798591a18484 100644 --- a/drivers/infiniband/hw/mlx5/flow.c +++ b/drivers/infiniband/hw/mlx5/flow.c @@ -630,8 +630,7 @@ const struct uapi_definition mlx5_ib_flow_defs[] = { UAPI_DEF_IS_OBJ_SUPPORTED(flow_is_supported)), UAPI_DEF_CHAIN_OBJ_TREE( UVERBS_OBJECT_FLOW, - &mlx5_ib_fs, - UAPI_DEF_IS_OBJ_SUPPORTED(flow_is_supported)), + &mlx5_ib_fs), UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION, &mlx5_ib_flow_actions), {}, diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c index 01e0f6200631..4ee32964e1dd 100644 --- a/drivers/infiniband/hw/mlx5/odp.c +++ b/drivers/infiniband/hw/mlx5/odp.c @@ -1595,10 +1595,12 @@ static void mlx5_ib_prefetch_mr_work(struct work_struct *work) struct prefetch_mr_work *w = container_of(work, struct prefetch_mr_work, work); - if (w->dev->ib_dev.reg_state == IB_DEV_REGISTERED) + if (ib_device_try_get(&w->dev->ib_dev)) { mlx5_ib_prefetch_sg_list(w->dev, w->pf_flags, w->sg_list, w->num_sge); - + ib_device_put(&w->dev->ib_dev); + } + put_device(&w->dev->ib_dev.dev); kfree(w); } @@ -1617,15 +1619,13 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd, return mlx5_ib_prefetch_sg_list(dev, pf_flags, sg_list, num_sge); - if (dev->ib_dev.reg_state != IB_DEV_REGISTERED) - return -ENODEV; - work = kvzalloc(struct_size(work, sg_list, num_sge), GFP_KERNEL); if (!work) return -ENOMEM; memcpy(work->sg_list, sg_list, num_sge * sizeof(struct ib_sge)); + get_device(&dev->ib_dev.dev); work->dev = dev; work->pf_flags = pf_flags; work->num_sge = num_sge; diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index dd2ae640bc84..7db778d96ef5 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -1912,14 +1912,16 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, } if (!check_flags_mask(ucmd.flags, + MLX5_QP_FLAG_ALLOW_SCATTER_CQE | + MLX5_QP_FLAG_BFREG_INDEX | + MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE | + MLX5_QP_FLAG_SCATTER_CQE | MLX5_QP_FLAG_SIGNATURE | - MLX5_QP_FLAG_SCATTER_CQE | - MLX5_QP_FLAG_TUNNEL_OFFLOADS | - MLX5_QP_FLAG_BFREG_INDEX | - MLX5_QP_FLAG_TYPE_DCT | - MLX5_QP_FLAG_TYPE_DCI | - MLX5_QP_FLAG_ALLOW_SCATTER_CQE | - MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE)) + MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_MC | + MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_UC | + MLX5_QP_FLAG_TUNNEL_OFFLOADS | + MLX5_QP_FLAG_TYPE_DCI | + MLX5_QP_FLAG_TYPE_DCT)) return -EINVAL; err = get_qp_user_index(to_mucontext(pd->uobject->context), diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index cc9c0c8ccba3..112d2f38e0de 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -623,8 +623,9 @@ int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type, page = dev->db_tab->page + end; alloc: - page->db_rec = dma_zalloc_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE, - &page->mapping, GFP_KERNEL); + page->db_rec = dma_alloc_coherent(&dev->pdev->dev, + MTHCA_ICM_PAGE_SIZE, &page->mapping, + GFP_KERNEL); if (!page->db_rec) { ret = -ENOMEM; goto out; diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 82cb6b71ac7c..e3e9dd54caa2 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -534,7 +534,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd, { struct mthca_ucontext *context; - qp = kmalloc(sizeof *qp, GFP_KERNEL); + qp = kzalloc(sizeof(*qp), GFP_KERNEL); if (!qp) return ERR_PTR(-ENOMEM); @@ -600,7 +600,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd, if (udata) return ERR_PTR(-EINVAL); - qp = kmalloc(sizeof (struct mthca_sqp), GFP_KERNEL); + qp = kzalloc(sizeof(struct mthca_sqp), GFP_KERNEL); if (!qp) return ERR_PTR(-ENOMEM); diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c index 241a57a07485..097e5ab2a19f 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c @@ -380,8 +380,8 @@ static int ocrdma_alloc_q(struct ocrdma_dev *dev, q->len = len; q->entry_size = entry_size; q->size = len * entry_size; - q->va = dma_zalloc_coherent(&dev->nic_info.pdev->dev, q->size, - &q->dma, GFP_KERNEL); + q->va = dma_alloc_coherent(&dev->nic_info.pdev->dev, q->size, &q->dma, + GFP_KERNEL); if (!q->va) return -ENOMEM; return 0; @@ -1819,7 +1819,7 @@ int ocrdma_mbx_create_cq(struct ocrdma_dev *dev, struct ocrdma_cq *cq, return -ENOMEM; ocrdma_init_mch(&cmd->cmd.req, OCRDMA_CMD_CREATE_CQ, OCRDMA_SUBSYS_COMMON, sizeof(*cmd)); - cq->va = dma_zalloc_coherent(&pdev->dev, cq->len, &cq->pa, GFP_KERNEL); + cq->va = dma_alloc_coherent(&pdev->dev, cq->len, &cq->pa, GFP_KERNEL); if (!cq->va) { status = -ENOMEM; goto mem_err; @@ -2209,7 +2209,7 @@ static int ocrdma_set_create_qp_sq_cmd(struct ocrdma_create_qp_req *cmd, qp->sq.max_cnt = max_wqe_allocated; len = (hw_pages * hw_page_size); - qp->sq.va = dma_zalloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL); + qp->sq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL); if (!qp->sq.va) return -EINVAL; qp->sq.len = len; @@ -2259,7 +2259,7 @@ static int ocrdma_set_create_qp_rq_cmd(struct ocrdma_create_qp_req *cmd, qp->rq.max_cnt = max_rqe_allocated; len = (hw_pages * hw_page_size); - qp->rq.va = dma_zalloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL); + qp->rq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL); if (!qp->rq.va) return -ENOMEM; qp->rq.pa = pa; @@ -2315,8 +2315,8 @@ static int ocrdma_set_create_qp_ird_cmd(struct ocrdma_create_qp_req *cmd, if (dev->attr.ird == 0) return 0; - qp->ird_q_va = dma_zalloc_coherent(&pdev->dev, ird_q_len, &pa, - GFP_KERNEL); + qp->ird_q_va = dma_alloc_coherent(&pdev->dev, ird_q_len, &pa, + GFP_KERNEL); if (!qp->ird_q_va) return -ENOMEM; ocrdma_build_q_pages(&cmd->ird_addr[0], dev->attr.num_ird_pages, diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c index dd15474b19b7..6be0ea109138 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c @@ -73,8 +73,8 @@ bool ocrdma_alloc_stats_resources(struct ocrdma_dev *dev) mem->size = max_t(u32, sizeof(struct ocrdma_rdma_stats_req), sizeof(struct ocrdma_rdma_stats_resp)); - mem->va = dma_zalloc_coherent(&dev->nic_info.pdev->dev, mem->size, - &mem->pa, GFP_KERNEL); + mem->va = dma_alloc_coherent(&dev->nic_info.pdev->dev, mem->size, + &mem->pa, GFP_KERNEL); if (!mem->va) { pr_err("%s: stats mbox allocation failed\n", __func__); return false; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index c46bed0c5513..287c332ff0e6 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -504,8 +504,8 @@ struct ib_ucontext *ocrdma_alloc_ucontext(struct ib_device *ibdev, INIT_LIST_HEAD(&ctx->mm_head); mutex_init(&ctx->mm_list_lock); - ctx->ah_tbl.va = dma_zalloc_coherent(&pdev->dev, map_len, - &ctx->ah_tbl.pa, GFP_KERNEL); + ctx->ah_tbl.va = dma_alloc_coherent(&pdev->dev, map_len, + &ctx->ah_tbl.pa, GFP_KERNEL); if (!ctx->ah_tbl.va) { kfree(ctx); return ERR_PTR(-ENOMEM); @@ -838,7 +838,7 @@ static int ocrdma_build_pbl_tbl(struct ocrdma_dev *dev, struct ocrdma_hw_mr *mr) return -ENOMEM; for (i = 0; i < mr->num_pbls; i++) { - va = dma_zalloc_coherent(&pdev->dev, dma_len, &pa, GFP_KERNEL); + va = dma_alloc_coherent(&pdev->dev, dma_len, &pa, GFP_KERNEL); if (!va) { ocrdma_free_mr_pbl_tbl(dev, mr); status = -ENOMEM; diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c index b342a70e2814..e1ccf32b1c3d 100644 --- a/drivers/infiniband/hw/qedr/verbs.c +++ b/drivers/infiniband/hw/qedr/verbs.c @@ -556,8 +556,8 @@ static struct qedr_pbl *qedr_alloc_pbl_tbl(struct qedr_dev *dev, return ERR_PTR(-ENOMEM); for (i = 0; i < pbl_info->num_pbls; i++) { - va = dma_zalloc_coherent(&pdev->dev, pbl_info->pbl_size, - &pa, flags); + va = dma_alloc_coherent(&pdev->dev, pbl_info->pbl_size, &pa, + flags); if (!va) goto err; diff --git a/drivers/infiniband/hw/qib/qib_ud.c b/drivers/infiniband/hw/qib/qib_ud.c index 868da0ece7ba..445ea19a2ec8 100644 --- a/drivers/infiniband/hw/qib/qib_ud.c +++ b/drivers/infiniband/hw/qib/qib_ud.c @@ -512,7 +512,6 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct ib_header *hdr, opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) { wc.ex.imm_data = ohdr->u.ud.imm_data; wc.wc_flags = IB_WC_WITH_IMM; - tlen -= sizeof(u32); } else if (opcode == IB_OPCODE_UD_SEND_ONLY) { wc.ex.imm_data = 0; wc.wc_flags = 0; diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h b/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h index 42b8685c997e..3c633ab58052 100644 --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h @@ -427,7 +427,40 @@ static inline enum ib_qp_state pvrdma_qp_state_to_ib(enum pvrdma_qp_state state) static inline enum pvrdma_wr_opcode ib_wr_opcode_to_pvrdma(enum ib_wr_opcode op) { - return (enum pvrdma_wr_opcode)op; + switch (op) { + case IB_WR_RDMA_WRITE: + return PVRDMA_WR_RDMA_WRITE; + case IB_WR_RDMA_WRITE_WITH_IMM: + return PVRDMA_WR_RDMA_WRITE_WITH_IMM; + case IB_WR_SEND: + return PVRDMA_WR_SEND; + case IB_WR_SEND_WITH_IMM: + return PVRDMA_WR_SEND_WITH_IMM; + case IB_WR_RDMA_READ: + return PVRDMA_WR_RDMA_READ; + case IB_WR_ATOMIC_CMP_AND_SWP: + return PVRDMA_WR_ATOMIC_CMP_AND_SWP; + case IB_WR_ATOMIC_FETCH_AND_ADD: + return PVRDMA_WR_ATOMIC_FETCH_AND_ADD; + case IB_WR_LSO: + return PVRDMA_WR_LSO; + case IB_WR_SEND_WITH_INV: + return PVRDMA_WR_SEND_WITH_INV; + case IB_WR_RDMA_READ_WITH_INV: + return PVRDMA_WR_RDMA_READ_WITH_INV; + case IB_WR_LOCAL_INV: + return PVRDMA_WR_LOCAL_INV; + case IB_WR_REG_MR: + return PVRDMA_WR_FAST_REG_MR; + case IB_WR_MASKED_ATOMIC_CMP_AND_SWP: + return PVRDMA_WR_MASKED_ATOMIC_CMP_AND_SWP; + case IB_WR_MASKED_ATOMIC_FETCH_AND_ADD: + return PVRDMA_WR_MASKED_ATOMIC_FETCH_AND_ADD; + case IB_WR_REG_SIG_MR: + return PVRDMA_WR_REG_SIG_MR; + default: + return PVRDMA_WR_ERROR; + } } static inline enum ib_wc_status pvrdma_wc_status_to_ib( diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c index eaa109dbc96a..39c37b6fd715 100644 --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c @@ -890,8 +890,8 @@ static int pvrdma_pci_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "device version %d, driver version %d\n", dev->dsr_version, PVRDMA_VERSION); - dev->dsr = dma_zalloc_coherent(&pdev->dev, sizeof(*dev->dsr), - &dev->dsrbase, GFP_KERNEL); + dev->dsr = dma_alloc_coherent(&pdev->dev, sizeof(*dev->dsr), + &dev->dsrbase, GFP_KERNEL); if (!dev->dsr) { dev_err(&pdev->dev, "failed to allocate shared region\n"); ret = -ENOMEM; diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c index 3acf74cbe266..1ec3646087ba 100644 --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c @@ -721,6 +721,12 @@ int pvrdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) wqe_hdr->ex.imm_data = wr->ex.imm_data; + if (unlikely(wqe_hdr->opcode == PVRDMA_WR_ERROR)) { + *bad_wr = wr; + ret = -EINVAL; + goto out; + } + switch (qp->ibqp.qp_type) { case IB_QPT_GSI: case IB_QPT_UD: diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index a1bd8cfc2c25..c6cc3e4ab71d 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -2910,6 +2910,8 @@ send: goto op_err; if (!ret) goto rnr_nak; + if (wqe->length > qp->r_len) + goto inv_err; break; case IB_WR_RDMA_WRITE_WITH_IMM: @@ -3078,7 +3080,10 @@ op_err: goto err; inv_err: - send_status = IB_WC_REM_INV_REQ_ERR; + send_status = + sqp->ibqp.qp_type == IB_QPT_RC ? + IB_WC_REM_INV_REQ_ERR : + IB_WC_SUCCESS; wc.status = IB_WC_LOC_QP_OP_ERR; goto err; diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 1da119d901a9..73e808c1e6ad 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -248,7 +248,6 @@ struct ipoib_cm_tx { struct list_head list; struct net_device *dev; struct ipoib_neigh *neigh; - struct ipoib_path *path; struct ipoib_tx_buf *tx_ring; unsigned int tx_head; unsigned int tx_tail; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 0428e01e8f69..aa9dcfc36cd3 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -1312,7 +1312,6 @@ struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path neigh->cm = tx; tx->neigh = neigh; - tx->path = path; tx->dev = dev; list_add(&tx->list, &priv->cm.start_list); set_bit(IPOIB_FLAG_INITIALIZED, &tx->flags); @@ -1371,7 +1370,7 @@ static void ipoib_cm_tx_start(struct work_struct *work) neigh->daddr + QPN_AND_OPTIONS_OFFSET); goto free_neigh; } - memcpy(&pathrec, &p->path->pathrec, sizeof(pathrec)); + memcpy(&pathrec, &path->pathrec, sizeof(pathrec)); spin_unlock_irqrestore(&priv->lock, flags); netif_tx_unlock_bh(dev); diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 31d91538bbf4..694324b37480 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -3032,7 +3032,6 @@ static int srp_reset_device(struct scsi_cmnd *scmnd) { struct srp_target_port *target = host_to_target(scmnd->device->host); struct srp_rdma_ch *ch; - int i, j; u8 status; shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n"); @@ -3044,15 +3043,6 @@ static int srp_reset_device(struct scsi_cmnd *scmnd) if (status) return FAILED; - for (i = 0; i < target->ch_count; i++) { - ch = &target->ch[i]; - for (j = 0; j < target->req_ring_size; ++j) { - struct srp_request *req = &ch->req_ring[j]; - - srp_finish_req(ch, req, scmnd->device, DID_RESET << 16); - } - } - return SUCCESS; } diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index cfc8b94527b9..aa4e431cbcd3 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -252,6 +252,8 @@ static const struct xpad_device { { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, + { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, + { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 }, { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 }, @@ -428,6 +430,7 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */ XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */ + XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries Controllers */ XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */ XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */ XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 4713957b0cbb..a878351f1643 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -420,7 +420,7 @@ config KEYBOARD_MPR121 config KEYBOARD_SNVS_PWRKEY tristate "IMX SNVS Power Key Driver" - depends on SOC_IMX6SX + depends on SOC_IMX6SX || SOC_IMX7D depends on OF help This is the snvs powerkey driver for the Freescale i.MX application diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c index 312916f99597..73686c2460ce 100644 --- a/drivers/input/keyboard/cap11xx.c +++ b/drivers/input/keyboard/cap11xx.c @@ -75,9 +75,7 @@ struct cap11xx_led { struct cap11xx_priv *priv; struct led_classdev cdev; - struct work_struct work; u32 reg; - enum led_brightness new_brightness; }; #endif @@ -233,30 +231,21 @@ static void cap11xx_input_close(struct input_dev *idev) } #ifdef CONFIG_LEDS_CLASS -static void cap11xx_led_work(struct work_struct *work) +static int cap11xx_led_set(struct led_classdev *cdev, + enum led_brightness value) { - struct cap11xx_led *led = container_of(work, struct cap11xx_led, work); + struct cap11xx_led *led = container_of(cdev, struct cap11xx_led, cdev); struct cap11xx_priv *priv = led->priv; - int value = led->new_brightness; /* - * All LEDs share the same duty cycle as this is a HW limitation. - * Brightness levels per LED are either 0 (OFF) and 1 (ON). + * All LEDs share the same duty cycle as this is a HW + * limitation. Brightness levels per LED are either + * 0 (OFF) and 1 (ON). */ - regmap_update_bits(priv->regmap, CAP11XX_REG_LED_OUTPUT_CONTROL, - BIT(led->reg), value ? BIT(led->reg) : 0); -} - -static void cap11xx_led_set(struct led_classdev *cdev, - enum led_brightness value) -{ - struct cap11xx_led *led = container_of(cdev, struct cap11xx_led, cdev); - - if (led->new_brightness == value) - return; - - led->new_brightness = value; - schedule_work(&led->work); + return regmap_update_bits(priv->regmap, + CAP11XX_REG_LED_OUTPUT_CONTROL, + BIT(led->reg), + value ? BIT(led->reg) : 0); } static int cap11xx_init_leds(struct device *dev, @@ -299,7 +288,7 @@ static int cap11xx_init_leds(struct device *dev, led->cdev.default_trigger = of_get_property(child, "linux,default-trigger", NULL); led->cdev.flags = 0; - led->cdev.brightness_set = cap11xx_led_set; + led->cdev.brightness_set_blocking = cap11xx_led_set; led->cdev.max_brightness = 1; led->cdev.brightness = LED_OFF; @@ -312,8 +301,6 @@ static int cap11xx_init_leds(struct device *dev, led->reg = reg; led->priv = priv; - INIT_WORK(&led->work, cap11xx_led_work); - error = devm_led_classdev_register(dev, &led->cdev); if (error) { of_node_put(child); diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 403452ef00e6..3d1cb7bf5e35 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -222,7 +222,7 @@ static void matrix_keypad_stop(struct input_dev *dev) keypad->stopped = true; spin_unlock_irq(&keypad->lock); - flush_work(&keypad->work.work); + flush_delayed_work(&keypad->work); /* * matrix_keypad_scan() will leave IRQs enabled; * we should disable them now. diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index 43b86482dda0..d466bc07aebb 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c @@ -58,10 +58,9 @@ static unsigned char qt2160_key2code[] = { struct qt2160_led { struct qt2160_data *qt2160; struct led_classdev cdev; - struct work_struct work; char name[32]; int id; - enum led_brightness new_brightness; + enum led_brightness brightness; }; #endif @@ -74,7 +73,6 @@ struct qt2160_data { u16 key_matrix; #ifdef CONFIG_LEDS_CLASS struct qt2160_led leds[QT2160_NUM_LEDS_X]; - struct mutex led_lock; #endif }; @@ -83,46 +81,39 @@ static int qt2160_write(struct i2c_client *client, u8 reg, u8 data); #ifdef CONFIG_LEDS_CLASS -static void qt2160_led_work(struct work_struct *work) +static int qt2160_led_set(struct led_classdev *cdev, + enum led_brightness value) { - struct qt2160_led *led = container_of(work, struct qt2160_led, work); + struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev); struct qt2160_data *qt2160 = led->qt2160; struct i2c_client *client = qt2160->client; - int value = led->new_brightness; u32 drive, pwmen; - mutex_lock(&qt2160->led_lock); - - drive = qt2160_read(client, QT2160_CMD_DRIVE_X); - pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X); - if (value != LED_OFF) { - drive |= (1 << led->id); - pwmen |= (1 << led->id); - - } else { - drive &= ~(1 << led->id); - pwmen &= ~(1 << led->id); - } - qt2160_write(client, QT2160_CMD_DRIVE_X, drive); - qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen); + if (value != led->brightness) { + drive = qt2160_read(client, QT2160_CMD_DRIVE_X); + pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X); + if (value != LED_OFF) { + drive |= BIT(led->id); + pwmen |= BIT(led->id); - /* - * Changing this register will change the brightness - * of every LED in the qt2160. It's a HW limitation. - */ - if (value != LED_OFF) - qt2160_write(client, QT2160_CMD_PWM_DUTY, value); + } else { + drive &= ~BIT(led->id); + pwmen &= ~BIT(led->id); + } + qt2160_write(client, QT2160_CMD_DRIVE_X, drive); + qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen); - mutex_unlock(&qt2160->led_lock); -} + /* + * Changing this register will change the brightness + * of every LED in the qt2160. It's a HW limitation. + */ + if (value != LED_OFF) + qt2160_write(client, QT2160_CMD_PWM_DUTY, value); -static void qt2160_led_set(struct led_classdev *cdev, - enum led_brightness value) -{ - struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev); + led->brightness = value; + } - led->new_brightness = value; - schedule_work(&led->work); + return 0; } #endif /* CONFIG_LEDS_CLASS */ @@ -293,20 +284,16 @@ static int qt2160_register_leds(struct qt2160_data *qt2160) int ret; int i; - mutex_init(&qt2160->led_lock); - for (i = 0; i < QT2160_NUM_LEDS_X; i++) { struct qt2160_led *led = &qt2160->leds[i]; snprintf(led->name, sizeof(led->name), "qt2160:x%d", i); led->cdev.name = led->name; - led->cdev.brightness_set = qt2160_led_set; + led->cdev.brightness_set_blocking = qt2160_led_set; led->cdev.brightness = LED_OFF; led->id = i; led->qt2160 = qt2160; - INIT_WORK(&led->work, qt2160_led_work); - ret = led_classdev_register(&client->dev, &led->cdev); if (ret < 0) return ret; @@ -324,10 +311,8 @@ static void qt2160_unregister_leds(struct qt2160_data *qt2160) { int i; - for (i = 0; i < QT2160_NUM_LEDS_X; i++) { + for (i = 0; i < QT2160_NUM_LEDS_X; i++) led_classdev_unregister(&qt2160->leds[i].cdev); - cancel_work_sync(&qt2160->leds[i].work); - } } #else diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c index babcfb165e4f..3b85631fde91 100644 --- a/drivers/input/keyboard/st-keyscan.c +++ b/drivers/input/keyboard/st-keyscan.c @@ -153,6 +153,8 @@ static int keyscan_probe(struct platform_device *pdev) input_dev->id.bustype = BUS_HOST; + keypad_data->input_dev = input_dev; + error = keypad_matrix_key_parse_dt(keypad_data); if (error) return error; @@ -168,8 +170,6 @@ static int keyscan_probe(struct platform_device *pdev) input_set_drvdata(input_dev, keypad_data); - keypad_data->input_dev = input_dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); keypad_data->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(keypad_data->base)) diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c index 094bddf56755..c1e66f45d552 100644 --- a/drivers/input/misc/apanel.c +++ b/drivers/input/misc/apanel.c @@ -22,7 +22,6 @@ #include <linux/io.h> #include <linux/input-polldev.h> #include <linux/i2c.h> -#include <linux/workqueue.h> #include <linux/leds.h> #define APANEL_NAME "Fujitsu Application Panel" @@ -59,8 +58,6 @@ struct apanel { struct i2c_client *client; unsigned short keymap[MAX_PANEL_KEYS]; u16 nkeys; - u16 led_bits; - struct work_struct led_work; struct led_classdev mail_led; }; @@ -109,25 +106,13 @@ static void apanel_poll(struct input_polled_dev *ipdev) report_key(idev, ap->keymap[i]); } -/* Track state changes of LED */ -static void led_update(struct work_struct *work) -{ - struct apanel *ap = container_of(work, struct apanel, led_work); - - i2c_smbus_write_word_data(ap->client, 0x10, ap->led_bits); -} - -static void mail_led_set(struct led_classdev *led, +static int mail_led_set(struct led_classdev *led, enum led_brightness value) { struct apanel *ap = container_of(led, struct apanel, mail_led); + u16 led_bits = value != LED_OFF ? 0x8000 : 0x0000; - if (value != LED_OFF) - ap->led_bits |= 0x8000; - else - ap->led_bits &= ~0x8000; - - schedule_work(&ap->led_work); + return i2c_smbus_write_word_data(ap->client, 0x10, led_bits); } static int apanel_remove(struct i2c_client *client) @@ -179,7 +164,7 @@ static struct apanel apanel = { }, .mail_led = { .name = "mail:blue", - .brightness_set = mail_led_set, + .brightness_set_blocking = mail_led_set, }, }; @@ -235,7 +220,6 @@ static int apanel_probe(struct i2c_client *client, if (err) goto out3; - INIT_WORK(&ap->led_work, led_update); if (device_chip[APANEL_DEV_LED] != CHIP_NONE) { err = led_classdev_register(&client->dev, &ap->mail_led); if (err) diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index 1efcfdf9f8a8..dd9dd4e40827 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -481,13 +481,14 @@ static int bma150_register_input_device(struct bma150_data *bma150) idev->close = bma150_irq_close; input_set_drvdata(idev, bma150); + bma150->input = idev; + error = input_register_device(idev); if (error) { input_free_device(idev); return error; } - bma150->input = idev; return 0; } @@ -510,15 +511,15 @@ static int bma150_register_polled_device(struct bma150_data *bma150) bma150_init_input_device(bma150, ipoll_dev->input); + bma150->input_polled = ipoll_dev; + bma150->input = ipoll_dev->input; + error = input_register_polled_device(ipoll_dev); if (error) { input_free_polled_device(ipoll_dev); return error; } - bma150->input_polled = ipoll_dev; - bma150->input = ipoll_dev->input; - return 0; } diff --git a/drivers/input/misc/pwm-vibra.c b/drivers/input/misc/pwm-vibra.c index 55da191ae550..dbb6d9e1b947 100644 --- a/drivers/input/misc/pwm-vibra.c +++ b/drivers/input/misc/pwm-vibra.c @@ -34,6 +34,7 @@ struct pwm_vibrator { struct work_struct play_work; u16 level; u32 direction_duty_cycle; + bool vcc_on; }; static int pwm_vibrator_start(struct pwm_vibrator *vibrator) @@ -42,10 +43,13 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator) struct pwm_state state; int err; - err = regulator_enable(vibrator->vcc); - if (err) { - dev_err(pdev, "failed to enable regulator: %d", err); - return err; + if (!vibrator->vcc_on) { + err = regulator_enable(vibrator->vcc); + if (err) { + dev_err(pdev, "failed to enable regulator: %d", err); + return err; + } + vibrator->vcc_on = true; } pwm_get_state(vibrator->pwm, &state); @@ -76,11 +80,14 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator) static void pwm_vibrator_stop(struct pwm_vibrator *vibrator) { - regulator_disable(vibrator->vcc); - if (vibrator->pwm_dir) pwm_disable(vibrator->pwm_dir); pwm_disable(vibrator->pwm); + + if (vibrator->vcc_on) { + regulator_disable(vibrator->vcc); + vibrator->vcc_on = false; + } } static void pwm_vibrator_play_work(struct work_struct *work) diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 8ec483e8688b..26ec603fe220 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -39,6 +39,7 @@ #include <linux/init.h> #include <linux/fs.h> #include <linux/miscdevice.h> +#include <linux/overflow.h> #include <linux/input/mt.h> #include "../input-compat.h" @@ -405,7 +406,7 @@ static int uinput_open(struct inode *inode, struct file *file) static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code, const struct input_absinfo *abs) { - int min, max; + int min, max, range; min = abs->minimum; max = abs->maximum; @@ -417,7 +418,7 @@ static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code, return -EINVAL; } - if (abs->flat > max - min) { + if (!check_sub_overflow(max, min, &range) && abs->flat > range) { printk(KERN_DEBUG "%s: abs_flat #%02x out of range: %d (min:%d/max:%d)\n", UINPUT_NAME, code, abs->flat, min, max); diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index f322a1768fbb..225ae6980182 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1336,7 +1336,6 @@ MODULE_DEVICE_TABLE(i2c, elan_id); static const struct acpi_device_id elan_acpi_id[] = { { "ELAN0000", 0 }, { "ELAN0100", 0 }, - { "ELAN0501", 0 }, { "ELAN0600", 0 }, { "ELAN0602", 0 }, { "ELAN0605", 0 }, @@ -1346,6 +1345,7 @@ static const struct acpi_device_id elan_acpi_id[] = { { "ELAN060C", 0 }, { "ELAN0611", 0 }, { "ELAN0612", 0 }, + { "ELAN0617", 0 }, { "ELAN0618", 0 }, { "ELAN061C", 0 }, { "ELAN061D", 0 }, diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 9fe075c137dc..a7f8b1614559 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1119,6 +1119,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, * Asus UX31 0x361f00 20, 15, 0e clickpad * Asus UX32VD 0x361f02 00, 15, 0e clickpad * Avatar AVIU-145A2 0x361f00 ? clickpad + * Fujitsu CELSIUS H760 0x570f02 40, 14, 0c 3 hw buttons (**) + * Fujitsu CELSIUS H780 0x5d0f02 41, 16, 0d 3 hw buttons (**) * Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons * Fujitsu LIFEBOOK E546 0x470f00 50, 12, 09 2 hw buttons * Fujitsu LIFEBOOK E547 0x470f00 50, 12, 09 2 hw buttons @@ -1171,6 +1173,13 @@ static const struct dmi_system_id elantech_dmi_has_middle_button[] = { DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H760"), }, }, + { + /* Fujitsu H780 also has a middle button */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), + DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H780"), + }, + }, #endif { } }; diff --git a/drivers/input/serio/olpc_apsp.c b/drivers/input/serio/olpc_apsp.c index b36084710f69..a7cfab3db9ee 100644 --- a/drivers/input/serio/olpc_apsp.c +++ b/drivers/input/serio/olpc_apsp.c @@ -23,7 +23,6 @@ #include <linux/of.h> #include <linux/slab.h> #include <linux/delay.h> -#include <linux/clk.h> /* * The OLPC XO-1.75 and XO-4 laptops do not have a hardware PS/2 controller. @@ -75,7 +74,6 @@ struct olpc_apsp { struct serio *kbio; struct serio *padio; void __iomem *base; - struct clk *clk; int open_count; int irq; }; @@ -148,17 +146,11 @@ static int olpc_apsp_open(struct serio *port) struct olpc_apsp *priv = port->port_data; unsigned int tmp; unsigned long l; - int error; if (priv->open_count++ == 0) { - error = clk_prepare_enable(priv->clk); - if (error) - return error; - l = readl(priv->base + COMMAND_FIFO_STATUS); if (!(l & CMD_STS_MASK)) { dev_err(priv->dev, "SP cannot accept commands.\n"); - clk_disable_unprepare(priv->clk); return -EIO; } @@ -179,8 +171,6 @@ static void olpc_apsp_close(struct serio *port) /* Disable interrupt 0 */ tmp = readl(priv->base + PJ_INTERRUPT_MASK); writel(tmp | INT_0, priv->base + PJ_INTERRUPT_MASK); - - clk_disable_unprepare(priv->clk); } } @@ -195,6 +185,8 @@ static int olpc_apsp_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + priv->dev = &pdev->dev; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->base)) { @@ -206,10 +198,6 @@ static int olpc_apsp_probe(struct platform_device *pdev) if (priv->irq < 0) return priv->irq; - priv->clk = devm_clk_get(&pdev->dev, "sp"); - if (IS_ERR(priv->clk)) - return PTR_ERR(priv->clk); - /* KEYBOARD */ kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); if (!kb_serio) @@ -248,7 +236,6 @@ static int olpc_apsp_probe(struct platform_device *pdev) goto err_irq; } - priv->dev = &pdev->dev; device_init_wakeup(priv->dev, 1); platform_set_drvdata(pdev, priv); diff --git a/drivers/input/serio/ps2-gpio.c b/drivers/input/serio/ps2-gpio.c index c62cceb97bb1..5e8d8384aa2a 100644 --- a/drivers/input/serio/ps2-gpio.c +++ b/drivers/input/serio/ps2-gpio.c @@ -76,6 +76,7 @@ static void ps2_gpio_close(struct serio *serio) { struct ps2_gpio_data *drvdata = serio->port_data; + flush_delayed_work(&drvdata->tx_work); disable_irq(drvdata->irq); } diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index af6027cc7bbf..068dbbc610fc 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -698,7 +698,7 @@ config TOUCHSCREEN_EDT_FT5X06 config TOUCHSCREEN_RASPBERRYPI_FW tristate "Raspberry Pi's firmware base touch screen support" - depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST + depends on RASPBERRYPI_FIRMWARE || (RASPBERRYPI_FIRMWARE=n && COMPILE_TEST) help Say Y here if you have the official Raspberry Pi 7 inch screen on your system. diff --git a/drivers/input/touchscreen/raspberrypi-ts.c b/drivers/input/touchscreen/raspberrypi-ts.c index f456c1125bd6..69881265d121 100644 --- a/drivers/input/touchscreen/raspberrypi-ts.c +++ b/drivers/input/touchscreen/raspberrypi-ts.c @@ -147,8 +147,8 @@ static int rpi_ts_probe(struct platform_device *pdev) return -ENOMEM; ts->pdev = pdev; - ts->fw_regs_va = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->fw_regs_phys, - GFP_KERNEL); + ts->fw_regs_va = dma_alloc_coherent(dev, PAGE_SIZE, &ts->fw_regs_phys, + GFP_KERNEL); if (!ts->fw_regs_va) { dev_err(dev, "failed to dma_alloc_coherent\n"); return -ENOMEM; diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 87ba23a75b38..2a7b78bb98b4 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -1991,16 +1991,13 @@ static void do_attach(struct iommu_dev_data *dev_data, static void do_detach(struct iommu_dev_data *dev_data) { + struct protection_domain *domain = dev_data->domain; struct amd_iommu *iommu; u16 alias; iommu = amd_iommu_rlookup_table[dev_data->devid]; alias = dev_data->alias; - /* decrease reference counters */ - dev_data->domain->dev_iommu[iommu->index] -= 1; - dev_data->domain->dev_cnt -= 1; - /* Update data structures */ dev_data->domain = NULL; list_del(&dev_data->list); @@ -2010,6 +2007,16 @@ static void do_detach(struct iommu_dev_data *dev_data) /* Flush the DTE entry */ device_flush_dte(dev_data); + + /* Flush IOTLB */ + domain_flush_tlb_pde(domain); + + /* Wait for the flushes to finish */ + domain_flush_complete(domain); + + /* decrease reference counters - needs to happen after the flushes */ + domain->dev_iommu[iommu->index] -= 1; + domain->dev_cnt -= 1; } /* @@ -2617,13 +2624,13 @@ out_unmap: bus_addr = address + s->dma_address + (j << PAGE_SHIFT); iommu_unmap_page(domain, bus_addr, PAGE_SIZE); - if (--mapped_pages) + if (--mapped_pages == 0) goto out_free_iova; } } out_free_iova: - free_iova_fast(&dma_dom->iovad, address, npages); + free_iova_fast(&dma_dom->iovad, address >> PAGE_SHIFT, npages); out_err: return 0; diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index dc9f14811e0f..58dc70bffd5b 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -144,7 +144,7 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event) for (tmp = dev; tmp; tmp = tmp->bus->self) level++; - size = sizeof(*info) + level * sizeof(struct acpi_dmar_pci_path); + size = sizeof(*info) + level * sizeof(info->path[0]); if (size <= sizeof(dmar_pci_notify_info_buf)) { info = (struct dmar_pci_notify_info *)dmar_pci_notify_info_buf; } else { diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 2bd9ac285c0d..78188bf7e90d 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -363,7 +363,7 @@ static int dmar_map_gfx = 1; static int dmar_forcedac; static int intel_iommu_strict; static int intel_iommu_superpage = 1; -static int intel_iommu_sm = 1; +static int intel_iommu_sm; static int iommu_identity_mapping; #define IDENTMAP_ALL 1 @@ -456,9 +456,9 @@ static int __init intel_iommu_setup(char *str) } else if (!strncmp(str, "sp_off", 6)) { pr_info("Disable supported super page\n"); intel_iommu_superpage = 0; - } else if (!strncmp(str, "sm_off", 6)) { - pr_info("Intel-IOMMU: disable scalable mode support\n"); - intel_iommu_sm = 0; + } else if (!strncmp(str, "sm_on", 5)) { + pr_info("Intel-IOMMU: scalable mode supported\n"); + intel_iommu_sm = 1; } else if (!strncmp(str, "tboot_noforce", 13)) { printk(KERN_INFO "Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n"); @@ -5294,7 +5294,7 @@ static void intel_iommu_put_resv_regions(struct device *dev, struct iommu_resv_region *entry, *next; list_for_each_entry_safe(entry, next, head, list) { - if (entry->type == IOMMU_RESV_RESERVED) + if (entry->type == IOMMU_RESV_MSI) kfree(entry); } } diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index 6ede4286b835..7e0df67bd3e9 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -232,9 +232,8 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data) spin_lock_init(&dom->pgtlock); - dom->pgt_va = dma_zalloc_coherent(data->dev, - M2701_IOMMU_PGT_SIZE, - &dom->pgt_pa, GFP_KERNEL); + dom->pgt_va = dma_alloc_coherent(data->dev, M2701_IOMMU_PGT_SIZE, + &dom->pgt_pa, GFP_KERNEL); if (!dom->pgt_va) return -ENOMEM; @@ -442,6 +441,10 @@ static int mtk_iommu_add_device(struct device *dev) iommu_spec.args_count = count; mtk_iommu_create_mapping(dev, &iommu_spec); + + /* dev->iommu_fwspec might have changed */ + fwspec = dev_iommu_fwspec_get(dev); + of_node_put(iommu_spec.np); } diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index d8947b28db2d..f04a6df65eb8 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -224,7 +224,7 @@ const struct iommu_ops *of_iommu_configure(struct device *dev, * If we have reason to believe the IOMMU driver missed the initial * probe for dev, replay it to get things in order. */ - if (dev->bus && !device_iommu_mapped(dev)) + if (!err && dev->bus && !device_iommu_mapped(dev)) err = iommu_probe_device(dev); /* Ignore all other errors apart from EPROBE_DEFER */ diff --git a/drivers/irqchip/irq-csky-apb-intc.c b/drivers/irqchip/irq-csky-apb-intc.c index 2543baba8b1f..5a2ec43b7ddd 100644 --- a/drivers/irqchip/irq-csky-apb-intc.c +++ b/drivers/irqchip/irq-csky-apb-intc.c @@ -95,7 +95,7 @@ static inline void setup_irq_channel(u32 magic, void __iomem *reg_addr) /* Setup 64 channel slots */ for (i = 0; i < INTC_IRQS; i += 4) - writel_relaxed(build_channel_val(i, magic), reg_addr + i); + writel(build_channel_val(i, magic), reg_addr + i); } static int __init @@ -135,16 +135,10 @@ ck_intc_init_comm(struct device_node *node, struct device_node *parent) static inline bool handle_irq_perbit(struct pt_regs *regs, u32 hwirq, u32 irq_base) { - u32 irq; - if (hwirq == 0) return 0; - while (hwirq) { - irq = __ffs(hwirq); - hwirq &= ~BIT(irq); - handle_domain_irq(root_domain, irq_base + irq, regs); - } + handle_domain_irq(root_domain, irq_base + __fls(hwirq), regs); return 1; } @@ -154,12 +148,16 @@ static void gx_irq_handler(struct pt_regs *regs) { bool ret; - do { - ret = handle_irq_perbit(regs, - readl_relaxed(reg_base + GX_INTC_PEN31_00), 0); - ret |= handle_irq_perbit(regs, - readl_relaxed(reg_base + GX_INTC_PEN63_32), 32); - } while (ret); +retry: + ret = handle_irq_perbit(regs, + readl(reg_base + GX_INTC_PEN63_32), 32); + if (ret) + goto retry; + + ret = handle_irq_perbit(regs, + readl(reg_base + GX_INTC_PEN31_00), 0); + if (ret) + goto retry; } static int __init @@ -174,14 +172,14 @@ gx_intc_init(struct device_node *node, struct device_node *parent) /* * Initial enable reg to disable all interrupts */ - writel_relaxed(0x0, reg_base + GX_INTC_NEN31_00); - writel_relaxed(0x0, reg_base + GX_INTC_NEN63_32); + writel(0x0, reg_base + GX_INTC_NEN31_00); + writel(0x0, reg_base + GX_INTC_NEN63_32); /* * Initial mask reg with all unmasked, because we only use enalbe reg */ - writel_relaxed(0x0, reg_base + GX_INTC_NMASK31_00); - writel_relaxed(0x0, reg_base + GX_INTC_NMASK63_32); + writel(0x0, reg_base + GX_INTC_NMASK31_00); + writel(0x0, reg_base + GX_INTC_NMASK63_32); setup_irq_channel(0x03020100, reg_base + GX_INTC_SOURCE); @@ -204,20 +202,29 @@ static void ck_irq_handler(struct pt_regs *regs) void __iomem *reg_pen_lo = reg_base + CK_INTC_PEN31_00; void __iomem *reg_pen_hi = reg_base + CK_INTC_PEN63_32; - do { - /* handle 0 - 31 irqs */ - ret = handle_irq_perbit(regs, readl_relaxed(reg_pen_lo), 0); - ret |= handle_irq_perbit(regs, readl_relaxed(reg_pen_hi), 32); +retry: + /* handle 0 - 63 irqs */ + ret = handle_irq_perbit(regs, readl(reg_pen_hi), 32); + if (ret) + goto retry; - if (nr_irq == INTC_IRQS) - continue; + ret = handle_irq_perbit(regs, readl(reg_pen_lo), 0); + if (ret) + goto retry; + + if (nr_irq == INTC_IRQS) + return; - /* handle 64 - 127 irqs */ - ret |= handle_irq_perbit(regs, - readl_relaxed(reg_pen_lo + CK_INTC_DUAL_BASE), 64); - ret |= handle_irq_perbit(regs, - readl_relaxed(reg_pen_hi + CK_INTC_DUAL_BASE), 96); - } while (ret); + /* handle 64 - 127 irqs */ + ret = handle_irq_perbit(regs, + readl(reg_pen_hi + CK_INTC_DUAL_BASE), 96); + if (ret) + goto retry; + + ret = handle_irq_perbit(regs, + readl(reg_pen_lo + CK_INTC_DUAL_BASE), 64); + if (ret) + goto retry; } static int __init @@ -230,11 +237,11 @@ ck_intc_init(struct device_node *node, struct device_node *parent) return ret; /* Initial enable reg to disable all interrupts */ - writel_relaxed(0, reg_base + CK_INTC_NEN31_00); - writel_relaxed(0, reg_base + CK_INTC_NEN63_32); + writel(0, reg_base + CK_INTC_NEN31_00); + writel(0, reg_base + CK_INTC_NEN63_32); /* Enable irq intc */ - writel_relaxed(BIT(31), reg_base + CK_INTC_ICR); + writel(BIT(31), reg_base + CK_INTC_ICR); ck_set_gc(node, reg_base, CK_INTC_NEN31_00, 0); ck_set_gc(node, reg_base, CK_INTC_NEN63_32, 32); @@ -260,8 +267,8 @@ ck_dual_intc_init(struct device_node *node, struct device_node *parent) return ret; /* Initial enable reg to disable all interrupts */ - writel_relaxed(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE); - writel_relaxed(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE); + writel(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE); + writel(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE); ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN31_00, 64); ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN63_32, 96); diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index db20e992a40f..c3aba3fc818d 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -97,9 +97,14 @@ struct its_device; * The ITS structure - contains most of the infrastructure, with the * top-level MSI domain, the command queue, the collections, and the * list of devices writing to it. + * + * dev_alloc_lock has to be taken for device allocations, while the + * spinlock must be taken to parse data structures such as the device + * list. */ struct its_node { raw_spinlock_t lock; + struct mutex dev_alloc_lock; struct list_head entry; void __iomem *base; phys_addr_t phys_base; @@ -156,6 +161,7 @@ struct its_device { void *itt; u32 nr_ites; u32 device_id; + bool shared; }; static struct { @@ -1580,6 +1586,9 @@ static unsigned long *its_lpi_alloc(int nr_irqs, u32 *base, int *nr_ids) nr_irqs /= 2; } while (nr_irqs > 0); + if (!nr_irqs) + err = -ENOSPC; + if (err) goto out; @@ -2059,6 +2068,29 @@ static int __init allocate_lpi_tables(void) return 0; } +static u64 its_clear_vpend_valid(void __iomem *vlpi_base) +{ + u32 count = 1000000; /* 1s! */ + bool clean; + u64 val; + + val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER); + val &= ~GICR_VPENDBASER_Valid; + gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER); + + do { + val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER); + clean = !(val & GICR_VPENDBASER_Dirty); + if (!clean) { + count--; + cpu_relax(); + udelay(1); + } + } while (!clean && count); + + return val; +} + static void its_cpu_init_lpis(void) { void __iomem *rbase = gic_data_rdist_rd_base(); @@ -2144,6 +2176,30 @@ static void its_cpu_init_lpis(void) val |= GICR_CTLR_ENABLE_LPIS; writel_relaxed(val, rbase + GICR_CTLR); + if (gic_rdists->has_vlpis) { + void __iomem *vlpi_base = gic_data_rdist_vlpi_base(); + + /* + * It's possible for CPU to receive VLPIs before it is + * sheduled as a vPE, especially for the first CPU, and the + * VLPI with INTID larger than 2^(IDbits+1) will be considered + * as out of range and dropped by GIC. + * So we initialize IDbits to known value to avoid VLPI drop. + */ + val = (LPI_NRBITS - 1) & GICR_VPROPBASER_IDBITS_MASK; + pr_debug("GICv4: CPU%d: Init IDbits to 0x%llx for GICR_VPROPBASER\n", + smp_processor_id(), val); + gits_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER); + + /* + * Also clear Valid bit of GICR_VPENDBASER, in case some + * ancient programming gets left in and has possibility of + * corrupting memory. + */ + val = its_clear_vpend_valid(vlpi_base); + WARN_ON(val & GICR_VPENDBASER_Dirty); + } + /* Make sure the GIC has seen the above */ dsb(sy); out: @@ -2399,13 +2455,14 @@ static void its_free_device(struct its_device *its_dev) kfree(its_dev); } -static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq) +static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number_t *hwirq) { int idx; - idx = find_first_zero_bit(dev->event_map.lpi_map, - dev->event_map.nr_lpis); - if (idx == dev->event_map.nr_lpis) + idx = bitmap_find_free_region(dev->event_map.lpi_map, + dev->event_map.nr_lpis, + get_count_order(nvecs)); + if (idx < 0) return -ENOSPC; *hwirq = dev->event_map.lpi_base + idx; @@ -2421,6 +2478,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev, struct its_device *its_dev; struct msi_domain_info *msi_info; u32 dev_id; + int err = 0; /* * We ignore "dev" entierely, and rely on the dev_id that has @@ -2443,6 +2501,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev, return -EINVAL; } + mutex_lock(&its->dev_alloc_lock); its_dev = its_find_device(its, dev_id); if (its_dev) { /* @@ -2450,18 +2509,22 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev, * another alias (PCI bridge of some sort). No need to * create the device. */ + its_dev->shared = true; pr_debug("Reusing ITT for devID %x\n", dev_id); goto out; } its_dev = its_create_device(its, dev_id, nvec, true); - if (!its_dev) - return -ENOMEM; + if (!its_dev) { + err = -ENOMEM; + goto out; + } pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec)); out: + mutex_unlock(&its->dev_alloc_lock); info->scratchpad[0].ptr = its_dev; - return 0; + return err; } static struct msi_domain_ops its_msi_domain_ops = { @@ -2501,21 +2564,21 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, int err; int i; - for (i = 0; i < nr_irqs; i++) { - err = its_alloc_device_irq(its_dev, &hwirq); - if (err) - return err; + err = its_alloc_device_irq(its_dev, nr_irqs, &hwirq); + if (err) + return err; - err = its_irq_gic_domain_alloc(domain, virq + i, hwirq); + for (i = 0; i < nr_irqs; i++) { + err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i); if (err) return err; irq_domain_set_hwirq_and_chip(domain, virq + i, - hwirq, &its_irq_chip, its_dev); + hwirq + i, &its_irq_chip, its_dev); irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i))); pr_debug("ID:%d pID:%d vID:%d\n", - (int)(hwirq - its_dev->event_map.lpi_base), - (int) hwirq, virq + i); + (int)(hwirq + i - its_dev->event_map.lpi_base), + (int)(hwirq + i), virq + i); } return 0; @@ -2565,6 +2628,7 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq, { struct irq_data *d = irq_domain_get_irq_data(domain, virq); struct its_device *its_dev = irq_data_get_irq_chip_data(d); + struct its_node *its = its_dev->its; int i; for (i = 0; i < nr_irqs; i++) { @@ -2579,8 +2643,14 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq, irq_domain_reset_irq_data(data); } - /* If all interrupts have been freed, start mopping the floor */ - if (bitmap_empty(its_dev->event_map.lpi_map, + mutex_lock(&its->dev_alloc_lock); + + /* + * If all interrupts have been freed, start mopping the + * floor. This is conditionned on the device not being shared. + */ + if (!its_dev->shared && + bitmap_empty(its_dev->event_map.lpi_map, its_dev->event_map.nr_lpis)) { its_lpi_free(its_dev->event_map.lpi_map, its_dev->event_map.lpi_base, @@ -2592,6 +2662,8 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq, its_free_device(its_dev); } + mutex_unlock(&its->dev_alloc_lock); + irq_domain_free_irqs_parent(domain, virq, nr_irqs); } @@ -2754,26 +2826,11 @@ static void its_vpe_schedule(struct its_vpe *vpe) static void its_vpe_deschedule(struct its_vpe *vpe) { void __iomem *vlpi_base = gic_data_rdist_vlpi_base(); - u32 count = 1000000; /* 1s! */ - bool clean; u64 val; - /* We're being scheduled out */ - val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER); - val &= ~GICR_VPENDBASER_Valid; - gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER); - - do { - val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER); - clean = !(val & GICR_VPENDBASER_Dirty); - if (!clean) { - count--; - cpu_relax(); - udelay(1); - } - } while (!clean && count); + val = its_clear_vpend_valid(vlpi_base); - if (unlikely(!clean && !count)) { + if (unlikely(val & GICR_VPENDBASER_Dirty)) { pr_err_ratelimited("ITS virtual pending table not cleaning\n"); vpe->idai = false; vpe->pending_last = true; @@ -3516,6 +3573,7 @@ static int __init its_probe_one(struct resource *res, } raw_spin_lock_init(&its->lock); + mutex_init(&its->dev_alloc_lock); INIT_LIST_HEAD(&its->entry); INIT_LIST_HEAD(&its->its_device_list); typer = gic_read_typer(its_base + GITS_TYPER); diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mbi.c index ad70e7c416e3..fbfa7ff6deb1 100644 --- a/drivers/irqchip/irq-gic-v3-mbi.c +++ b/drivers/irqchip/irq-gic-v3-mbi.c @@ -24,7 +24,7 @@ struct mbi_range { unsigned long *bm; }; -static struct mutex mbi_lock; +static DEFINE_MUTEX(mbi_lock); static phys_addr_t mbi_phys_base; static struct mbi_range *mbi_ranges; static unsigned int mbi_range_nr; diff --git a/drivers/irqchip/irq-madera.c b/drivers/irqchip/irq-madera.c index e9256dee1a45..8b81271c823c 100644 --- a/drivers/irqchip/irq-madera.c +++ b/drivers/irqchip/irq-madera.c @@ -7,7 +7,6 @@ */ #include <linux/module.h> -#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/irqdomain.h> @@ -16,7 +15,6 @@ #include <linux/slab.h> #include <linux/of.h> #include <linux/of_device.h> -#include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/irqchip/irq-madera.h> #include <linux/mfd/madera/core.h> diff --git a/drivers/irqchip/irq-mmp.c b/drivers/irqchip/irq-mmp.c index 25f32e1d7764..3496b61a312a 100644 --- a/drivers/irqchip/irq-mmp.c +++ b/drivers/irqchip/irq-mmp.c @@ -34,6 +34,9 @@ #define SEL_INT_PENDING (1 << 6) #define SEL_INT_NUM_MASK 0x3f +#define MMP2_ICU_INT_ROUTE_PJ4_IRQ (1 << 5) +#define MMP2_ICU_INT_ROUTE_PJ4_FIQ (1 << 6) + struct icu_chip_data { int nr_irqs; unsigned int virq_base; @@ -190,7 +193,8 @@ static const struct mmp_intc_conf mmp_conf = { static const struct mmp_intc_conf mmp2_conf = { .conf_enable = 0x20, .conf_disable = 0x0, - .conf_mask = 0x7f, + .conf_mask = MMP2_ICU_INT_ROUTE_PJ4_IRQ | + MMP2_ICU_INT_ROUTE_PJ4_FIQ, }; static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs) diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c index 6edfd4bfa169..a93296b9b45d 100644 --- a/drivers/irqchip/irq-stm32-exti.c +++ b/drivers/irqchip/irq-stm32-exti.c @@ -822,6 +822,7 @@ out_unmap: static const struct irq_domain_ops stm32_exti_h_domain_ops = { .alloc = stm32_exti_h_domain_alloc, .free = irq_domain_free_irqs_common, + .xlate = irq_domain_xlate_twocell, }; static int diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c index 5385f5768345..27933338f7b3 100644 --- a/drivers/irqchip/irq-xtensa-mx.c +++ b/drivers/irqchip/irq-xtensa-mx.c @@ -71,14 +71,17 @@ static void xtensa_mx_irq_mask(struct irq_data *d) unsigned int mask = 1u << d->hwirq; if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE | - XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) { - set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) - - HW_IRQ_MX_BASE), MIENG); - } else { - mask = __this_cpu_read(cached_irq_mask) & ~mask; - __this_cpu_write(cached_irq_mask, mask); - xtensa_set_sr(mask, intenable); + XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) { + unsigned int ext_irq = xtensa_get_ext_irq_no(d->hwirq); + + if (ext_irq >= HW_IRQ_MX_BASE) { + set_er(1u << (ext_irq - HW_IRQ_MX_BASE), MIENG); + return; + } } + mask = __this_cpu_read(cached_irq_mask) & ~mask; + __this_cpu_write(cached_irq_mask, mask); + xtensa_set_sr(mask, intenable); } static void xtensa_mx_irq_unmask(struct irq_data *d) @@ -86,14 +89,17 @@ static void xtensa_mx_irq_unmask(struct irq_data *d) unsigned int mask = 1u << d->hwirq; if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE | - XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) { - set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) - - HW_IRQ_MX_BASE), MIENGSET); - } else { - mask |= __this_cpu_read(cached_irq_mask); - __this_cpu_write(cached_irq_mask, mask); - xtensa_set_sr(mask, intenable); + XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) { + unsigned int ext_irq = xtensa_get_ext_irq_no(d->hwirq); + + if (ext_irq >= HW_IRQ_MX_BASE) { + set_er(1u << (ext_irq - HW_IRQ_MX_BASE), MIENGSET); + return; + } } + mask |= __this_cpu_read(cached_irq_mask); + __this_cpu_write(cached_irq_mask, mask); + xtensa_set_sr(mask, intenable); } static void xtensa_mx_irq_enable(struct irq_data *d) @@ -113,7 +119,11 @@ static void xtensa_mx_irq_ack(struct irq_data *d) static int xtensa_mx_irq_retrigger(struct irq_data *d) { - xtensa_set_sr(1 << d->hwirq, intset); + unsigned int mask = 1u << d->hwirq; + + if (WARN_ON(mask & ~XCHAL_INTTYPE_MASK_SOFTWARE)) + return 0; + xtensa_set_sr(mask, intset); return 1; } diff --git a/drivers/irqchip/irq-xtensa-pic.c b/drivers/irqchip/irq-xtensa-pic.c index c200234dd2c9..ab12328be5ee 100644 --- a/drivers/irqchip/irq-xtensa-pic.c +++ b/drivers/irqchip/irq-xtensa-pic.c @@ -70,7 +70,11 @@ static void xtensa_irq_ack(struct irq_data *d) static int xtensa_irq_retrigger(struct irq_data *d) { - xtensa_set_sr(1 << d->hwirq, intset); + unsigned int mask = 1u << d->hwirq; + + if (WARN_ON(mask & ~XCHAL_INTTYPE_MASK_SOFTWARE)) + return 0; + xtensa_set_sr(mask, intset); return 1; } diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c index 4ac378e48902..40ca1e8fa09f 100644 --- a/drivers/isdn/hardware/avm/b1.c +++ b/drivers/isdn/hardware/avm/b1.c @@ -423,7 +423,7 @@ void b1_parse_version(avmctrl_info *cinfo) int i, j; for (j = 0; j < AVM_MAXVERSION; j++) - cinfo->version[j] = "\0\0" + 1; + cinfo->version[j] = ""; for (i = 0, j = 0; j < AVM_MAXVERSION && i < cinfo->versionlen; j++, i += cinfo->versionbuf[i] + 1) diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index 6d05946b445e..124ff530da82 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c @@ -262,8 +262,7 @@ hfcsusb_ph_info(struct hfcsusb *hw) struct dchannel *dch = &hw->dch; int i; - phi = kzalloc(sizeof(struct ph_info) + - dch->dev.nrbchan * sizeof(struct ph_info_ch), GFP_ATOMIC); + phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC); phi->dch.ch.protocol = hw->protocol; phi->dch.ch.Flags = dch->Flags; phi->dch.state = dch->state; diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 1b2239c1d569..dc1cded716c1 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1437,15 +1437,19 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { modem_info *info = (modem_info *) tty->driver_data; + mutex_lock(&modem_info_mutex); if (!old_termios) isdn_tty_change_speed(info); else { if (tty->termios.c_cflag == old_termios->c_cflag && tty->termios.c_ispeed == old_termios->c_ispeed && - tty->termios.c_ospeed == old_termios->c_ospeed) + tty->termios.c_ospeed == old_termios->c_ospeed) { + mutex_unlock(&modem_info_mutex); return; + } isdn_tty_change_speed(info); } + mutex_unlock(&modem_info_mutex); } /* diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c index 211ed6cffd10..578978711887 100644 --- a/drivers/isdn/mISDN/timerdev.c +++ b/drivers/isdn/mISDN/timerdev.c @@ -170,8 +170,8 @@ dev_expire_timer(struct timer_list *t) spin_lock_irqsave(&timer->dev->lock, flags); if (timer->id >= 0) list_move_tail(&timer->list, &timer->dev->expired); - spin_unlock_irqrestore(&timer->dev->lock, flags); wake_up_interruptible(&timer->dev->wait); + spin_unlock_irqrestore(&timer->dev->lock, flags); } static int diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index a2e74feee2b2..fd64df5a57a5 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -318,7 +318,9 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip) /* Let the programs run for couple of ms and check the engine status */ usleep_range(3000, 6000); - lp55xx_read(chip, LP5523_REG_STATUS, &status); + ret = lp55xx_read(chip, LP5523_REG_STATUS, &status); + if (ret) + return ret; status &= LP5523_ENG_STATUS_MASK; if (status != LP5523_ENG_STATUS_MASK) { diff --git a/drivers/mailbox/bcm-flexrm-mailbox.c b/drivers/mailbox/bcm-flexrm-mailbox.c index d713271ebf7c..a64116586b4c 100644 --- a/drivers/mailbox/bcm-flexrm-mailbox.c +++ b/drivers/mailbox/bcm-flexrm-mailbox.c @@ -1396,9 +1396,9 @@ static void flexrm_shutdown(struct mbox_chan *chan) /* Clear ring flush state */ timeout = 1000; /* timeout of 1s */ - writel_relaxed(0x0, ring + RING_CONTROL); + writel_relaxed(0x0, ring->regs + RING_CONTROL); do { - if (!(readl_relaxed(ring + RING_FLUSH_DONE) & + if (!(readl_relaxed(ring->regs + RING_FLUSH_DONE) & FLUSH_DONE_MASK)) break; mdelay(1); diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c index c6a7d4582dc6..38d9df3fb199 100644 --- a/drivers/mailbox/mailbox.c +++ b/drivers/mailbox/mailbox.c @@ -310,6 +310,7 @@ int mbox_flush(struct mbox_chan *chan, unsigned long timeout) return ret; } +EXPORT_SYMBOL_GPL(mbox_flush); /** * mbox_request_channel - Request a mailbox channel. diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 0ff22159a0ca..dd538e6b2748 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -932,7 +932,7 @@ static int dm_crypt_integrity_io_alloc(struct dm_crypt_io *io, struct bio *bio) if (IS_ERR(bip)) return PTR_ERR(bip); - tag_len = io->cc->on_disk_tag_size * bio_sectors(bio); + tag_len = io->cc->on_disk_tag_size * (bio_sectors(bio) >> io->cc->sector_shift); bip->bip_iter.bi_size = tag_len; bip->bip_iter.bi_sector = io->cc->start + io->sector; @@ -2414,9 +2414,21 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key * capi:cipher_api_spec-iv:ivopts */ tmp = &cipher_in[strlen("capi:")]; - cipher_api = strsep(&tmp, "-"); - *ivmode = strsep(&tmp, ":"); - *ivopts = tmp; + + /* Separate IV options if present, it can contain another '-' in hash name */ + *ivopts = strrchr(tmp, ':'); + if (*ivopts) { + **ivopts = '\0'; + (*ivopts)++; + } + /* Parse IV mode */ + *ivmode = strrchr(tmp, '-'); + if (*ivmode) { + **ivmode = '\0'; + (*ivmode)++; + } + /* The rest is crypto API spec */ + cipher_api = tmp; if (*ivmode && !strcmp(*ivmode, "lmk")) cc->tfms_count = 64; @@ -2486,11 +2498,8 @@ static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key goto bad_mem; chainmode = strsep(&tmp, "-"); - *ivopts = strsep(&tmp, "-"); - *ivmode = strsep(&*ivopts, ":"); - - if (tmp) - DMWARN("Ignoring unexpected additional cipher options"); + *ivmode = strsep(&tmp, ":"); + *ivopts = tmp; /* * For compatibility with the original dm-crypt mapping format, if diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 4eb5f8c56535..a20531e5f3b4 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -131,7 +131,7 @@ static void rq_end_stats(struct mapped_device *md, struct request *orig) static void rq_completed(struct mapped_device *md) { /* nudge anyone waiting on suspend queue */ - if (unlikely(waitqueue_active(&md->wait))) + if (unlikely(wq_has_sleeper(&md->wait))) wake_up(&md->wait); /* diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 20b0776e39ef..ed3caceaed07 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -1678,7 +1678,7 @@ int dm_thin_remove_range(struct dm_thin_device *td, return r; } -int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result) +int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result) { int r; uint32_t ref_count; @@ -1686,7 +1686,7 @@ int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *resu down_read(&pmd->root_lock); r = dm_sm_get_count(pmd->data_sm, b, &ref_count); if (!r) - *result = (ref_count != 0); + *result = (ref_count > 1); up_read(&pmd->root_lock); return r; diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h index 35e954ea20a9..f6be0d733c20 100644 --- a/drivers/md/dm-thin-metadata.h +++ b/drivers/md/dm-thin-metadata.h @@ -195,7 +195,7 @@ int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd, int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result); -int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result); +int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result); int dm_pool_inc_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e); int dm_pool_dec_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e); diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index dadd9696340c..e83b63608262 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -257,6 +257,7 @@ struct pool { spinlock_t lock; struct bio_list deferred_flush_bios; + struct bio_list deferred_flush_completions; struct list_head prepared_mappings; struct list_head prepared_discards; struct list_head prepared_discards_pt2; @@ -956,6 +957,39 @@ static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m) mempool_free(m, &m->tc->pool->mapping_pool); } +static void complete_overwrite_bio(struct thin_c *tc, struct bio *bio) +{ + struct pool *pool = tc->pool; + unsigned long flags; + + /* + * If the bio has the REQ_FUA flag set we must commit the metadata + * before signaling its completion. + */ + if (!bio_triggers_commit(tc, bio)) { + bio_endio(bio); + return; + } + + /* + * Complete bio with an error if earlier I/O caused changes to the + * metadata that can't be committed, e.g, due to I/O errors on the + * metadata device. + */ + if (dm_thin_aborted_changes(tc->td)) { + bio_io_error(bio); + return; + } + + /* + * Batch together any bios that trigger commits and then issue a + * single commit for them in process_deferred_bios(). + */ + spin_lock_irqsave(&pool->lock, flags); + bio_list_add(&pool->deferred_flush_completions, bio); + spin_unlock_irqrestore(&pool->lock, flags); +} + static void process_prepared_mapping(struct dm_thin_new_mapping *m) { struct thin_c *tc = m->tc; @@ -988,7 +1022,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m) */ if (bio) { inc_remap_and_issue_cell(tc, m->cell, m->data_block); - bio_endio(bio); + complete_overwrite_bio(tc, bio); } else { inc_all_io_entry(tc->pool, m->cell->holder); remap_and_issue(tc, m->cell->holder, m->data_block); @@ -1048,7 +1082,7 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m * passdown we have to check that these blocks are now unused. */ int r = 0; - bool used = true; + bool shared = true; struct thin_c *tc = m->tc; struct pool *pool = tc->pool; dm_block_t b = m->data_block, e, end = m->data_block + m->virt_end - m->virt_begin; @@ -1058,11 +1092,11 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m while (b != end) { /* find start of unmapped run */ for (; b < end; b++) { - r = dm_pool_block_is_used(pool->pmd, b, &used); + r = dm_pool_block_is_shared(pool->pmd, b, &shared); if (r) goto out; - if (!used) + if (!shared) break; } @@ -1071,11 +1105,11 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m /* find end of run */ for (e = b + 1; e != end; e++) { - r = dm_pool_block_is_used(pool->pmd, e, &used); + r = dm_pool_block_is_shared(pool->pmd, e, &shared); if (r) goto out; - if (used) + if (shared) break; } @@ -2317,7 +2351,7 @@ static void process_deferred_bios(struct pool *pool) { unsigned long flags; struct bio *bio; - struct bio_list bios; + struct bio_list bios, bio_completions; struct thin_c *tc; tc = get_first_thin(pool); @@ -2328,26 +2362,36 @@ static void process_deferred_bios(struct pool *pool) } /* - * If there are any deferred flush bios, we must commit - * the metadata before issuing them. + * If there are any deferred flush bios, we must commit the metadata + * before issuing them or signaling their completion. */ bio_list_init(&bios); + bio_list_init(&bio_completions); + spin_lock_irqsave(&pool->lock, flags); bio_list_merge(&bios, &pool->deferred_flush_bios); bio_list_init(&pool->deferred_flush_bios); + + bio_list_merge(&bio_completions, &pool->deferred_flush_completions); + bio_list_init(&pool->deferred_flush_completions); spin_unlock_irqrestore(&pool->lock, flags); - if (bio_list_empty(&bios) && + if (bio_list_empty(&bios) && bio_list_empty(&bio_completions) && !(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool))) return; if (commit(pool)) { + bio_list_merge(&bios, &bio_completions); + while ((bio = bio_list_pop(&bios))) bio_io_error(bio); return; } pool->last_commit_jiffies = jiffies; + while ((bio = bio_list_pop(&bio_completions))) + bio_endio(bio); + while ((bio = bio_list_pop(&bios))) generic_make_request(bio); } @@ -2954,6 +2998,7 @@ static struct pool *pool_create(struct mapped_device *pool_md, INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout); spin_lock_init(&pool->lock); bio_list_init(&pool->deferred_flush_bios); + bio_list_init(&pool->deferred_flush_completions); INIT_LIST_HEAD(&pool->prepared_mappings); INIT_LIST_HEAD(&pool->prepared_discards); INIT_LIST_HEAD(&pool->prepared_discards_pt2); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d67c95ef8d7e..515e6af9bed2 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -699,7 +699,7 @@ static void end_io_acct(struct dm_io *io) true, duration, &io->stats_aux); /* nudge anyone waiting on suspend queue */ - if (unlikely(waitqueue_active(&md->wait))) + if (unlikely(wq_has_sleeper(&md->wait))) wake_up(&md->wait); } @@ -1320,7 +1320,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio, __bio_clone_fast(clone, bio); - if (unlikely(bio_integrity(bio) != NULL)) { + if (bio_integrity(bio)) { int r; if (unlikely(!dm_target_has_integrity(tio->ti->type) && @@ -1339,7 +1339,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio, bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector)); clone->bi_iter.bi_size = to_bytes(len); - if (unlikely(bio_integrity(bio) != NULL)) + if (bio_integrity(bio)) bio_integrity_trim(clone); return 0; @@ -1588,6 +1588,9 @@ static void init_clone_info(struct clone_info *ci, struct mapped_device *md, ci->sector = bio->bi_iter.bi_sector; } +#define __dm_part_stat_sub(part, field, subnd) \ + (part_stat_get(part, field) -= (subnd)) + /* * Entry point to split a bio into clones and submit them to the targets. */ @@ -1642,7 +1645,21 @@ static blk_qc_t __split_and_process_bio(struct mapped_device *md, struct bio *b = bio_split(bio, bio_sectors(bio) - ci.sector_count, GFP_NOIO, &md->queue->bio_split); ci.io->orig_bio = b; + + /* + * Adjust IO stats for each split, otherwise upon queue + * reentry there will be redundant IO accounting. + * NOTE: this is a stop-gap fix, a proper fix involves + * significant refactoring of DM core's bio splitting + * (by eliminating DM's splitting and just using bio_split) + */ + part_stat_lock(); + __dm_part_stat_sub(&dm_disk(md)->part0, + sectors[op_stat_group(bio_op(bio))], ci.sector_count); + part_stat_unlock(); + bio_chain(b, bio); + trace_block_split(md->queue, b, bio->bi_iter.bi_sector); ret = generic_make_request(bio); break; } @@ -1713,6 +1730,15 @@ out: return ret; } +static blk_qc_t dm_process_bio(struct mapped_device *md, + struct dm_table *map, struct bio *bio) +{ + if (dm_get_md_type(md) == DM_TYPE_NVME_BIO_BASED) + return __process_bio(md, map, bio); + else + return __split_and_process_bio(md, map, bio); +} + static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio) { struct mapped_device *md = q->queuedata; @@ -1733,10 +1759,7 @@ static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio) return ret; } - if (dm_get_md_type(md) == DM_TYPE_NVME_BIO_BASED) - ret = __process_bio(md, map, bio); - else - ret = __split_and_process_bio(md, map, bio); + ret = dm_process_bio(md, map, bio); dm_put_live_table(md, srcu_idx); return ret; @@ -2415,9 +2438,9 @@ static void dm_wq_work(struct work_struct *work) break; if (dm_request_based(md)) - generic_make_request(c); + (void) generic_make_request(c); else - __split_and_process_bio(md, map, c); + (void) dm_process_bio(md, map, c); } dm_put_live_table(md, srcu_idx); diff --git a/drivers/md/md.c b/drivers/md/md.c index fd4af4de03b4..05ffffb8b769 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -207,15 +207,10 @@ static bool create_on_open = true; struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs, struct mddev *mddev) { - struct bio *b; - if (!mddev || !bioset_initialized(&mddev->bio_set)) return bio_alloc(gfp_mask, nr_iovecs); - b = bio_alloc_bioset(gfp_mask, nr_iovecs, &mddev->bio_set); - if (!b) - return NULL; - return b; + return bio_alloc_bioset(gfp_mask, nr_iovecs, &mddev->bio_set); } EXPORT_SYMBOL_GPL(bio_alloc_mddev); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 1d54109071cc..fa47249fa3e4 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1863,6 +1863,20 @@ static void end_sync_read(struct bio *bio) reschedule_retry(r1_bio); } +static void abort_sync_write(struct mddev *mddev, struct r1bio *r1_bio) +{ + sector_t sync_blocks = 0; + sector_t s = r1_bio->sector; + long sectors_to_go = r1_bio->sectors; + + /* make sure these bits don't get cleared. */ + do { + md_bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1); + s += sync_blocks; + sectors_to_go -= sync_blocks; + } while (sectors_to_go > 0); +} + static void end_sync_write(struct bio *bio) { int uptodate = !bio->bi_status; @@ -1874,15 +1888,7 @@ static void end_sync_write(struct bio *bio) struct md_rdev *rdev = conf->mirrors[find_bio_disk(r1_bio, bio)].rdev; if (!uptodate) { - sector_t sync_blocks = 0; - sector_t s = r1_bio->sector; - long sectors_to_go = r1_bio->sectors; - /* make sure these bits doesn't get cleared. */ - do { - md_bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1); - s += sync_blocks; - sectors_to_go -= sync_blocks; - } while (sectors_to_go > 0); + abort_sync_write(mddev, r1_bio); set_bit(WriteErrorSeen, &rdev->flags); if (!test_and_set_bit(WantReplacement, &rdev->flags)) set_bit(MD_RECOVERY_NEEDED, & @@ -2172,8 +2178,10 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio) (i == r1_bio->read_disk || !test_bit(MD_RECOVERY_SYNC, &mddev->recovery)))) continue; - if (test_bit(Faulty, &conf->mirrors[i].rdev->flags)) + if (test_bit(Faulty, &conf->mirrors[i].rdev->flags)) { + abort_sync_write(mddev, r1_bio); continue; + } bio_set_op_attrs(wbio, REQ_OP_WRITE, 0); if (test_bit(FailFast, &conf->mirrors[i].rdev->flags)) diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index ec3a5ef7fee0..cbbe6b6535be 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c @@ -1935,12 +1935,14 @@ out: } static struct stripe_head * -r5c_recovery_alloc_stripe(struct r5conf *conf, - sector_t stripe_sect) +r5c_recovery_alloc_stripe( + struct r5conf *conf, + sector_t stripe_sect, + int noblock) { struct stripe_head *sh; - sh = raid5_get_active_stripe(conf, stripe_sect, 0, 1, 0); + sh = raid5_get_active_stripe(conf, stripe_sect, 0, noblock, 0); if (!sh) return NULL; /* no more stripe available */ @@ -2150,7 +2152,7 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log, stripe_sect); if (!sh) { - sh = r5c_recovery_alloc_stripe(conf, stripe_sect); + sh = r5c_recovery_alloc_stripe(conf, stripe_sect, 1); /* * cannot get stripe from raid5_get_active_stripe * try replay some stripes @@ -2159,20 +2161,29 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log, r5c_recovery_replay_stripes( cached_stripe_list, ctx); sh = r5c_recovery_alloc_stripe( - conf, stripe_sect); + conf, stripe_sect, 1); } if (!sh) { + int new_size = conf->min_nr_stripes * 2; pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n", mdname(mddev), - conf->min_nr_stripes * 2); - raid5_set_cache_size(mddev, - conf->min_nr_stripes * 2); - sh = r5c_recovery_alloc_stripe(conf, - stripe_sect); + new_size); + ret = raid5_set_cache_size(mddev, new_size); + if (conf->min_nr_stripes <= new_size / 2) { + pr_err("md/raid:%s: Cannot increase cache size, ret=%d, new_size=%d, min_nr_stripes=%d, max_nr_stripes=%d\n", + mdname(mddev), + ret, + new_size, + conf->min_nr_stripes, + conf->max_nr_stripes); + return -ENOMEM; + } + sh = r5c_recovery_alloc_stripe( + conf, stripe_sect, 0); } if (!sh) { pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n", - mdname(mddev)); + mdname(mddev)); return -ENOMEM; } list_add_tail(&sh->lru, cached_stripe_list); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 4990f0319f6c..cecea901ab8c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -6369,6 +6369,7 @@ raid5_show_stripe_cache_size(struct mddev *mddev, char *page) int raid5_set_cache_size(struct mddev *mddev, int size) { + int result = 0; struct r5conf *conf = mddev->private; if (size <= 16 || size > 32768) @@ -6385,11 +6386,14 @@ raid5_set_cache_size(struct mddev *mddev, int size) mutex_lock(&conf->cache_size_mutex); while (size > conf->max_nr_stripes) - if (!grow_one_stripe(conf, GFP_KERNEL)) + if (!grow_one_stripe(conf, GFP_KERNEL)) { + conf->min_nr_stripes = conf->max_nr_stripes; + result = -ENOMEM; break; + } mutex_unlock(&conf->cache_size_mutex); - return 0; + return result; } EXPORT_SYMBOL(raid5_set_cache_size); diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 447baaebca44..cdb79ae2d8dc 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -218,8 +218,8 @@ static int cio2_fbpt_init(struct cio2_device *cio2, struct cio2_queue *q) { struct device *dev = &cio2->pci_dev->dev; - q->fbpt = dma_zalloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr, - GFP_KERNEL); + q->fbpt = dma_alloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr, + GFP_KERNEL); if (!q->fbpt) return -ENOMEM; diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c index e80123cba406..060c0ad6243a 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c @@ -49,7 +49,7 @@ int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data, struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)data; struct device *dev = &ctx->dev->plat_dev->dev; - mem->va = dma_zalloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL); + mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL); if (!mem->va) { mtk_v4l2_err("%s dma_alloc size=%ld failed!", dev_name(dev), size); diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index d01821a6906a..89d9c4c21037 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -807,7 +807,9 @@ static void vim2m_stop_streaming(struct vb2_queue *q) struct vb2_v4l2_buffer *vbuf; unsigned long flags; - cancel_delayed_work_sync(&dev->work_run); + if (v4l2_m2m_get_curr_priv(dev->m2m_dev) == ctx) + cancel_delayed_work_sync(&dev->work_run); + for (;;) { if (V4L2_TYPE_IS_OUTPUT(q->type)) vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 1441a73ce64c..90aad465f9ed 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -287,6 +287,7 @@ static void v4l_print_format(const void *arg, bool write_only) const struct v4l2_window *win; const struct v4l2_sdr_format *sdr; const struct v4l2_meta_format *meta; + u32 planes; unsigned i; pr_cont("type=%s", prt_names(p->type, v4l2_type_names)); @@ -317,7 +318,8 @@ static void v4l_print_format(const void *arg, bool write_only) prt_names(mp->field, v4l2_field_names), mp->colorspace, mp->num_planes, mp->flags, mp->ycbcr_enc, mp->quantization, mp->xfer_func); - for (i = 0; i < mp->num_planes; i++) + planes = min_t(u32, mp->num_planes, VIDEO_MAX_PLANES); + for (i = 0; i < planes; i++) printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i, mp->plane_fmt[i].bytesperline, mp->plane_fmt[i].sizeimage); @@ -1551,8 +1553,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!ops->vidioc_s_fmt_vid_cap_mplane)) break; CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); + if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) + break; for (i = 0; i < p->fmt.pix_mp.num_planes; i++) - CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline); + CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], + bytesperline); return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OVERLAY: if (unlikely(!ops->vidioc_s_fmt_vid_overlay)) @@ -1581,8 +1586,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!ops->vidioc_s_fmt_vid_out_mplane)) break; CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); + if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) + break; for (i = 0; i < p->fmt.pix_mp.num_planes; i++) - CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline); + CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], + bytesperline); return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay)) @@ -1648,8 +1656,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane)) break; CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); + if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) + break; for (i = 0; i < p->fmt.pix_mp.num_planes; i++) - CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline); + CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], + bytesperline); return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OVERLAY: if (unlikely(!ops->vidioc_try_fmt_vid_overlay)) @@ -1678,8 +1689,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!ops->vidioc_try_fmt_vid_out_mplane)) break; CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); + if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) + break; for (i = 0; i < p->fmt.pix_mp.num_planes; i++) - CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline); + CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], + bytesperline); return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay)) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 8c5dfdce4326..76f9909cf396 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -102,6 +102,7 @@ config MFD_AAT2870_CORE config MFD_AT91_USART tristate "AT91 USART Driver" select MFD_CORE + depends on ARCH_AT91 || COMPILE_TEST help Select this to get support for AT91 USART IP. This is a wrapper over at91-usart-serial driver and usart-spi-driver. Only one function @@ -1418,7 +1419,7 @@ config MFD_TPS65217 config MFD_TPS68470 bool "TI TPS68470 Power Management / LED chips" - depends on ACPI && I2C=y + depends on ACPI && PCI && I2C=y select MFD_CORE select REGMAP_I2C select I2C_DESIGNWARE_PLATFORM diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 30d09d177171..11ab17f64c64 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -261,7 +261,7 @@ static int get_register_interruptible(struct ab8500 *ab8500, u8 bank, mutex_unlock(&ab8500->lock); dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); - return ret; + return (ret < 0) ? ret : 0; } static int ab8500_get_register(struct device *dev, u8 bank, diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index e1450a56fc07..3c97f2c0fdfe 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -641,9 +641,9 @@ static const struct mfd_cell axp221_cells[] = { static const struct mfd_cell axp223_cells[] = { { - .name = "axp221-pek", - .num_resources = ARRAY_SIZE(axp22x_pek_resources), - .resources = axp22x_pek_resources, + .name = "axp221-pek", + .num_resources = ARRAY_SIZE(axp22x_pek_resources), + .resources = axp22x_pek_resources, }, { .name = "axp22x-adc", .of_compatible = "x-powers,axp221-adc", @@ -651,7 +651,7 @@ static const struct mfd_cell axp223_cells[] = { .name = "axp20x-battery-power-supply", .of_compatible = "x-powers,axp221-battery-power-supply", }, { - .name = "axp20x-regulator", + .name = "axp20x-regulator", }, { .name = "axp20x-ac-power-supply", .of_compatible = "x-powers,axp221-ac-power-supply", @@ -667,9 +667,9 @@ static const struct mfd_cell axp223_cells[] = { static const struct mfd_cell axp152_cells[] = { { - .name = "axp20x-pek", - .num_resources = ARRAY_SIZE(axp152_pek_resources), - .resources = axp152_pek_resources, + .name = "axp20x-pek", + .num_resources = ARRAY_SIZE(axp152_pek_resources), + .resources = axp152_pek_resources, }, }; @@ -698,87 +698,101 @@ static const struct resource axp288_charger_resources[] = { static const struct mfd_cell axp288_cells[] = { { - .name = "axp288_adc", - .num_resources = ARRAY_SIZE(axp288_adc_resources), - .resources = axp288_adc_resources, - }, - { - .name = "axp288_extcon", - .num_resources = ARRAY_SIZE(axp288_extcon_resources), - .resources = axp288_extcon_resources, - }, - { - .name = "axp288_charger", - .num_resources = ARRAY_SIZE(axp288_charger_resources), - .resources = axp288_charger_resources, - }, - { - .name = "axp288_fuel_gauge", - .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources), - .resources = axp288_fuel_gauge_resources, - }, - { - .name = "axp221-pek", - .num_resources = ARRAY_SIZE(axp288_power_button_resources), - .resources = axp288_power_button_resources, - }, - { - .name = "axp288_pmic_acpi", + .name = "axp288_adc", + .num_resources = ARRAY_SIZE(axp288_adc_resources), + .resources = axp288_adc_resources, + }, { + .name = "axp288_extcon", + .num_resources = ARRAY_SIZE(axp288_extcon_resources), + .resources = axp288_extcon_resources, + }, { + .name = "axp288_charger", + .num_resources = ARRAY_SIZE(axp288_charger_resources), + .resources = axp288_charger_resources, + }, { + .name = "axp288_fuel_gauge", + .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources), + .resources = axp288_fuel_gauge_resources, + }, { + .name = "axp221-pek", + .num_resources = ARRAY_SIZE(axp288_power_button_resources), + .resources = axp288_power_button_resources, + }, { + .name = "axp288_pmic_acpi", }, }; static const struct mfd_cell axp803_cells[] = { { - .name = "axp221-pek", - .num_resources = ARRAY_SIZE(axp803_pek_resources), - .resources = axp803_pek_resources, + .name = "axp221-pek", + .num_resources = ARRAY_SIZE(axp803_pek_resources), + .resources = axp803_pek_resources, + }, { + .name = "axp20x-gpio", + .of_compatible = "x-powers,axp813-gpio", + }, { + .name = "axp813-adc", + .of_compatible = "x-powers,axp813-adc", + }, { + .name = "axp20x-battery-power-supply", + .of_compatible = "x-powers,axp813-battery-power-supply", + }, { + .name = "axp20x-ac-power-supply", + .of_compatible = "x-powers,axp813-ac-power-supply", + .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), + .resources = axp20x_ac_power_supply_resources, }, - { .name = "axp20x-regulator" }, + { .name = "axp20x-regulator" }, }; static const struct mfd_cell axp806_self_working_cells[] = { { - .name = "axp221-pek", - .num_resources = ARRAY_SIZE(axp806_pek_resources), - .resources = axp806_pek_resources, + .name = "axp221-pek", + .num_resources = ARRAY_SIZE(axp806_pek_resources), + .resources = axp806_pek_resources, }, - { .name = "axp20x-regulator" }, + { .name = "axp20x-regulator" }, }; static const struct mfd_cell axp806_cells[] = { { - .id = 2, - .name = "axp20x-regulator", + .id = 2, + .name = "axp20x-regulator", }, }; static const struct mfd_cell axp809_cells[] = { { - .name = "axp221-pek", - .num_resources = ARRAY_SIZE(axp809_pek_resources), - .resources = axp809_pek_resources, + .name = "axp221-pek", + .num_resources = ARRAY_SIZE(axp809_pek_resources), + .resources = axp809_pek_resources, }, { - .id = 1, - .name = "axp20x-regulator", + .id = 1, + .name = "axp20x-regulator", }, }; static const struct mfd_cell axp813_cells[] = { { - .name = "axp221-pek", - .num_resources = ARRAY_SIZE(axp803_pek_resources), - .resources = axp803_pek_resources, + .name = "axp221-pek", + .num_resources = ARRAY_SIZE(axp803_pek_resources), + .resources = axp803_pek_resources, }, { - .name = "axp20x-regulator", + .name = "axp20x-regulator", }, { - .name = "axp20x-gpio", - .of_compatible = "x-powers,axp813-gpio", + .name = "axp20x-gpio", + .of_compatible = "x-powers,axp813-gpio", }, { - .name = "axp813-adc", - .of_compatible = "x-powers,axp813-adc", + .name = "axp813-adc", + .of_compatible = "x-powers,axp813-adc", }, { .name = "axp20x-battery-power-supply", .of_compatible = "x-powers,axp813-battery-power-supply", + }, { + .name = "axp20x-ac-power-supply", + .of_compatible = "x-powers,axp813-ac-power-supply", + .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), + .resources = axp20x_ac_power_supply_resources, }, }; diff --git a/drivers/mfd/bd9571mwv.c b/drivers/mfd/bd9571mwv.c index 503979c81dae..fab3cdc27ed6 100644 --- a/drivers/mfd/bd9571mwv.c +++ b/drivers/mfd/bd9571mwv.c @@ -59,6 +59,7 @@ static const struct regmap_access_table bd9571mwv_writable_table = { }; static const struct regmap_range bd9571mwv_volatile_yes_ranges[] = { + regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC), regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN), regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT), regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ), diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index b99a194ce5a4..2d0fee488c5a 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -499,6 +499,7 @@ static int ec_device_remove(struct platform_device *pdev) cros_ec_debugfs_remove(ec); + mfd_remove_devices(ec->dev); cdev_del(&ec->cdev); device_unregister(&ec->class_dev); return 0; diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 5970b8def548..aec20e1c7d3d 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -2584,7 +2584,7 @@ static struct irq_chip prcmu_irq_chip = { .irq_unmask = prcmu_irq_unmask, }; -static __init char *fw_project_name(u32 project) +static char *fw_project_name(u32 project) { switch (project) { case PRCMU_FW_PROJECT_U8500: @@ -2732,7 +2732,7 @@ void __init db8500_prcmu_early_init(u32 phy_base, u32 size) INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work); } -static void __init init_prcm_registers(void) +static void init_prcm_registers(void) { u32 val; diff --git a/drivers/mfd/exynos-lpass.c b/drivers/mfd/exynos-lpass.c index ca829f85672f..2713de989f05 100644 --- a/drivers/mfd/exynos-lpass.c +++ b/drivers/mfd/exynos-lpass.c @@ -82,11 +82,13 @@ static void exynos_lpass_enable(struct exynos_lpass *lpass) LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S); regmap_write(lpass->top, SFR_LPASS_INTR_CPU_MASK, - LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S); + LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S | + LPASS_INTR_UART); exynos_lpass_core_sw_reset(lpass, LPASS_I2S_SW_RESET); exynos_lpass_core_sw_reset(lpass, LPASS_DMA_SW_RESET); exynos_lpass_core_sw_reset(lpass, LPASS_MEM_SW_RESET); + exynos_lpass_core_sw_reset(lpass, LPASS_UART_SW_RESET); } static void exynos_lpass_disable(struct exynos_lpass *lpass) diff --git a/drivers/mfd/madera-core.c b/drivers/mfd/madera-core.c index 440030cecbbd..2a77988d0462 100644 --- a/drivers/mfd/madera-core.c +++ b/drivers/mfd/madera-core.c @@ -15,6 +15,7 @@ #include <linux/gpio.h> #include <linux/mfd/core.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/notifier.h> #include <linux/of.h> #include <linux/of_gpio.h> @@ -155,7 +156,7 @@ static int madera_wait_for_boot(struct madera *madera) usleep_range(MADERA_BOOT_POLL_INTERVAL_USEC / 2, MADERA_BOOT_POLL_INTERVAL_USEC); regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val); - }; + } if (!(val & MADERA_BOOT_DONE_STS1)) { dev_err(madera->dev, "Polling BOOT_DONE_STS timed out\n"); @@ -357,6 +358,8 @@ int madera_dev_init(struct madera *madera) dev_set_drvdata(madera->dev, madera); BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier); + mutex_init(&madera->dapm_ptr_lock); + madera_set_micbias_info(madera); /* diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index d8217366ed36..d8ddd1a6f304 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c @@ -280,7 +280,7 @@ static int max77620_config_fps(struct max77620_chip *chip, for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) { sprintf(fps_name, "fps%d", fps_id); - if (!strcmp(fps_np->name, fps_name)) + if (of_node_name_eq(fps_np, fps_name)) break; } diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index f475e848252f..d0bf50e3568d 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c @@ -274,7 +274,9 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode, mc13xxx->adcflags |= MC13XXX_ADC_WORKING; - mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0); + ret = mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0); + if (ret) + goto out; adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2 | MC13XXX_ADC0_CHRGRAWDIV; diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index 77b64bd64df3..ab24e176ef44 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -329,8 +329,7 @@ static int mt6397_probe(struct platform_device *pdev) default: dev_err(&pdev->dev, "unsupported chip: %d\n", id); - ret = -ENODEV; - break; + return -ENODEV; } if (ret) { diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c index 52fafea06067..8d420c37b2a6 100644 --- a/drivers/mfd/qcom_rpm.c +++ b/drivers/mfd/qcom_rpm.c @@ -638,6 +638,10 @@ static int qcom_rpm_probe(struct platform_device *pdev) return -EFAULT; } + writel(fw_version[0], RPM_CTRL_REG(rpm, 0)); + writel(fw_version[1], RPM_CTRL_REG(rpm, 1)); + writel(fw_version[2], RPM_CTRL_REG(rpm, 2)); + dev_info(&pdev->dev, "RPM firmware %u.%u.%u\n", fw_version[0], fw_version[1], fw_version[2]); diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c index 2a8369657e38..26c7b63e008a 100644 --- a/drivers/mfd/rave-sp.c +++ b/drivers/mfd/rave-sp.c @@ -109,7 +109,7 @@ struct rave_sp_reply { /** * struct rave_sp_checksum - Variant specific checksum implementation details * - * @length: Caculated checksum length + * @length: Calculated checksum length * @subroutine: Utilized checksum algorithm implementation */ struct rave_sp_checksum { diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 566caca4efd8..7569a4be0608 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -1302,17 +1302,17 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata, pdata->autosleep = (pdata->autosleep_timeout) ? true : false; for_each_child_of_node(np, child) { - if (!strcmp(child->name, "stmpe_gpio")) { + if (of_node_name_eq(child, "stmpe_gpio")) { pdata->blocks |= STMPE_BLOCK_GPIO; - } else if (!strcmp(child->name, "stmpe_keypad")) { + } else if (of_node_name_eq(child, "stmpe_keypad")) { pdata->blocks |= STMPE_BLOCK_KEYPAD; - } else if (!strcmp(child->name, "stmpe_touchscreen")) { + } else if (of_node_name_eq(child, "stmpe_touchscreen")) { pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN; - } else if (!strcmp(child->name, "stmpe_adc")) { + } else if (of_node_name_eq(child, "stmpe_adc")) { pdata->blocks |= STMPE_BLOCK_ADC; - } else if (!strcmp(child->name, "stmpe_pwm")) { + } else if (of_node_name_eq(child, "stmpe_pwm")) { pdata->blocks |= STMPE_BLOCK_PWM; - } else if (!strcmp(child->name, "stmpe_rotator")) { + } else if (of_node_name_eq(child, "stmpe_rotator")) { pdata->blocks |= STMPE_BLOCK_ROTATOR; } } diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index c2d47d78705b..fd111296b959 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -264,8 +264,9 @@ static int ti_tscadc_probe(struct platform_device *pdev) cell->pdata_size = sizeof(tscadc); } - err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells, - tscadc->used_cells, NULL, 0, NULL); + err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, + tscadc->cells, tscadc->used_cells, NULL, + 0, NULL); if (err < 0) goto err_disable_clk; diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c index 910f569ff77c..8bcdecf494d0 100644 --- a/drivers/mfd/tps65218.c +++ b/drivers/mfd/tps65218.c @@ -235,9 +235,9 @@ static int tps65218_probe(struct i2c_client *client, mutex_init(&tps->tps_lock); - ret = regmap_add_irq_chip(tps->regmap, tps->irq, - IRQF_ONESHOT, 0, &tps65218_irq_chip, - &tps->irq_data); + ret = devm_regmap_add_irq_chip(&client->dev, tps->regmap, tps->irq, + IRQF_ONESHOT, 0, &tps65218_irq_chip, + &tps->irq_data); if (ret < 0) return ret; @@ -253,26 +253,9 @@ static int tps65218_probe(struct i2c_client *client, ARRAY_SIZE(tps65218_cells), NULL, 0, regmap_irq_get_domain(tps->irq_data)); - if (ret < 0) - goto err_irq; - - return 0; - -err_irq: - regmap_del_irq_chip(tps->irq, tps->irq_data); - return ret; } -static int tps65218_remove(struct i2c_client *client) -{ - struct tps65218 *tps = i2c_get_clientdata(client); - - regmap_del_irq_chip(tps->irq, tps->irq_data); - - return 0; -} - static const struct i2c_device_id tps65218_id_table[] = { { "tps65218", TPS65218 }, { }, @@ -285,7 +268,6 @@ static struct i2c_driver tps65218_driver = { .of_match_table = of_tps65218_match_table, }, .probe = tps65218_probe, - .remove = tps65218_remove, .id_table = tps65218_id_table, }; diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index b89379782741..9c7925ca13cf 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -592,6 +592,29 @@ static int tps6586x_i2c_remove(struct i2c_client *client) return 0; } +static int __maybe_unused tps6586x_i2c_suspend(struct device *dev) +{ + struct tps6586x *tps6586x = dev_get_drvdata(dev); + + if (tps6586x->client->irq) + disable_irq(tps6586x->client->irq); + + return 0; +} + +static int __maybe_unused tps6586x_i2c_resume(struct device *dev) +{ + struct tps6586x *tps6586x = dev_get_drvdata(dev); + + if (tps6586x->client->irq) + enable_irq(tps6586x->client->irq); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_i2c_suspend, + tps6586x_i2c_resume); + static const struct i2c_device_id tps6586x_id_table[] = { { "tps6586x", 0 }, { }, @@ -602,6 +625,7 @@ static struct i2c_driver tps6586x_driver = { .driver = { .name = "tps6586x", .of_match_table = of_match_ptr(tps6586x_of_match), + .pm = &tps6586x_pm_ops, }, .probe = tps6586x_i2c_probe, .remove = tps6586x_i2c_remove, diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 4be3d239da9e..299016bc46d9 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -979,7 +979,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, * letting it generate the right frequencies for USB, MADC, and * other purposes. */ -static inline int __init protect_pm_master(void) +static inline int protect_pm_master(void) { int e = 0; @@ -988,7 +988,7 @@ static inline int __init protect_pm_master(void) return e; } -static inline int __init unprotect_pm_master(void) +static inline int unprotect_pm_master(void) { int e = 0; diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 1ee68bd440fb..16c6e2accfaa 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -1618,6 +1618,7 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00000ECD, 0x0000 }, /* R3789 - HPLPF4_2 */ { 0x00000EE0, 0x0000 }, /* R3808 - ASRC_ENABLE */ { 0x00000EE2, 0x0000 }, /* R3810 - ASRC_RATE1 */ + { 0x00000EE3, 0x4000 }, /* R3811 - ASRC_RATE2 */ { 0x00000EF0, 0x0000 }, /* R3824 - ISRC 1 CTRL 1 */ { 0x00000EF1, 0x0000 }, /* R3825 - ISRC 1 CTRL 2 */ { 0x00000EF2, 0x0000 }, /* R3826 - ISRC 1 CTRL 3 */ @@ -2869,6 +2870,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_ASRC_ENABLE: case ARIZONA_ASRC_STATUS: case ARIZONA_ASRC_RATE1: + case ARIZONA_ASRC_RATE2: case ARIZONA_ISRC_1_CTRL_1: case ARIZONA_ISRC_1_CTRL_2: case ARIZONA_ISRC_1_CTRL_3: diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c index efe2fb72d54b..25265fd0fd6e 100644 --- a/drivers/misc/genwqe/card_utils.c +++ b/drivers/misc/genwqe/card_utils.c @@ -218,8 +218,8 @@ void *__genwqe_alloc_consistent(struct genwqe_dev *cd, size_t size, if (get_order(size) >= MAX_ORDER) return NULL; - return dma_zalloc_coherent(&cd->pci_dev->dev, size, dma_handle, - GFP_KERNEL); + return dma_alloc_coherent(&cd->pci_dev->dev, size, dma_handle, + GFP_KERNEL); } void __genwqe_free_consistent(struct genwqe_dev *cd, size_t size, diff --git a/drivers/misc/ibmvmc.c b/drivers/misc/ibmvmc.c index b8aaa684c397..2ed23c99f59f 100644 --- a/drivers/misc/ibmvmc.c +++ b/drivers/misc/ibmvmc.c @@ -820,21 +820,24 @@ static int ibmvmc_send_msg(struct crq_server_adapter *adapter, * * Return: * 0 - Success + * Non-zero - Failure */ static int ibmvmc_open(struct inode *inode, struct file *file) { struct ibmvmc_file_session *session; - int rc = 0; pr_debug("%s: inode = 0x%lx, file = 0x%lx, state = 0x%x\n", __func__, (unsigned long)inode, (unsigned long)file, ibmvmc.state); session = kzalloc(sizeof(*session), GFP_KERNEL); + if (!session) + return -ENOMEM; + session->file = file; file->private_data = session; - return rc; + return 0; } /** diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 1fc8ea0f519b..ca4c9cc218a2 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -401,8 +401,11 @@ static void mei_io_list_flush_cl(struct list_head *head, struct mei_cl_cb *cb, *next; list_for_each_entry_safe(cb, next, head, list) { - if (cl == cb->cl) + if (cl == cb->cl) { list_del_init(&cb->list); + if (cb->fop_type == MEI_FOP_READ) + mei_io_cb_free(cb); + } } } diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 78c26cebf5d4..8f7616557c97 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -1187,9 +1187,15 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) dma_setup_res = (struct hbm_dma_setup_response *)mei_msg; if (dma_setup_res->status) { - dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n", - dma_setup_res->status, - mei_hbm_status_str(dma_setup_res->status)); + u8 status = dma_setup_res->status; + + if (status == MEI_HBMS_NOT_ALLOWED) { + dev_dbg(dev->dev, "hbm: dma setup not allowed\n"); + } else { + dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n", + status, + mei_hbm_status_str(status)); + } dev->hbm_f_dr_supported = 0; mei_dmam_ring_free(dev); } diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index e4b10b2d1a08..bb1ee9834a02 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -127,6 +127,8 @@ #define MEI_DEV_ID_BXT_M 0x1A9A /* Broxton M */ #define MEI_DEV_ID_APL_I 0x5A9A /* Apollo Lake I */ +#define MEI_DEV_ID_DNV_IE 0x19E5 /* Denverton IE */ + #define MEI_DEV_ID_GLK 0x319A /* Gemini Lake */ #define MEI_DEV_ID_KBP 0xA2BA /* Kaby Point */ @@ -137,6 +139,8 @@ #define MEI_DEV_ID_CNP_H 0xA360 /* Cannon Point H */ #define MEI_DEV_ID_CNP_H_4 0xA364 /* Cannon Point H 4 (iTouch) */ +#define MEI_DEV_ID_ICP_LP 0x34E0 /* Ice Lake Point LP */ + /* * MEI HW Section */ diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 73ace2d59dea..3ab946ad3257 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -88,11 +88,13 @@ static const struct pci_device_id mei_me_pci_tbl[] = { {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_DNV_IE, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_GLK, MEI_ME_PCH8_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)}, @@ -103,6 +105,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = { {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH12_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H_4, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)}, + /* required last entry */ {0, } }; diff --git a/drivers/misc/mic/vop/vop_main.c b/drivers/misc/mic/vop/vop_main.c index 6b212c8b78e7..744757f541be 100644 --- a/drivers/misc/mic/vop/vop_main.c +++ b/drivers/misc/mic/vop/vop_main.c @@ -47,7 +47,8 @@ * @dc: Virtio device control * @vpdev: VOP device which is the parent for this virtio device * @vr: Buffer for accessing the VRING - * @used: Buffer for used + * @used_virt: Virtual address of used ring + * @used: DMA address of used ring * @used_size: Size of the used buffer * @reset_done: Track whether VOP reset is complete * @virtio_cookie: Cookie returned upon requesting a interrupt @@ -61,6 +62,7 @@ struct _vop_vdev { struct mic_device_ctrl __iomem *dc; struct vop_device *vpdev; void __iomem *vr[VOP_MAX_VRINGS]; + void *used_virt[VOP_MAX_VRINGS]; dma_addr_t used[VOP_MAX_VRINGS]; int used_size[VOP_MAX_VRINGS]; struct completion reset_done; @@ -260,12 +262,12 @@ static bool vop_notify(struct virtqueue *vq) static void vop_del_vq(struct virtqueue *vq, int n) { struct _vop_vdev *vdev = to_vopvdev(vq->vdev); - struct vring *vr = (struct vring *)(vq + 1); struct vop_device *vpdev = vdev->vpdev; dma_unmap_single(&vpdev->dev, vdev->used[n], vdev->used_size[n], DMA_BIDIRECTIONAL); - free_pages((unsigned long)vr->used, get_order(vdev->used_size[n])); + free_pages((unsigned long)vdev->used_virt[n], + get_order(vdev->used_size[n])); vring_del_virtqueue(vq); vpdev->hw_ops->iounmap(vpdev, vdev->vr[n]); vdev->vr[n] = NULL; @@ -283,6 +285,26 @@ static void vop_del_vqs(struct virtio_device *dev) vop_del_vq(vq, idx++); } +static struct virtqueue *vop_new_virtqueue(unsigned int index, + unsigned int num, + struct virtio_device *vdev, + bool context, + void *pages, + bool (*notify)(struct virtqueue *vq), + void (*callback)(struct virtqueue *vq), + const char *name, + void *used) +{ + bool weak_barriers = false; + struct vring vring; + + vring_init(&vring, num, pages, MIC_VIRTIO_RING_ALIGN); + vring.used = used; + + return __vring_new_virtqueue(index, vring, vdev, weak_barriers, context, + notify, callback, name); +} + /* * This routine will assign vring's allocated in host/io memory. Code in * virtio_ring.c however continues to access this io memory as if it were local @@ -302,7 +324,6 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev, struct _mic_vring_info __iomem *info; void *used; int vr_size, _vr_size, err, magic; - struct vring *vr; u8 type = ioread8(&vdev->desc->type); if (index >= ioread8(&vdev->desc->num_vq)) @@ -322,17 +343,7 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev, return ERR_PTR(-ENOMEM); vdev->vr[index] = va; memset_io(va, 0x0, _vr_size); - vq = vring_new_virtqueue( - index, - le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN, - dev, - false, - ctx, - (void __force *)va, vop_notify, callback, name); - if (!vq) { - err = -ENOMEM; - goto unmap; - } + info = va + _vr_size; magic = ioread32(&info->magic); @@ -341,18 +352,27 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev, goto unmap; } - /* Allocate and reassign used ring now */ vdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * le16_to_cpu(config.num)); used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(vdev->used_size[index])); + vdev->used_virt[index] = used; if (!used) { err = -ENOMEM; dev_err(_vop_dev(vdev), "%s %d err %d\n", __func__, __LINE__, err); - goto del_vq; + goto unmap; } + + vq = vop_new_virtqueue(index, le16_to_cpu(config.num), dev, ctx, + (void __force *)va, vop_notify, callback, + name, used); + if (!vq) { + err = -ENOMEM; + goto free_used; + } + vdev->used[index] = dma_map_single(&vpdev->dev, used, vdev->used_size[index], DMA_BIDIRECTIONAL); @@ -360,26 +380,17 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev, err = -ENOMEM; dev_err(_vop_dev(vdev), "%s %d err %d\n", __func__, __LINE__, err); - goto free_used; + goto del_vq; } writeq(vdev->used[index], &vqconfig->used_address); - /* - * To reassign the used ring here we are directly accessing - * struct vring_virtqueue which is a private data structure - * in virtio_ring.c. At the minimum, a BUILD_BUG_ON() in - * vring_new_virtqueue() would ensure that - * (&vq->vring == (struct vring *) (&vq->vq + 1)); - */ - vr = (struct vring *)(vq + 1); - vr->used = used; vq->priv = vdev; return vq; +del_vq: + vring_del_virtqueue(vq); free_used: free_pages((unsigned long)used, get_order(vdev->used_size[index])); -del_vq: - vring_del_virtqueue(vq); unmap: vpdev->hw_ops->iounmap(vpdev, vdev->vr[index]); return ERR_PTR(err); @@ -394,16 +405,21 @@ static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs, struct _vop_vdev *vdev = to_vopvdev(dev); struct vop_device *vpdev = vdev->vpdev; struct mic_device_ctrl __iomem *dc = vdev->dc; - int i, err, retry; + int i, err, retry, queue_idx = 0; /* We must have this many virtqueues. */ if (nvqs > ioread8(&vdev->desc->num_vq)) return -ENOENT; for (i = 0; i < nvqs; ++i) { + if (!names[i]) { + vqs[i] = NULL; + continue; + } + dev_dbg(_vop_dev(vdev), "%s: %d: %s\n", __func__, i, names[i]); - vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i], + vqs[i] = vop_find_vq(dev, queue_idx++, callbacks[i], names[i], ctx ? ctx[i] : false); if (IS_ERR(vqs[i])) { err = PTR_ERR(vqs[i]); @@ -576,6 +592,8 @@ static int _vop_remove_device(struct mic_device_desc __iomem *d, int ret = -1; if (ioread8(&dc->config_change) == MIC_VIRTIO_PARAM_DEV_REMOVE) { + struct device *dev = get_device(&vdev->vdev.dev); + dev_dbg(&vpdev->dev, "%s %d config_change %d type %d vdev %p\n", __func__, __LINE__, @@ -587,7 +605,7 @@ static int _vop_remove_device(struct mic_device_desc __iomem *d, iowrite8(-1, &dc->h2c_vdev_db); if (status & VIRTIO_CONFIG_S_DRIVER_OK) wait_for_completion(&vdev->reset_done); - put_device(&vdev->vdev.dev); + put_device(dev); iowrite8(1, &dc->guest_ack); dev_dbg(&vpdev->dev, "%s %d guest_ack %d\n", __func__, __LINE__, ioread8(&dc->guest_ack)); diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c index 595ac065b401..95ff7c5a1dfb 100644 --- a/drivers/misc/pvpanic.c +++ b/drivers/misc/pvpanic.c @@ -70,8 +70,12 @@ pvpanic_walk_resources(struct acpi_resource *res, void *context) struct resource r; if (acpi_dev_resource_io(res, &r)) { +#ifdef CONFIG_HAS_IOPORT_MAP base = ioport_map(r.start, resource_size(&r)); return AE_OK; +#else + return AE_ERROR; +#endif } else if (acpi_dev_resource_memory(res, &r)) { base = ioremap(r.start, resource_size(&r)); return AE_OK; diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index abba078f7f49..95ffe008ebdf 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile @@ -8,7 +8,7 @@ mmc_core-y := core.o bus.o host.o \ mmc.o mmc_ops.o sd.o sd_ops.o \ sdio.o sdio_ops.o sdio_bus.o \ sdio_cis.o sdio_io.o sdio_irq.o \ - slot-gpio.o + slot-gpio.o regulator.o mmc_core-$(CONFIG_OF) += pwrseq.o obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o obj-$(CONFIG_PWRSEQ_SD8787) += pwrseq_sd8787.o diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index aef1185f383d..2c71a434c915 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1124,7 +1124,7 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) { struct mmc_blk_data *md = mq->blkdata; struct mmc_card *card = md->queue.card; - unsigned int from, nr, arg; + unsigned int from, nr; int err = 0, type = MMC_BLK_DISCARD; blk_status_t status = BLK_STS_OK; @@ -1136,24 +1136,18 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) from = blk_rq_pos(req); nr = blk_rq_sectors(req); - if (mmc_can_discard(card)) - arg = MMC_DISCARD_ARG; - else if (mmc_can_trim(card)) - arg = MMC_TRIM_ARG; - else - arg = MMC_ERASE_ARG; do { err = 0; if (card->quirks & MMC_QUIRK_INAND_CMD38) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, INAND_CMD38_ARG_EXT_CSD, - arg == MMC_TRIM_ARG ? + card->erase_arg == MMC_TRIM_ARG ? INAND_CMD38_ARG_TRIM : INAND_CMD38_ARG_ERASE, 0); } if (!err) - err = mmc_erase(card, from, nr, arg); + err = mmc_erase(card, from, nr, card->erase_arg); } while (err == -EIO && !mmc_blk_reset(md, card->host, type)); if (err) status = BLK_STS_IOERR; @@ -2112,7 +2106,7 @@ static void mmc_blk_mq_req_done(struct mmc_request *mrq) if (waiting) wake_up(&mq->wait); else - kblockd_schedule_work(&mq->complete_work); + queue_work(mq->card->complete_wq, &mq->complete_work); return; } @@ -2380,12 +2374,6 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, snprintf(md->disk->disk_name, sizeof(md->disk->disk_name), "mmcblk%u%s", card->host->index, subname ? subname : ""); - if (mmc_card_mmc(card)) - blk_queue_logical_block_size(md->queue.queue, - card->ext_csd.data_sector_size); - else - blk_queue_logical_block_size(md->queue.queue, 512); - set_capacity(md->disk, size); if (mmc_host_cmd23(card->host)) { @@ -2774,8 +2762,8 @@ static int mmc_dbg_card_status_get(void *data, u64 *val) return ret; } -DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, - NULL, "%08llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, + NULL, "%08llx\n"); /* That is two digits * 512 + 1 for newline */ #define EXT_CSD_STR_LEN 1025 @@ -2863,8 +2851,9 @@ static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md) if (mmc_card_mmc(card) || mmc_card_sd(card)) { md->status_dentry = - debugfs_create_file("status", S_IRUSR, root, card, - &mmc_dbg_card_status_fops); + debugfs_create_file_unsafe("status", 0400, root, + card, + &mmc_dbg_card_status_fops); if (!md->status_dentry) return -EIO; } @@ -2924,6 +2913,13 @@ static int mmc_blk_probe(struct mmc_card *card) mmc_fixup_device(card, mmc_blk_fixups); + card->complete_wq = alloc_workqueue("mmc_complete", + WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); + if (unlikely(!card->complete_wq)) { + pr_err("Failed to create mmc completion workqueue"); + return -ENOMEM; + } + md = mmc_blk_alloc(card); if (IS_ERR(md)) return PTR_ERR(md); @@ -2987,6 +2983,7 @@ static void mmc_blk_remove(struct mmc_card *card) pm_runtime_put_noidle(&card->dev); mmc_blk_remove_req(md); dev_set_drvdata(&card->dev, NULL); + destroy_workqueue(card->complete_wq); } static int _mmc_blk_suspend(struct mmc_card *card) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 5bd58b95d318..6db36dc870b5 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -21,7 +21,6 @@ #include <linux/leds.h> #include <linux/scatterlist.h> #include <linux/log2.h> -#include <linux/regulator/consumer.h> #include <linux/pm_runtime.h> #include <linux/pm_wakeup.h> #include <linux/suspend.h> @@ -52,6 +51,7 @@ /* The max erase timeout, used when host->max_busy_timeout isn't specified */ #define MMC_ERASE_TIMEOUT_MS (60 * 1000) /* 60 s */ +#define SD_DISCARD_TIMEOUT_MS (250) static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; @@ -95,7 +95,7 @@ static void mmc_should_fail_request(struct mmc_host *host, if (!data) return; - if (cmd->error || data->error || + if ((cmd && cmd->error) || data->error || !should_fail(&host->fail_mmc_request, data->blksz * data->blocks)) return; @@ -758,33 +758,6 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) } EXPORT_SYMBOL(mmc_set_data_timeout); -/** - * mmc_align_data_size - pads a transfer size to a more optimal value - * @card: the MMC card associated with the data transfer - * @sz: original transfer size - * - * Pads the original data size with a number of extra bytes in - * order to avoid controller bugs and/or performance hits - * (e.g. some controllers revert to PIO for certain sizes). - * - * Returns the improved size, which might be unmodified. - * - * Note that this function is only relevant when issuing a - * single scatter gather entry. - */ -unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz) -{ - /* - * FIXME: We don't have a system for the controller to tell - * the core about its problems yet, so for now we just 32-bit - * align the size. - */ - sz = ((sz + 3) / 4) * 4; - - return sz; -} -EXPORT_SYMBOL(mmc_align_data_size); - /* * Allow claiming an already claimed host if the context is the same or there is * no context but the task is the same. @@ -1112,55 +1085,6 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max) return mask; } -EXPORT_SYMBOL(mmc_vddrange_to_ocrmask); - -#ifdef CONFIG_OF - -/** - * mmc_of_parse_voltage - return mask of supported voltages - * @np: The device node need to be parsed. - * @mask: mask of voltages available for MMC/SD/SDIO - * - * Parse the "voltage-ranges" DT property, returning zero if it is not - * found, negative errno if the voltage-range specification is invalid, - * or one if the voltage-range is specified and successfully parsed. - */ -int mmc_of_parse_voltage(struct device_node *np, u32 *mask) -{ - const u32 *voltage_ranges; - int num_ranges, i; - - voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges); - num_ranges = num_ranges / sizeof(*voltage_ranges) / 2; - if (!voltage_ranges) { - pr_debug("%pOF: voltage-ranges unspecified\n", np); - return 0; - } - if (!num_ranges) { - pr_err("%pOF: voltage-ranges empty\n", np); - return -EINVAL; - } - - for (i = 0; i < num_ranges; i++) { - const int j = i * 2; - u32 ocr_mask; - - ocr_mask = mmc_vddrange_to_ocrmask( - be32_to_cpu(voltage_ranges[j]), - be32_to_cpu(voltage_ranges[j + 1])); - if (!ocr_mask) { - pr_err("%pOF: voltage-range #%d is invalid\n", - np, i); - return -EINVAL; - } - *mask |= ocr_mask; - } - - return 1; -} -EXPORT_SYMBOL(mmc_of_parse_voltage); - -#endif /* CONFIG_OF */ static int mmc_of_get_func_num(struct device_node *node) { @@ -1190,246 +1114,6 @@ struct device_node *mmc_of_find_child_device(struct mmc_host *host, return NULL; } -#ifdef CONFIG_REGULATOR - -/** - * mmc_ocrbitnum_to_vdd - Convert a OCR bit number to its voltage - * @vdd_bit: OCR bit number - * @min_uV: minimum voltage value (mV) - * @max_uV: maximum voltage value (mV) - * - * This function returns the voltage range according to the provided OCR - * bit number. If conversion is not possible a negative errno value returned. - */ -static int mmc_ocrbitnum_to_vdd(int vdd_bit, int *min_uV, int *max_uV) -{ - int tmp; - - if (!vdd_bit) - return -EINVAL; - - /* - * REVISIT mmc_vddrange_to_ocrmask() may have set some - * bits this regulator doesn't quite support ... don't - * be too picky, most cards and regulators are OK with - * a 0.1V range goof (it's a small error percentage). - */ - tmp = vdd_bit - ilog2(MMC_VDD_165_195); - if (tmp == 0) { - *min_uV = 1650 * 1000; - *max_uV = 1950 * 1000; - } else { - *min_uV = 1900 * 1000 + tmp * 100 * 1000; - *max_uV = *min_uV + 100 * 1000; - } - - return 0; -} - -/** - * mmc_regulator_get_ocrmask - return mask of supported voltages - * @supply: regulator to use - * - * This returns either a negative errno, or a mask of voltages that - * can be provided to MMC/SD/SDIO devices using the specified voltage - * regulator. This would normally be called before registering the - * MMC host adapter. - */ -int mmc_regulator_get_ocrmask(struct regulator *supply) -{ - int result = 0; - int count; - int i; - int vdd_uV; - int vdd_mV; - - count = regulator_count_voltages(supply); - if (count < 0) - return count; - - for (i = 0; i < count; i++) { - vdd_uV = regulator_list_voltage(supply, i); - if (vdd_uV <= 0) - continue; - - vdd_mV = vdd_uV / 1000; - result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV); - } - - if (!result) { - vdd_uV = regulator_get_voltage(supply); - if (vdd_uV <= 0) - return vdd_uV; - - vdd_mV = vdd_uV / 1000; - result = mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV); - } - - return result; -} -EXPORT_SYMBOL_GPL(mmc_regulator_get_ocrmask); - -/** - * mmc_regulator_set_ocr - set regulator to match host->ios voltage - * @mmc: the host to regulate - * @supply: regulator to use - * @vdd_bit: zero for power off, else a bit number (host->ios.vdd) - * - * Returns zero on success, else negative errno. - * - * MMC host drivers may use this to enable or disable a regulator using - * a particular supply voltage. This would normally be called from the - * set_ios() method. - */ -int mmc_regulator_set_ocr(struct mmc_host *mmc, - struct regulator *supply, - unsigned short vdd_bit) -{ - int result = 0; - int min_uV, max_uV; - - if (vdd_bit) { - mmc_ocrbitnum_to_vdd(vdd_bit, &min_uV, &max_uV); - - result = regulator_set_voltage(supply, min_uV, max_uV); - if (result == 0 && !mmc->regulator_enabled) { - result = regulator_enable(supply); - if (!result) - mmc->regulator_enabled = true; - } - } else if (mmc->regulator_enabled) { - result = regulator_disable(supply); - if (result == 0) - mmc->regulator_enabled = false; - } - - if (result) - dev_err(mmc_dev(mmc), - "could not set regulator OCR (%d)\n", result); - return result; -} -EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr); - -static int mmc_regulator_set_voltage_if_supported(struct regulator *regulator, - int min_uV, int target_uV, - int max_uV) -{ - /* - * Check if supported first to avoid errors since we may try several - * signal levels during power up and don't want to show errors. - */ - if (!regulator_is_supported_voltage(regulator, min_uV, max_uV)) - return -EINVAL; - - return regulator_set_voltage_triplet(regulator, min_uV, target_uV, - max_uV); -} - -/** - * mmc_regulator_set_vqmmc - Set VQMMC as per the ios - * - * For 3.3V signaling, we try to match VQMMC to VMMC as closely as possible. - * That will match the behavior of old boards where VQMMC and VMMC were supplied - * by the same supply. The Bus Operating conditions for 3.3V signaling in the - * SD card spec also define VQMMC in terms of VMMC. - * If this is not possible we'll try the full 2.7-3.6V of the spec. - * - * For 1.2V and 1.8V signaling we'll try to get as close as possible to the - * requested voltage. This is definitely a good idea for UHS where there's a - * separate regulator on the card that's trying to make 1.8V and it's best if - * we match. - * - * This function is expected to be used by a controller's - * start_signal_voltage_switch() function. - */ -int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios) -{ - struct device *dev = mmc_dev(mmc); - int ret, volt, min_uV, max_uV; - - /* If no vqmmc supply then we can't change the voltage */ - if (IS_ERR(mmc->supply.vqmmc)) - return -EINVAL; - - switch (ios->signal_voltage) { - case MMC_SIGNAL_VOLTAGE_120: - return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, - 1100000, 1200000, 1300000); - case MMC_SIGNAL_VOLTAGE_180: - return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, - 1700000, 1800000, 1950000); - case MMC_SIGNAL_VOLTAGE_330: - ret = mmc_ocrbitnum_to_vdd(mmc->ios.vdd, &volt, &max_uV); - if (ret < 0) - return ret; - - dev_dbg(dev, "%s: found vmmc voltage range of %d-%duV\n", - __func__, volt, max_uV); - - min_uV = max(volt - 300000, 2700000); - max_uV = min(max_uV + 200000, 3600000); - - /* - * Due to a limitation in the current implementation of - * regulator_set_voltage_triplet() which is taking the lowest - * voltage possible if below the target, search for a suitable - * voltage in two steps and try to stay close to vmmc - * with a 0.3V tolerance at first. - */ - if (!mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, - min_uV, volt, max_uV)) - return 0; - - return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, - 2700000, volt, 3600000); - default: - return -EINVAL; - } -} -EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc); - -#endif /* CONFIG_REGULATOR */ - -/** - * mmc_regulator_get_supply - try to get VMMC and VQMMC regulators for a host - * @mmc: the host to regulate - * - * Returns 0 or errno. errno should be handled, it is either a critical error - * or -EPROBE_DEFER. 0 means no critical error but it does not mean all - * regulators have been found because they all are optional. If you require - * certain regulators, you need to check separately in your driver if they got - * populated after calling this function. - */ -int mmc_regulator_get_supply(struct mmc_host *mmc) -{ - struct device *dev = mmc_dev(mmc); - int ret; - - mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc"); - mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc"); - - if (IS_ERR(mmc->supply.vmmc)) { - if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER) - return -EPROBE_DEFER; - dev_dbg(dev, "No vmmc regulator found\n"); - } else { - ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc); - if (ret > 0) - mmc->ocr_avail = ret; - else - dev_warn(dev, "Failed getting OCR mask: %d\n", ret); - } - - if (IS_ERR(mmc->supply.vqmmc)) { - if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER) - return -EPROBE_DEFER; - dev_dbg(dev, "No vqmmc regulator found\n"); - } - - return 0; -} -EXPORT_SYMBOL_GPL(mmc_regulator_get_supply); - /* * Mask off any voltages we don't support and select * the lowest voltage @@ -1936,6 +1620,12 @@ static unsigned int mmc_sd_erase_timeout(struct mmc_card *card, { unsigned int erase_timeout; + /* for DISCARD none of the below calculation applies. + * the busy timeout is 250msec per discard command. + */ + if (arg == SD_DISCARD_ARG) + return SD_DISCARD_TIMEOUT_MS; + if (card->ssr.erase_timeout) { /* Erase timeout specified in SD Status Register (SSR) */ erase_timeout = card->ssr.erase_timeout * qty + @@ -2164,7 +1854,7 @@ static unsigned int mmc_align_erase_size(struct mmc_card *card, * @card: card to erase * @from: first sector to erase * @nr: number of sectors to erase - * @arg: erase command argument (SD supports only %MMC_ERASE_ARG) + * @arg: erase command argument * * Caller must claim host before calling this function. */ @@ -2181,14 +1871,14 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr, if (!card->erase_size) return -EOPNOTSUPP; - if (mmc_card_sd(card) && arg != MMC_ERASE_ARG) + if (mmc_card_sd(card) && arg != SD_ERASE_ARG && arg != SD_DISCARD_ARG) return -EOPNOTSUPP; - if ((arg & MMC_SECURE_ARGS) && + if (mmc_card_mmc(card) && (arg & MMC_SECURE_ARGS) && !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN)) return -EOPNOTSUPP; - if ((arg & MMC_TRIM_ARGS) && + if (mmc_card_mmc(card) && (arg & MMC_TRIM_ARGS) && !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN)) return -EOPNOTSUPP; @@ -2381,9 +2071,9 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) return card->pref_erase; max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG); - if (max_discard && mmc_can_trim(card)) { + if (mmc_can_trim(card)) { max_trim = mmc_do_calc_max_discard(card, MMC_TRIM_ARG); - if (max_trim < max_discard) + if (max_trim < max_discard || max_discard == 0) max_discard = max_trim; } else if (max_discard < card->erase_size) { max_discard = 0; diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 8fb6bc37f808..b5083b13d594 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -59,6 +59,7 @@ void mmc_power_up(struct mmc_host *host, u32 ocr); void mmc_power_off(struct mmc_host *host); void mmc_power_cycle(struct mmc_host *host, u32 ocr); void mmc_set_initial_state(struct mmc_host *host); +u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max); static inline void mmc_delay(unsigned int ms) { diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index f57f5de54206..3a4402a79904 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -194,7 +194,7 @@ int mmc_of_parse(struct mmc_host *host) switch (bus_width) { case 8: host->caps |= MMC_CAP_8_BIT_DATA; - /* Hosts capable of 8-bit transfers can also do 4 bits */ + /* fall through - Hosts capable of 8-bit can also do 4 bits */ case 4: host->caps |= MMC_CAP_4_BIT_DATA; break; @@ -234,7 +234,7 @@ int mmc_of_parse(struct mmc_host *host) if (device_property_read_bool(dev, "broken-cd")) host->caps |= MMC_CAP_NEEDS_POLL; - ret = mmc_gpiod_request_cd(host, "cd", 0, true, + ret = mmc_gpiod_request_cd(host, "cd", 0, false, cd_debounce_delay_ms * 1000, &cd_gpio_invert); if (!ret) @@ -260,7 +260,7 @@ int mmc_of_parse(struct mmc_host *host) /* Parse Write Protection */ ro_cap_invert = device_property_read_bool(dev, "wp-inverted"); - ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert); + ret = mmc_gpiod_request_ro(host, "wp", 0, 0, &ro_gpio_invert); if (!ret) dev_info(host->parent, "Got WP GPIO\n"); else if (ret != -ENOENT && ret != -ENOSYS) @@ -349,6 +349,50 @@ int mmc_of_parse(struct mmc_host *host) EXPORT_SYMBOL(mmc_of_parse); /** + * mmc_of_parse_voltage - return mask of supported voltages + * @np: The device node need to be parsed. + * @mask: mask of voltages available for MMC/SD/SDIO + * + * Parse the "voltage-ranges" DT property, returning zero if it is not + * found, negative errno if the voltage-range specification is invalid, + * or one if the voltage-range is specified and successfully parsed. + */ +int mmc_of_parse_voltage(struct device_node *np, u32 *mask) +{ + const u32 *voltage_ranges; + int num_ranges, i; + + voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges); + num_ranges = num_ranges / sizeof(*voltage_ranges) / 2; + if (!voltage_ranges) { + pr_debug("%pOF: voltage-ranges unspecified\n", np); + return 0; + } + if (!num_ranges) { + pr_err("%pOF: voltage-ranges empty\n", np); + return -EINVAL; + } + + for (i = 0; i < num_ranges; i++) { + const int j = i * 2; + u32 ocr_mask; + + ocr_mask = mmc_vddrange_to_ocrmask( + be32_to_cpu(voltage_ranges[j]), + be32_to_cpu(voltage_ranges[j + 1])); + if (!ocr_mask) { + pr_err("%pOF: voltage-range #%d is invalid\n", + np, i); + return -EINVAL; + } + *mask |= ocr_mask; + } + + return 1; +} +EXPORT_SYMBOL(mmc_of_parse_voltage); + +/** * mmc_alloc_host - initialise the per-host structure. * @extra: sizeof private data structure * @dev: pointer to host device model structure diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index da892a599524..3e786ba204c3 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1594,6 +1594,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, if (oldcard) { if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) { + pr_debug("%s: Perhaps the card was replaced\n", + mmc_hostname(host)); err = -ENOENT; goto err; } @@ -1743,6 +1745,14 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, card->ext_csd.power_off_notification = EXT_CSD_POWER_ON; } + /* set erase_arg */ + if (mmc_can_discard(card)) + card->erase_arg = MMC_DISCARD_ARG; + else if (mmc_can_trim(card)) + card->erase_arg = MMC_TRIM_ARG; + else + card->erase_arg = MMC_ERASE_ARG; + /* * Select timing interface */ diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 9054329fe903..c5208fb312ae 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -562,7 +562,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, if (index == EXT_CSD_SANITIZE_START) cmd.sanitize_busy = true; - err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); + err = mmc_wait_for_cmd(host, &cmd, 0); if (err) goto out; diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 35cc138b096d..15a45ec6518d 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -355,6 +355,7 @@ static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card) { struct mmc_host *host = card->host; u64 limit = BLK_BOUNCE_HIGH; + unsigned block_size = 512; if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; @@ -368,7 +369,13 @@ static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card) blk_queue_max_hw_sectors(mq->queue, min(host->max_blk_count, host->max_req_size / 512)); blk_queue_max_segments(mq->queue, host->max_segs); - blk_queue_max_segment_size(mq->queue, host->max_seg_size); + + if (mmc_card_mmc(card)) + block_size = card->ext_csd.data_sector_size; + + blk_queue_logical_block_size(mq->queue, block_size); + blk_queue_max_segment_size(mq->queue, + round_down(host->max_seg_size, block_size)); INIT_WORK(&mq->recovery_work, mmc_mq_recovery_handler); INIT_WORK(&mq->complete_work, mmc_blk_mq_complete_work); diff --git a/drivers/mmc/core/regulator.c b/drivers/mmc/core/regulator.c new file mode 100644 index 000000000000..b6febbcf8978 --- /dev/null +++ b/drivers/mmc/core/regulator.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Helper functions for MMC regulators. + */ + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/log2.h> +#include <linux/regulator/consumer.h> + +#include <linux/mmc/host.h> + +#include "core.h" +#include "host.h" + +#ifdef CONFIG_REGULATOR + +/** + * mmc_ocrbitnum_to_vdd - Convert a OCR bit number to its voltage + * @vdd_bit: OCR bit number + * @min_uV: minimum voltage value (mV) + * @max_uV: maximum voltage value (mV) + * + * This function returns the voltage range according to the provided OCR + * bit number. If conversion is not possible a negative errno value returned. + */ +static int mmc_ocrbitnum_to_vdd(int vdd_bit, int *min_uV, int *max_uV) +{ + int tmp; + + if (!vdd_bit) + return -EINVAL; + + /* + * REVISIT mmc_vddrange_to_ocrmask() may have set some + * bits this regulator doesn't quite support ... don't + * be too picky, most cards and regulators are OK with + * a 0.1V range goof (it's a small error percentage). + */ + tmp = vdd_bit - ilog2(MMC_VDD_165_195); + if (tmp == 0) { + *min_uV = 1650 * 1000; + *max_uV = 1950 * 1000; + } else { + *min_uV = 1900 * 1000 + tmp * 100 * 1000; + *max_uV = *min_uV + 100 * 1000; + } + + return 0; +} + +/** + * mmc_regulator_get_ocrmask - return mask of supported voltages + * @supply: regulator to use + * + * This returns either a negative errno, or a mask of voltages that + * can be provided to MMC/SD/SDIO devices using the specified voltage + * regulator. This would normally be called before registering the + * MMC host adapter. + */ +static int mmc_regulator_get_ocrmask(struct regulator *supply) +{ + int result = 0; + int count; + int i; + int vdd_uV; + int vdd_mV; + + count = regulator_count_voltages(supply); + if (count < 0) + return count; + + for (i = 0; i < count; i++) { + vdd_uV = regulator_list_voltage(supply, i); + if (vdd_uV <= 0) + continue; + + vdd_mV = vdd_uV / 1000; + result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV); + } + + if (!result) { + vdd_uV = regulator_get_voltage(supply); + if (vdd_uV <= 0) + return vdd_uV; + + vdd_mV = vdd_uV / 1000; + result = mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV); + } + + return result; +} + +/** + * mmc_regulator_set_ocr - set regulator to match host->ios voltage + * @mmc: the host to regulate + * @supply: regulator to use + * @vdd_bit: zero for power off, else a bit number (host->ios.vdd) + * + * Returns zero on success, else negative errno. + * + * MMC host drivers may use this to enable or disable a regulator using + * a particular supply voltage. This would normally be called from the + * set_ios() method. + */ +int mmc_regulator_set_ocr(struct mmc_host *mmc, + struct regulator *supply, + unsigned short vdd_bit) +{ + int result = 0; + int min_uV, max_uV; + + if (vdd_bit) { + mmc_ocrbitnum_to_vdd(vdd_bit, &min_uV, &max_uV); + + result = regulator_set_voltage(supply, min_uV, max_uV); + if (result == 0 && !mmc->regulator_enabled) { + result = regulator_enable(supply); + if (!result) + mmc->regulator_enabled = true; + } + } else if (mmc->regulator_enabled) { + result = regulator_disable(supply); + if (result == 0) + mmc->regulator_enabled = false; + } + + if (result) + dev_err(mmc_dev(mmc), + "could not set regulator OCR (%d)\n", result); + return result; +} +EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr); + +static int mmc_regulator_set_voltage_if_supported(struct regulator *regulator, + int min_uV, int target_uV, + int max_uV) +{ + /* + * Check if supported first to avoid errors since we may try several + * signal levels during power up and don't want to show errors. + */ + if (!regulator_is_supported_voltage(regulator, min_uV, max_uV)) + return -EINVAL; + + return regulator_set_voltage_triplet(regulator, min_uV, target_uV, + max_uV); +} + +/** + * mmc_regulator_set_vqmmc - Set VQMMC as per the ios + * + * For 3.3V signaling, we try to match VQMMC to VMMC as closely as possible. + * That will match the behavior of old boards where VQMMC and VMMC were supplied + * by the same supply. The Bus Operating conditions for 3.3V signaling in the + * SD card spec also define VQMMC in terms of VMMC. + * If this is not possible we'll try the full 2.7-3.6V of the spec. + * + * For 1.2V and 1.8V signaling we'll try to get as close as possible to the + * requested voltage. This is definitely a good idea for UHS where there's a + * separate regulator on the card that's trying to make 1.8V and it's best if + * we match. + * + * This function is expected to be used by a controller's + * start_signal_voltage_switch() function. + */ +int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct device *dev = mmc_dev(mmc); + int ret, volt, min_uV, max_uV; + + /* If no vqmmc supply then we can't change the voltage */ + if (IS_ERR(mmc->supply.vqmmc)) + return -EINVAL; + + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_120: + return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, + 1100000, 1200000, 1300000); + case MMC_SIGNAL_VOLTAGE_180: + return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, + 1700000, 1800000, 1950000); + case MMC_SIGNAL_VOLTAGE_330: + ret = mmc_ocrbitnum_to_vdd(mmc->ios.vdd, &volt, &max_uV); + if (ret < 0) + return ret; + + dev_dbg(dev, "%s: found vmmc voltage range of %d-%duV\n", + __func__, volt, max_uV); + + min_uV = max(volt - 300000, 2700000); + max_uV = min(max_uV + 200000, 3600000); + + /* + * Due to a limitation in the current implementation of + * regulator_set_voltage_triplet() which is taking the lowest + * voltage possible if below the target, search for a suitable + * voltage in two steps and try to stay close to vmmc + * with a 0.3V tolerance at first. + */ + if (!mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, + min_uV, volt, max_uV)) + return 0; + + return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, + 2700000, volt, 3600000); + default: + return -EINVAL; + } +} +EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc); + +#else + +static inline int mmc_regulator_get_ocrmask(struct regulator *supply) +{ + return 0; +} + +#endif /* CONFIG_REGULATOR */ + +/** + * mmc_regulator_get_supply - try to get VMMC and VQMMC regulators for a host + * @mmc: the host to regulate + * + * Returns 0 or errno. errno should be handled, it is either a critical error + * or -EPROBE_DEFER. 0 means no critical error but it does not mean all + * regulators have been found because they all are optional. If you require + * certain regulators, you need to check separately in your driver if they got + * populated after calling this function. + */ +int mmc_regulator_get_supply(struct mmc_host *mmc) +{ + struct device *dev = mmc_dev(mmc); + int ret; + + mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc"); + mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc"); + + if (IS_ERR(mmc->supply.vmmc)) { + if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_dbg(dev, "No vmmc regulator found\n"); + } else { + ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc); + if (ret > 0) + mmc->ocr_avail = ret; + else + dev_warn(dev, "Failed getting OCR mask: %d\n", ret); + } + + if (IS_ERR(mmc->supply.vqmmc)) { + if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_dbg(dev, "No vqmmc regulator found\n"); + } + + return 0; +} +EXPORT_SYMBOL_GPL(mmc_regulator_get_supply); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index d0d9f90e7cdf..265e1aeeb9d8 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -209,6 +209,11 @@ static int mmc_decode_scr(struct mmc_card *card) /* Check if Physical Layer Spec v3.0 is supported */ scr->sda_spec3 = UNSTUFF_BITS(resp, 47, 1); + if (scr->sda_spec3) { + scr->sda_spec4 = UNSTUFF_BITS(resp, 42, 1); + scr->sda_specx = UNSTUFF_BITS(resp, 38, 4); + } + if (UNSTUFF_BITS(resp, 55, 1)) card->erased_byte = 0xFF; else @@ -226,6 +231,8 @@ static int mmc_read_ssr(struct mmc_card *card) { unsigned int au, es, et, eo; __be32 *raw_ssr; + u32 resp[4] = {}; + u8 discard_support; int i; if (!(card->csd.cmdclass & CCC_APP_SPEC)) { @@ -271,6 +278,14 @@ static int mmc_read_ssr(struct mmc_card *card) } } + /* + * starting SD5.1 discard is supported if DISCARD_SUPPORT (b313) is set + */ + resp[3] = card->raw_ssr[6]; + discard_support = UNSTUFF_BITS(resp, 313 - 288, 1); + card->erase_arg = (card->scr.sda_specx && discard_support) ? + SD_DISCARD_ARG : SD_ERASE_ARG; + return 0; } @@ -936,8 +951,11 @@ retry: return err; if (oldcard) { - if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) + if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) { + pr_debug("%s: Perhaps the card was replaced\n", + mmc_hostname(host)); return -ENOENT; + } card = oldcard; } else { diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index 47056d8d1bac..0bb0b8419016 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -52,36 +52,17 @@ int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) } EXPORT_SYMBOL_GPL(mmc_app_cmd); -/** - * mmc_wait_for_app_cmd - start an application command and wait for - completion - * @host: MMC host to start command - * @card: Card to send MMC_APP_CMD to - * @cmd: MMC command to start - * @retries: maximum number of retries - * - * Sends a MMC_APP_CMD, checks the card response, sends the command - * in the parameter and waits for it to complete. Return any error - * that occurred while the command was executing. Do not attempt to - * parse the response. - */ -int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, - struct mmc_command *cmd, int retries) +static int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, + struct mmc_command *cmd) { struct mmc_request mrq = {}; - - int i, err; - - if (retries < 0) - retries = MMC_CMD_RETRIES; - - err = -EIO; + int i, err = -EIO; /* * We have to resend MMC_APP_CMD for each attempt so * we cannot use the retries field in mmc_command. */ - for (i = 0;i <= retries;i++) { + for (i = 0; i <= MMC_CMD_RETRIES; i++) { err = mmc_app_cmd(host, card); if (err) { /* no point in retrying; no APP commands allowed */ @@ -116,8 +97,6 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, return err; } -EXPORT_SYMBOL(mmc_wait_for_app_cmd); - int mmc_app_set_bus_width(struct mmc_card *card, int width) { struct mmc_command cmd = {}; @@ -136,7 +115,7 @@ int mmc_app_set_bus_width(struct mmc_card *card, int width) return -EINVAL; } - return mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES); + return mmc_wait_for_app_cmd(card->host, card, &cmd); } int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) @@ -152,7 +131,7 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; for (i = 100; i; i--) { - err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES); + err = mmc_wait_for_app_cmd(host, NULL, &cmd); if (err) break; diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h index 0e6c3d51e66d..ffaed5cacc88 100644 --- a/drivers/mmc/core/sd_ops.h +++ b/drivers/mmc/core/sd_ops.h @@ -16,7 +16,6 @@ struct mmc_card; struct mmc_host; -struct mmc_command; int mmc_app_set_bus_width(struct mmc_card *card, int width); int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); @@ -27,8 +26,6 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, u8 value, u8 *resp); int mmc_app_sd_status(struct mmc_card *card, void *ssr); int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card); -int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, - struct mmc_command *cmd, int retries); #endif diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index d8e17ea6126d..6718fc8bb40f 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -617,6 +617,8 @@ try_again: if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO || memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) { mmc_remove_card(card); + pr_debug("%s: Perhaps the card was replaced\n", + mmc_hostname(host)); return -ENOENT; } } else { @@ -624,6 +626,8 @@ try_again: if (oldcard && oldcard->type != MMC_TYPE_SDIO) { mmc_remove_card(card); + pr_debug("%s: Perhaps the card was replaced\n", + mmc_hostname(host)); return -ENOENT; } } @@ -736,8 +740,11 @@ try_again: int same = (card->cis.vendor == oldcard->cis.vendor && card->cis.device == oldcard->cis.device); mmc_remove_card(card); - if (!same) + if (!same) { + pr_debug("%s: Perhaps the card was replaced\n", + mmc_hostname(host)); return -ENOENT; + } card = oldcard; } diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index b6d8203e46eb..62b0f5ecc7f7 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -179,7 +179,6 @@ static int sdio_bus_remove(struct device *dev) { struct sdio_driver *drv = to_sdio_driver(dev->driver); struct sdio_func *func = dev_to_sdio_func(dev); - int ret = 0; /* Make sure card is powered before invoking ->remove() */ if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) @@ -205,7 +204,7 @@ static int sdio_bus_remove(struct device *dev) dev_pm_domain_detach(dev, false); - return ret; + return 0; } static const struct dev_pm_ops sdio_bus_pm_ops = { diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c index d40744bbafa9..3f67fbbe0d75 100644 --- a/drivers/mmc/core/sdio_io.c +++ b/drivers/mmc/core/sdio_io.c @@ -10,6 +10,7 @@ */ #include <linux/export.h> +#include <linux/kernel.h> #include <linux/mmc/host.h> #include <linux/mmc/card.h> #include <linux/mmc/sdio.h> @@ -203,6 +204,21 @@ static inline unsigned int sdio_max_byte_size(struct sdio_func *func) return min(mval, 512u); /* maximum size for byte mode */ } +/* + * This is legacy code, which needs to be re-worked some day. Basically we need + * to take into account the properties of the host, as to enable the SDIO func + * driver layer to allocate optimal buffers. + */ +static inline unsigned int _sdio_align_size(unsigned int sz) +{ + /* + * FIXME: We don't have a system for the controller to tell + * the core about its problems yet, so for now we just 32-bit + * align the size. + */ + return ALIGN(sz, 4); +} + /** * sdio_align_size - pads a transfer size to a more optimal value * @func: SDIO function @@ -230,7 +246,7 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz) * wants to increase the size up to a point where it * might need more than one block. */ - sz = mmc_align_data_size(func->card, sz); + sz = _sdio_align_size(sz); /* * If we can still do this with just a byte transfer, then @@ -252,7 +268,7 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz) */ blk_sz = ((sz + func->cur_blksize - 1) / func->cur_blksize) * func->cur_blksize; - blk_sz = mmc_align_data_size(func->card, blk_sz); + blk_sz = _sdio_align_size(blk_sz); /* * This value is only good if it is still just @@ -265,8 +281,7 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz) * We failed to do one request, but at least try to * pad the remainder properly. */ - byte_sz = mmc_align_data_size(func->card, - sz % func->cur_blksize); + byte_sz = _sdio_align_size(sz % func->cur_blksize); if (byte_sz <= sdio_max_byte_size(func)) { blk_sz = sz / func->cur_blksize; return blk_sz * func->cur_blksize + byte_sz; @@ -276,16 +291,14 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz) * We need multiple requests, so first check that the * controller can handle the chunk size; */ - chunk_sz = mmc_align_data_size(func->card, - sdio_max_byte_size(func)); + chunk_sz = _sdio_align_size(sdio_max_byte_size(func)); if (chunk_sz == sdio_max_byte_size(func)) { /* * Fix up the size of the remainder (if any) */ byte_sz = orig_sz % chunk_sz; if (byte_sz) { - byte_sz = mmc_align_data_size(func->card, - byte_sz); + byte_sz = _sdio_align_size(byte_sz); } return (orig_sz / chunk_sz) * chunk_sz + byte_sz; diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h index 96945cafbf0b..1f6d0447ea0f 100644 --- a/drivers/mmc/core/sdio_ops.h +++ b/drivers/mmc/core/sdio_ops.h @@ -25,7 +25,6 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz); int sdio_reset(struct mmc_host *host); -unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz); void sdio_irq_work(struct work_struct *work); static inline bool sdio_is_io_busy(u32 opcode, u32 arg) diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 319ccd93383d..4afc6b87b465 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c @@ -22,7 +22,6 @@ struct mmc_gpio { struct gpio_desc *ro_gpio; struct gpio_desc *cd_gpio; - bool override_ro_active_level; bool override_cd_active_level; irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id); char *ro_label; @@ -71,10 +70,6 @@ int mmc_gpio_get_ro(struct mmc_host *host) if (!ctx || !ctx->ro_gpio) return -ENOSYS; - if (ctx->override_ro_active_level) - return !gpiod_get_raw_value_cansleep(ctx->ro_gpio) ^ - !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH); - return gpiod_get_value_cansleep(ctx->ro_gpio); } EXPORT_SYMBOL(mmc_gpio_get_ro); @@ -225,7 +220,6 @@ EXPORT_SYMBOL(mmc_can_gpio_cd); * @host: mmc host * @con_id: function within the GPIO consumer * @idx: index of the GPIO to obtain in the consumer - * @override_active_level: ignore %GPIO_ACTIVE_LOW flag * @debounce: debounce time in microseconds * @gpio_invert: will return whether the GPIO line is inverted or not, * set to NULL to ignore @@ -233,7 +227,7 @@ EXPORT_SYMBOL(mmc_can_gpio_cd); * Returns zero on success, else an error. */ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, - unsigned int idx, bool override_active_level, + unsigned int idx, unsigned int debounce, bool *gpio_invert) { struct mmc_gpio *ctx = host->slot.handler_priv; @@ -253,7 +247,6 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, if (gpio_invert) *gpio_invert = !gpiod_is_active_low(desc); - ctx->override_ro_active_level = override_active_level; ctx->ro_gpio = desc; return 0; diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index e26b8145efb3..28fcd8f580a1 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -116,7 +116,7 @@ config MMC_RICOH_MMC config MMC_SDHCI_ACPI tristate "SDHCI support for ACPI enumerated SDHCI controllers" - depends on MMC_SDHCI && ACPI + depends on MMC_SDHCI && ACPI && PCI select IOSF_MBI if X86 help This selects support for ACPI enumerated SDHCI controllers, @@ -224,6 +224,7 @@ config MMC_SDHCI_ESDHC_IMX depends on ARCH_MXC depends on MMC_SDHCI_PLTFM select MMC_SDHCI_IO_ACCESSORS + select MMC_CQHCI help This selects the Freescale eSDHC/uSDHC controller support found on i.MX25, i.MX35 i.MX5x and i.MX6x. @@ -250,6 +251,7 @@ config MMC_SDHCI_TEGRA depends on ARCH_TEGRA depends on MMC_SDHCI_PLTFM select MMC_SDHCI_IO_ACCESSORS + select MMC_CQHCI help This selects the Tegra SD/MMC controller. If you have a Tegra platform with SD or MMC devices, say Y or M here. @@ -978,7 +980,7 @@ config MMC_SDHCI_OMAP tristate "TI SDHCI Controller Support" depends on MMC_SDHCI_PLTFM && OF select THERMAL - select TI_SOC_THERMAL + imply TI_SOC_THERMAL help This selects the Secure Digital Host Controller Interface (SDHCI) support present in TI's DRA7 SOCs. The controller supports diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 47189f9ed4e2..735aa5871358 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1410,6 +1410,9 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) case MMC_BUS_WIDTH_4: slot->sdc_reg |= ATMCI_SDCBUS_4BIT; break; + case MMC_BUS_WIDTH_8: + slot->sdc_reg |= ATMCI_SDCBUS_8BIT; + break; } if (ios->clock) { @@ -2275,8 +2278,11 @@ static int atmci_init_slot(struct atmel_mci *host, * use only one bit for data to prevent fifo underruns and overruns * which will corrupt data. */ - if ((slot_data->bus_width >= 4) && host->caps.has_rwproof) + if ((slot_data->bus_width >= 4) && host->caps.has_rwproof) { mmc->caps |= MMC_CAP_4_BIT_DATA; + if (slot_data->bus_width >= 8) + mmc->caps |= MMC_CAP_8_BIT_DATA; + } if (atmci_get_version(host) < 0x200) { mmc->max_segs = 256; diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index 50293529d6de..7e0d3a49c06d 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -148,7 +148,6 @@ struct bcm2835_host { void __iomem *ioaddr; u32 phys_addr; - struct mmc_host *mmc; struct platform_device *pdev; int clock; /* Current clock speed */ @@ -618,7 +617,7 @@ static void bcm2835_finish_request(struct bcm2835_host *host) "failed to terminate DMA (%d)\n", err); } - mmc_request_done(host->mmc, mrq); + mmc_request_done(mmc_from_priv(host), mrq); } static @@ -837,7 +836,7 @@ static void bcm2835_timeout(struct work_struct *work) dev_err(dev, "timeout waiting for hardware interrupt.\n"); bcm2835_dumpregs(host); - bcm2835_reset(host->mmc); + bcm2835_reset(mmc_from_priv(host)); if (host->data) { host->data->error = -ETIMEDOUT; @@ -1100,6 +1099,7 @@ static void bcm2835_dma_complete_work(struct work_struct *work) static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock) { + struct mmc_host *mmc = mmc_from_priv(host); int div; /* The SDCDIV register has 11 bits, and holds (div - 2). But @@ -1143,18 +1143,18 @@ static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock) div = SDCDIV_MAX_CDIV; clock = host->max_clk / (div + 2); - host->mmc->actual_clock = clock; + mmc->actual_clock = clock; /* Calibrate some delays */ host->ns_per_fifo_word = (1000000000 / clock) * - ((host->mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32); + ((mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32); host->cdiv = div; writel(host->cdiv, host->ioaddr + SDCDIV); /* Set the timeout to 500ms */ - writel(host->mmc->actual_clock / 2, host->ioaddr + SDTOUT); + writel(mmc->actual_clock / 2, host->ioaddr + SDTOUT); } static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq) @@ -1264,7 +1264,7 @@ static const struct mmc_host_ops bcm2835_ops = { static int bcm2835_add_host(struct bcm2835_host *host) { - struct mmc_host *mmc = host->mmc; + struct mmc_host *mmc = mmc_from_priv(host); struct device *dev = &host->pdev->dev; char pio_limit_string[20]; int ret; @@ -1286,7 +1286,7 @@ static int bcm2835_add_host(struct bcm2835_host *host) spin_lock_init(&host->lock); mutex_init(&host->mutex); - if (IS_ERR_OR_NULL(host->dma_chan_rxtx)) { + if (!host->dma_chan_rxtx) { dev_warn(dev, "unable to initialise DMA channel. Falling back to PIO\n"); host->use_dma = false; } else { @@ -1370,7 +1370,6 @@ static int bcm2835_probe(struct platform_device *pdev) mmc->ops = &bcm2835_ops; host = mmc_priv(mmc); - host->mmc = mmc; host->pdev = pdev; spin_lock_init(&host->lock); @@ -1431,6 +1430,8 @@ static int bcm2835_probe(struct platform_device *pdev) err: dev_dbg(dev, "%s -> err %d\n", __func__, ret); + if (host->dma_chan_rxtx) + dma_release_channel(host->dma_chan_rxtx); mmc_free_host(mmc); return ret; @@ -1439,8 +1440,9 @@ err: static int bcm2835_remove(struct platform_device *pdev) { struct bcm2835_host *host = platform_get_drvdata(pdev); + struct mmc_host *mmc = mmc_from_priv(host); - mmc_remove_host(host->mmc); + mmc_remove_host(mmc); writel(SDVDD_POWER_OFF, host->ioaddr + SDVDD); @@ -1452,8 +1454,7 @@ static int bcm2835_remove(struct platform_device *pdev) if (host->dma_chan_rxtx) dma_release_channel(host->dma_chan_rxtx); - mmc_free_host(host->mmc); - platform_set_drvdata(pdev, NULL); + mmc_free_host(mmc); return 0; } diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c index 1087b4c79cd6..4c477dcd2ada 100644 --- a/drivers/mmc/host/cb710-mmc.c +++ b/drivers/mmc/host/cb710-mmc.c @@ -566,30 +566,32 @@ static void cb710_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) cb710_mmc_select_clock_divider(mmc, ios->clock); - if (ios->power_mode != reader->last_power_mode) - switch (ios->power_mode) { - case MMC_POWER_ON: - err = cb710_mmc_powerup(slot); - if (err) { - dev_warn(cb710_slot_dev(slot), - "powerup failed (%d)- retrying\n", err); - cb710_mmc_powerdown(slot); - udelay(1); + if (ios->power_mode != reader->last_power_mode) { + switch (ios->power_mode) { + case MMC_POWER_ON: err = cb710_mmc_powerup(slot); - if (err) + if (err) { dev_warn(cb710_slot_dev(slot), - "powerup retry failed (%d) - expect errors\n", + "powerup failed (%d)- retrying\n", err); + cb710_mmc_powerdown(slot); + udelay(1); + err = cb710_mmc_powerup(slot); + if (err) + dev_warn(cb710_slot_dev(slot), + "powerup retry failed (%d) - expect errors\n", err); + } + reader->last_power_mode = MMC_POWER_ON; + break; + case MMC_POWER_OFF: + cb710_mmc_powerdown(slot); + reader->last_power_mode = MMC_POWER_OFF; + break; + case MMC_POWER_UP: + default: + /* ignore */ + break; } - reader->last_power_mode = MMC_POWER_ON; - break; - case MMC_POWER_OFF: - cb710_mmc_powerdown(slot); - reader->last_power_mode = MMC_POWER_OFF; - break; - case MMC_POWER_UP: - default: - /* ignore */; } cb710_mmc_enable_4bit_data(slot, ios->bus_width != MMC_BUS_WIDTH_1); diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c index 159270e947cf..a8af682a9182 100644 --- a/drivers/mmc/host/cqhci.c +++ b/drivers/mmc/host/cqhci.c @@ -201,7 +201,7 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) cq_host->desc_size = cq_host->slot_sz * cq_host->num_slots; cq_host->data_size = cq_host->trans_desc_len * cq_host->mmc->max_segs * - (cq_host->num_slots - 1); + cq_host->mmc->cqe_qdepth; pr_debug("%s: cqhci: desc_size: %zu data_sz: %zu slot-sz: %d\n", mmc_hostname(cq_host->mmc), cq_host->desc_size, cq_host->data_size, @@ -217,12 +217,21 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) cq_host->desc_size, &cq_host->desc_dma_base, GFP_KERNEL); + if (!cq_host->desc_base) + return -ENOMEM; + cq_host->trans_desc_base = dmam_alloc_coherent(mmc_dev(cq_host->mmc), cq_host->data_size, &cq_host->trans_desc_dma_base, GFP_KERNEL); - if (!cq_host->desc_base || !cq_host->trans_desc_base) + if (!cq_host->trans_desc_base) { + dmam_free_coherent(mmc_dev(cq_host->mmc), cq_host->desc_size, + cq_host->desc_base, + cq_host->desc_dma_base); + cq_host->desc_base = NULL; + cq_host->desc_dma_base = 0; return -ENOMEM; + } pr_debug("%s: cqhci: desc-base: 0x%p trans-base: 0x%p\n desc_dma 0x%llx trans_dma: 0x%llx\n", mmc_hostname(cq_host->mmc), cq_host->desc_base, cq_host->trans_desc_base, diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 9e68c3645e22..49e0daf2ef5e 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -1193,7 +1193,7 @@ static int mmc_davinci_parse_pdata(struct mmc_host *mmc) else if (ret) mmc->caps |= MMC_CAP_NEEDS_POLL; - ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL); + ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL); if (ret == -EPROBE_DEFER) return ret; diff --git a/drivers/mmc/host/dw_mmc-bluefield.c b/drivers/mmc/host/dw_mmc-bluefield.c index ed8f2254b66a..aa38b1a8017e 100644 --- a/drivers/mmc/host/dw_mmc-bluefield.c +++ b/drivers/mmc/host/dw_mmc-bluefield.c @@ -1,11 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2018 Mellanox Technologies. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #include <linux/bitfield.h> diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 33215d66afa2..63303022669c 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -21,7 +21,6 @@ #include <linux/dmaengine.h> #include <linux/dma-mapping.h> #include <linux/err.h> -#include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/irq.h> @@ -36,7 +35,6 @@ #include <asm/cacheflush.h> #include <asm/mach-jz4740/dma.h> -#include <asm/mach-jz4740/jz4740_mmc.h> #define JZ_REG_MMC_STRPCL 0x00 #define JZ_REG_MMC_STATUS 0x04 @@ -148,9 +146,7 @@ enum jz4780_cookie { struct jz4740_mmc_host { struct mmc_host *mmc; struct platform_device *pdev; - struct jz4740_mmc_platform_data *pdata; struct clk *clk; - struct gpio_desc *power; enum jz4740_mmc_version version; @@ -743,6 +739,7 @@ static irqreturn_t jz_mmc_irq_worker(int irq, void *devid) break; jz_mmc_prepare_data_transfer(host); + /* fall through */ case JZ4740_MMC_STATE_TRANSFER_DATA: if (host->use_dma) { @@ -777,6 +774,7 @@ static irqreturn_t jz_mmc_irq_worker(int irq, void *devid) break; } jz4740_mmc_write_irq_reg(host, JZ_MMC_IRQ_DATA_TRAN_DONE); + /* fall through */ case JZ4740_MMC_STATE_SEND_STOP: if (!req->stop) @@ -894,16 +892,16 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) switch (ios->power_mode) { case MMC_POWER_UP: jz4740_mmc_reset(host); - if (host->power) - gpiod_set_value(host->power, 1); + if (!IS_ERR(mmc->supply.vmmc)) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); host->cmdat |= JZ_MMC_CMDAT_INIT; clk_prepare_enable(host->clk); break; case MMC_POWER_ON: break; default: - if (host->power) - gpiod_set_value(host->power, 0); + if (!IS_ERR(mmc->supply.vmmc)) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); clk_disable_unprepare(host->clk); break; } @@ -936,38 +934,6 @@ static const struct mmc_host_ops jz4740_mmc_ops = { .enable_sdio_irq = jz4740_mmc_enable_sdio_irq, }; -static int jz4740_mmc_request_gpios(struct jz4740_mmc_host *host, - struct mmc_host *mmc, - struct platform_device *pdev) -{ - struct jz4740_mmc_platform_data *pdata = dev_get_platdata(&pdev->dev); - int ret = 0; - - if (!pdata) - return 0; - - if (!pdata->card_detect_active_low) - mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; - if (!pdata->read_only_active_low) - mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; - - /* - * Get optional card detect and write protect GPIOs, - * only back out on probe deferral. - */ - ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL); - if (ret == -EPROBE_DEFER) - return ret; - - ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL); - if (ret == -EPROBE_DEFER) - return ret; - - host->power = devm_gpiod_get_optional(&pdev->dev, "power", - GPIOD_OUT_HIGH); - return PTR_ERR_OR_ZERO(host->power); -} - static const struct of_device_id jz4740_mmc_of_match[] = { { .compatible = "ingenic,jz4740-mmc", .data = (void *) JZ_MMC_JZ4740 }, { .compatible = "ingenic,jz4725b-mmc", .data = (void *)JZ_MMC_JZ4725B }, @@ -982,9 +948,6 @@ static int jz4740_mmc_probe(struct platform_device* pdev) struct mmc_host *mmc; struct jz4740_mmc_host *host; const struct of_device_id *match; - struct jz4740_mmc_platform_data *pdata; - - pdata = dev_get_platdata(&pdev->dev); mmc = mmc_alloc_host(sizeof(struct jz4740_mmc_host), &pdev->dev); if (!mmc) { @@ -993,29 +956,25 @@ static int jz4740_mmc_probe(struct platform_device* pdev) } host = mmc_priv(mmc); - host->pdata = pdata; match = of_match_device(jz4740_mmc_of_match, &pdev->dev); if (match) { host->version = (enum jz4740_mmc_version)match->data; - ret = mmc_of_parse(mmc); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "could not parse of data: %d\n", ret); - goto err_free_host; - } } else { /* JZ4740 should be the only one using legacy probe */ host->version = JZ_MMC_JZ4740; - mmc->caps |= MMC_CAP_SDIO_IRQ; - if (!(pdata && pdata->data_1bit)) - mmc->caps |= MMC_CAP_4_BIT_DATA; - ret = jz4740_mmc_request_gpios(host, mmc, pdev); - if (ret) - goto err_free_host; } + ret = mmc_of_parse(mmc); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "could not parse device properties: %d\n", ret); + goto err_free_host; + } + + mmc_regulator_get_supply(mmc); + host->irq = platform_get_irq(pdev, 0); if (host->irq < 0) { ret = host->irq; diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index c2690c1a50ff..2eba507790e4 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -179,6 +179,8 @@ struct meson_host { struct sd_emmc_desc *descs; dma_addr_t descs_dma_addr; + int irq; + bool vqmmc_enabled; }; @@ -738,6 +740,11 @@ static int meson_mmc_clk_phase_tuning(struct mmc_host *mmc, u32 opcode, static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) { struct meson_host *host = mmc_priv(mmc); + int adj = 0; + + /* enable signal resampling w/o delay */ + adj = ADJUST_ADJ_EN; + writel(adj, host->regs + host->data->adjust); return meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk); } @@ -768,6 +775,9 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (!IS_ERR(mmc->supply.vmmc)) mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); + /* disable signal resampling */ + writel(0, host->regs + host->data->adjust); + /* Reset rx phase */ clk_set_phase(host->rx_clk, 0); @@ -1166,7 +1176,7 @@ static int meson_mmc_get_cd(struct mmc_host *mmc) static void meson_mmc_cfg_init(struct meson_host *host) { - u32 cfg = 0, adj = 0; + u32 cfg = 0; cfg |= FIELD_PREP(CFG_RESP_TIMEOUT_MASK, ilog2(SD_EMMC_CFG_RESP_TIMEOUT)); @@ -1177,10 +1187,6 @@ static void meson_mmc_cfg_init(struct meson_host *host) cfg |= CFG_ERR_ABORT; writel(cfg, host->regs + SD_EMMC_CFG); - - /* enable signal resampling w/o delay */ - adj = ADJUST_ADJ_EN; - writel(adj, host->regs + host->data->adjust); } static int meson_mmc_card_busy(struct mmc_host *mmc) @@ -1231,7 +1237,7 @@ static int meson_mmc_probe(struct platform_device *pdev) struct resource *res; struct meson_host *host; struct mmc_host *mmc; - int ret, irq; + int ret; mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev); if (!mmc) @@ -1276,8 +1282,8 @@ static int meson_mmc_probe(struct platform_device *pdev) goto free_host; } - irq = platform_get_irq(pdev, 0); - if (irq <= 0) { + host->irq = platform_get_irq(pdev, 0); + if (host->irq <= 0) { dev_err(&pdev->dev, "failed to get interrupt resource.\n"); ret = -EINVAL; goto free_host; @@ -1331,9 +1337,9 @@ static int meson_mmc_probe(struct platform_device *pdev) writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN, host->regs + SD_EMMC_IRQ_EN); - ret = devm_request_threaded_irq(&pdev->dev, irq, meson_mmc_irq, - meson_mmc_irq_thread, IRQF_SHARED, - NULL, host); + ret = request_threaded_irq(host->irq, meson_mmc_irq, + meson_mmc_irq_thread, IRQF_SHARED, + dev_name(&pdev->dev), host); if (ret) goto err_init_clk; @@ -1351,7 +1357,7 @@ static int meson_mmc_probe(struct platform_device *pdev) if (host->bounce_buf == NULL) { dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n"); ret = -ENOMEM; - goto err_init_clk; + goto err_free_irq; } host->descs = dma_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN, @@ -1370,6 +1376,8 @@ static int meson_mmc_probe(struct platform_device *pdev) err_bounce_buf: dma_free_coherent(host->dev, host->bounce_buf_size, host->bounce_buf, host->bounce_dma_addr); +err_free_irq: + free_irq(host->irq, host); err_init_clk: clk_disable_unprepare(host->mmc_clk); err_core_clk: @@ -1387,6 +1395,7 @@ static int meson_mmc_remove(struct platform_device *pdev) /* disable interrupts */ writel(0, host->regs + SD_EMMC_IRQ_EN); + free_irq(host->irq, host); dma_free_coherent(host->dev, SD_EMMC_DESC_BUF_LEN, host->descs, host->descs_dma_addr); diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 10ba46b728e8..1b1498805972 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1450,9 +1450,10 @@ static int mmc_spi_probe(struct spi_device *spi) mmc->caps &= ~MMC_CAP_NEEDS_POLL; mmc_gpiod_request_cd_irq(mmc); } + mmc_detect_change(mmc, 0); /* Index 1 is write protect/read only */ - status = mmc_gpiod_request_ro(mmc, NULL, 1, false, 0, NULL); + status = mmc_gpiod_request_ro(mmc, NULL, 1, 0, NULL); if (status == -EPROBE_DEFER) goto fail_add_host; if (!status) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index e352f5ad5801..387ff14587b8 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -1127,6 +1127,12 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) writel(c, base + MMCICOMMAND); } +static void mmci_stop_command(struct mmci_host *host) +{ + host->stop_abort.error = 0; + mmci_start_command(host, &host->stop_abort, 0); +} + static void mmci_data_irq(struct mmci_host *host, struct mmc_data *data, unsigned int status) @@ -1196,10 +1202,16 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, /* The error clause is handled above, success! */ data->bytes_xfered = data->blksz * data->blocks; - if (!data->stop || (host->mrq->sbc && !data->error)) + if (!data->stop) { + if (host->variant->cmdreg_stop && data->error) + mmci_stop_command(host); + else + mmci_request_end(host, data->mrq); + } else if (host->mrq->sbc && !data->error) { mmci_request_end(host, data->mrq); - else + } else { mmci_start_command(host, data->stop, 0); + } } } @@ -1298,6 +1310,10 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, mmci_dma_error(host); mmci_stop_data(host); + if (host->variant->cmdreg_stop && cmd->error) { + mmci_stop_command(host); + return; + } } mmci_request_end(host, host->mrq); } else if (sbc) { @@ -1956,6 +1972,11 @@ static int mmci_probe(struct amba_device *dev, mmc->max_busy_timeout = 0; } + /* Prepare a CMD12 - needed to clear the DPSM on some variants. */ + host->stop_abort.opcode = MMC_STOP_TRANSMISSION; + host->stop_abort.arg = 0; + host->stop_abort.flags = MMC_RSP_R1B | MMC_CMD_AC; + mmc->ops = &mmci_ops; /* We support these PM capabilities. */ @@ -2011,7 +2032,7 @@ static int mmci_probe(struct amba_device *dev, if (ret == -EPROBE_DEFER) goto clk_disable; - ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL); + ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL); if (ret == -EPROBE_DEFER) goto clk_disable; } diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 24229097d05c..14df81054438 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -377,6 +377,7 @@ struct mmci_host { void __iomem *base; struct mmc_request *mrq; struct mmc_command *cmd; + struct mmc_command stop_abort; struct mmc_data *data; struct mmc_host *mmc; struct clk *clk; diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 8afeaf81ae66..833ef0590af8 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -846,7 +846,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) if (timing == MMC_TIMING_MMC_HS400 && host->dev_comp->hs400_tune) - sdr_set_field(host->base + PAD_CMD_TUNE, + sdr_set_field(host->base + tune_reg, MSDC_PAD_TUNE_CMDRRDLY, host->hs400_cmd_int_delay); dev_dbg(host->dev, "sclk: %d, timing: %d\n", host->mmc->actual_clock, diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 4d17032d15ee..d54612257b06 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -31,14 +31,12 @@ #include <linux/delay.h> #include <linux/clk.h> #include <linux/io.h> -#include <linux/gpio.h> #include <linux/regulator/consumer.h> #include <linux/dmaengine.h> #include <linux/types.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_dma.h> -#include <linux/of_gpio.h> #include <linux/mmc/slot-gpio.h> #include <asm/dma.h> diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index add1e70195ea..4f06fb03c0a2 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -25,7 +25,6 @@ #include <linux/ioport.h> #include <linux/of.h> #include <linux/of_device.h> -#include <linux/of_gpio.h> #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/interrupt.h> @@ -39,7 +38,6 @@ #include <linux/mmc/mmc.h> #include <linux/mmc/sdio.h> #include <linux/mmc/slot-gpio.h> -#include <linux/gpio.h> #include <linux/regulator/consumer.h> #include <linux/module.h> #include <linux/stmp_device.h> diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index b294b221f225..8a274b91804e 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c @@ -61,9 +61,6 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) struct device *dev = &spi->dev; struct device_node *np = dev->of_node; struct of_mmc_spi *oms; - const __be32 *voltage_ranges; - int num_ranges; - int i; if (dev->platform_data || !np) return dev->platform_data; @@ -72,25 +69,8 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) if (!oms) return NULL; - voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges); - num_ranges = num_ranges / sizeof(*voltage_ranges) / 2; - if (!voltage_ranges || !num_ranges) { - dev_err(dev, "OF: voltage-ranges unspecified\n"); + if (mmc_of_parse_voltage(np, &oms->pdata.ocr_mask) <= 0) goto err_ocr; - } - - for (i = 0; i < num_ranges; i++) { - const int j = i * 2; - u32 mask; - - mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]), - be32_to_cpu(voltage_ranges[j + 1])); - if (!mask) { - dev_err(dev, "OF: voltage-range #%d is invalid\n", i); - goto err_ocr; - } - oms->pdata.ocr_mask |= mask; - } oms->detect_irq = irq_of_parse_and_map(np, 0); if (oms->detect_irq != 0) { diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index c60a7625b1fa..b2873a2432b6 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -920,7 +920,7 @@ static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_reques reg &= ~(1 << 5); OMAP_MMC_WRITE(host, SDIO, reg); /* Set maximum timeout */ - OMAP_MMC_WRITE(host, CTO, 0xff); + OMAP_MMC_WRITE(host, CTO, 0xfd); } static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req) diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 8779bbaa6b69..c907bf502a12 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -743,7 +743,7 @@ static int pxamci_probe(struct platform_device *pdev) goto out; } - ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL); + ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL); if (ret && ret != -ENOENT) { dev_err(dev, "Failed requesting gpio_ro\n"); goto out; diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index da1e49c45bec..8394a7bb1fc1 100644 --- a/drivers/mmc/host/renesas_sdhi.h +++ b/drivers/mmc/host/renesas_sdhi.h @@ -15,6 +15,7 @@ struct renesas_sdhi_scc { unsigned long clk_rate; /* clock rate for SDR104 */ u32 tap; /* sampling clock position for SDR104 */ + u32 tap_hs400; /* sampling clock position for HS400 */ }; struct renesas_sdhi_of_data { @@ -49,6 +50,7 @@ struct renesas_sdhi { struct pinctrl_state *pins_default, *pins_uhs; void __iomem *scc_ctl; u32 scc_tappos; + u32 scc_tappos_hs400; }; #define host_to_priv(host) \ diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 31a351a20dc0..71e13844df6c 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -337,6 +337,10 @@ static void renesas_sdhi_hs400_complete(struct tmio_mmc_host *host) /* Set HS400 mode */ sd_ctrl_write16(host, CTL_SDIF_MODE, 0x0001 | sd_ctrl_read16(host, CTL_SDIF_MODE)); + + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, + priv->scc_tappos_hs400); + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, (SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN | SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) | @@ -396,6 +400,9 @@ static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host, /* Reset HS400 mode */ sd_ctrl_write16(host, CTL_SDIF_MODE, ~0x0001 & sd_ctrl_read16(host, CTL_SDIF_MODE)); + + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, priv->scc_tappos); + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, ~(SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN | SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) & @@ -723,6 +730,13 @@ int renesas_sdhi_probe(struct platform_device *pdev, host->ops.start_signal_voltage_switch = renesas_sdhi_start_signal_voltage_switch; host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27; + + /* SDR and HS200/400 registers requires HW reset */ + if (of_data && of_data->scc_offset) { + priv->scc_ctl = host->ctl + of_data->scc_offset; + host->mmc->caps |= MMC_CAP_HW_RESET; + host->hw_reset = renesas_sdhi_hw_reset; + } } /* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */ @@ -775,12 +789,11 @@ int renesas_sdhi_probe(struct platform_device *pdev, const struct renesas_sdhi_scc *taps = of_data->taps; bool hit = false; - host->mmc->caps |= MMC_CAP_HW_RESET; - for (i = 0; i < of_data->taps_num; i++) { if (taps[i].clk_rate == 0 || taps[i].clk_rate == host->mmc->f_max) { priv->scc_tappos = taps->tap; + priv->scc_tappos_hs400 = taps->tap_hs400; hit = true; break; } @@ -789,12 +802,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, if (!hit) dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n"); - priv->scc_ctl = host->ctl + of_data->scc_offset; host->init_tuning = renesas_sdhi_init_tuning; host->prepare_tuning = renesas_sdhi_prepare_tuning; host->select_tuning = renesas_sdhi_select_tuning; host->check_scc_error = renesas_sdhi_check_scc_error; - host->hw_reset = renesas_sdhi_hw_reset; host->prepare_hs400_tuning = renesas_sdhi_prepare_hs400_tuning; host->hs400_downgrade = renesas_sdhi_disable_scc; diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 92c9b15252da..9dfafa2a90a3 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -81,6 +81,7 @@ static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = { { .clk_rate = 0, .tap = 0x00000300, + .tap_hs400 = 0x00000704, }, }; diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c index 8471160316e0..02cd878e209f 100644 --- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c @@ -65,6 +65,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen2_compatible = { .scc_offset = 0x0300, .taps = rcar_gen2_scc_taps, .taps_num = ARRAY_SIZE(rcar_gen2_scc_taps), + .max_blk_count = 0xffffffff, }; /* Definitions for sampling clocks */ diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 10f5219b3b40..f31333e831a7 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -1530,7 +1530,7 @@ static int s3cmci_probe_pdata(struct s3cmci_host *host) return ret; } - ret = mmc_gpiod_request_ro(host->mmc, "wp", 0, false, 0, NULL); + ret = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0, NULL); if (ret != -ENOENT) { dev_err(&pdev->dev, "error requesting GPIO for WP %d\n", ret); diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index bdbd4897c0f7..a6c2bd202b45 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c @@ -18,12 +18,10 @@ #include <linux/platform_device.h> #include <linux/mmc/host.h> #include <linux/io.h> -#include <linux/gpio.h> #include <linux/clk.h> #include <linux/regulator/consumer.h> #include <linux/of.h> #include <linux/of_device.h> -#include <linux/of_gpio.h> #include <linux/mmc/slot-gpio.h> #include "sdhci-pltfm.h" diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index 552bddc5096c..1cd10356fc14 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -55,7 +55,9 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) } sdhci_get_of_property(pdev); - mmc_of_parse(host->mmc); + res = mmc_of_parse(host->mmc); + if (res) + goto err; /* * Supply the existing CAPS, but clear the UHS modes. This diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index d0d319398a54..8dbbc1f62b70 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -25,6 +25,7 @@ #include <linux/pm_runtime.h> #include "sdhci-pltfm.h" #include "sdhci-esdhc.h" +#include "cqhci.h" #define ESDHC_SYS_CTRL_DTOCV_MASK 0x0f #define ESDHC_CTRL_D3CD 0x08 @@ -50,6 +51,7 @@ #define ESDHC_MIX_CTRL_AUTO_TUNE_EN (1 << 24) #define ESDHC_MIX_CTRL_FBCLK_SEL (1 << 25) #define ESDHC_MIX_CTRL_HS400_EN (1 << 26) +#define ESDHC_MIX_CTRL_HS400_ES_EN (1 << 27) /* Bits 3 and 6 are not SDHCI standard definitions */ #define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7 /* Tuning bits */ @@ -76,6 +78,9 @@ #define ESDHC_STROBE_DLL_STS_REF_LOCK (1 << 1) #define ESDHC_STROBE_DLL_STS_SLV_LOCK 0x1 +#define ESDHC_VEND_SPEC2 0xc8 +#define ESDHC_VEND_SPEC2_EN_BUSY_IRQ (1 << 8) + #define ESDHC_TUNING_CTRL 0xcc #define ESDHC_STD_TUNING_EN (1 << 24) /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */ @@ -103,6 +108,9 @@ */ #define ESDHC_INT_VENDOR_SPEC_DMA_ERR (1 << 28) +/* the address offset of CQHCI */ +#define ESDHC_CQHCI_ADDR_OFFSET 0x100 + /* * The CMDTYPE of the CMD register (offset 0xE) should be set to * "11" when the STOP CMD12 is issued on imx53 to abort one @@ -138,51 +146,71 @@ #define ESDHC_FLAG_HS200 BIT(8) /* The IP supports HS400 mode */ #define ESDHC_FLAG_HS400 BIT(9) - -/* A clock frequency higher than this rate requires strobe dll control */ -#define ESDHC_STROBE_DLL_CLK_FREQ 100000000 +/* + * The IP has errata ERR010450 + * uSDHC: Due to the I/O timing limit, for SDR mode, SD card clock can't + * exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz. + */ +#define ESDHC_FLAG_ERR010450 BIT(10) +/* The IP supports HS400ES mode */ +#define ESDHC_FLAG_HS400_ES BIT(11) +/* The IP has Host Controller Interface for Command Queuing */ +#define ESDHC_FLAG_CQHCI BIT(12) struct esdhc_soc_data { u32 flags; }; -static struct esdhc_soc_data esdhc_imx25_data = { +static const struct esdhc_soc_data esdhc_imx25_data = { .flags = ESDHC_FLAG_ERR004536, }; -static struct esdhc_soc_data esdhc_imx35_data = { +static const struct esdhc_soc_data esdhc_imx35_data = { .flags = ESDHC_FLAG_ERR004536, }; -static struct esdhc_soc_data esdhc_imx51_data = { +static const struct esdhc_soc_data esdhc_imx51_data = { .flags = 0, }; -static struct esdhc_soc_data esdhc_imx53_data = { +static const struct esdhc_soc_data esdhc_imx53_data = { .flags = ESDHC_FLAG_MULTIBLK_NO_INT, }; -static struct esdhc_soc_data usdhc_imx6q_data = { +static const struct esdhc_soc_data usdhc_imx6q_data = { .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING, }; -static struct esdhc_soc_data usdhc_imx6sl_data = { +static const struct esdhc_soc_data usdhc_imx6sl_data = { .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_ERR004536 | ESDHC_FLAG_HS200, }; -static struct esdhc_soc_data usdhc_imx6sx_data = { +static const struct esdhc_soc_data usdhc_imx6sx_data = { .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200, }; -static struct esdhc_soc_data usdhc_imx7d_data = { +static const struct esdhc_soc_data usdhc_imx6ull_data = { + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 + | ESDHC_FLAG_ERR010450, +}; + +static const struct esdhc_soc_data usdhc_imx7d_data = { .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 | ESDHC_FLAG_HS400, }; +static struct esdhc_soc_data usdhc_imx8qxp_data = { + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 + | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES + | ESDHC_FLAG_CQHCI, +}; + struct pltfm_imx_data { u32 scratchpad; struct pinctrl *pinctrl; @@ -227,7 +255,9 @@ static const struct of_device_id imx_esdhc_dt_ids[] = { { .compatible = "fsl,imx6sx-usdhc", .data = &usdhc_imx6sx_data, }, { .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, }, { .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, }, + { .compatible = "fsl,imx6ull-usdhc", .data = &usdhc_imx6ull_data, }, { .compatible = "fsl,imx7d-usdhc", .data = &usdhc_imx7d_data, }, + { .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids); @@ -733,6 +763,14 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, | ESDHC_CLOCK_MASK); sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); + if (imx_data->socdata->flags & ESDHC_FLAG_ERR010450) { + unsigned int max_clock; + + max_clock = imx_data->is_ddr ? 45000000 : 150000000; + + clock = min(clock, max_clock); + } + while (host_clock / (16 * pre_div * ddr_pre_div) > clock && pre_div < 256) pre_div *= 2; @@ -801,6 +839,20 @@ static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) SDHCI_HOST_CONTROL); } +static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) +{ + struct sdhci_host *host = mmc_priv(mmc); + + /* + * i.MX uSDHC internally already uses a fixed optimized timing for + * DDR50, normally does not require tuning for DDR50 mode. + */ + if (host->timing == MMC_TIMING_UHS_DDR50) + return 0; + + return sdhci_execute_tuning(mmc, opcode); +} + static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) { u32 reg; @@ -864,6 +916,19 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode) return ret; } +static void esdhc_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + u32 m; + + m = readl(host->ioaddr + ESDHC_MIX_CTRL); + if (ios->enhanced_strobe) + m |= ESDHC_MIX_CTRL_HS400_ES_EN; + else + m &= ~ESDHC_MIX_CTRL_HS400_ES_EN; + writel(m, host->ioaddr + ESDHC_MIX_CTRL); +} + static int esdhc_change_pinstate(struct sdhci_host *host, unsigned int uhs) { @@ -905,39 +970,35 @@ static int esdhc_change_pinstate(struct sdhci_host *host, * edge of data_strobe line. Due to the time delay between CLK line and * data_strobe line, if the delay time is larger than one clock cycle, * then CLK and data_strobe line will be misaligned, read error shows up. - * So when the CLK is higher than 100MHz, each clock cycle is short enough, - * host should configure the delay target. */ static void esdhc_set_strobe_dll(struct sdhci_host *host) { u32 v; - if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) { - /* disable clock before enabling strobe dll */ - writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) & - ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, - host->ioaddr + ESDHC_VENDOR_SPEC); + /* disable clock before enabling strobe dll */ + writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) & + ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, + host->ioaddr + ESDHC_VENDOR_SPEC); - /* force a reset on strobe dll */ - writel(ESDHC_STROBE_DLL_CTRL_RESET, - host->ioaddr + ESDHC_STROBE_DLL_CTRL); - /* - * enable strobe dll ctrl and adjust the delay target - * for the uSDHC loopback read clock - */ - v = ESDHC_STROBE_DLL_CTRL_ENABLE | - (7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT); - writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL); - /* wait 1us to make sure strobe dll status register stable */ - udelay(1); - v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS); - if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK)) - dev_warn(mmc_dev(host->mmc), - "warning! HS400 strobe DLL status REF not lock!\n"); - if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK)) - dev_warn(mmc_dev(host->mmc), - "warning! HS400 strobe DLL status SLV not lock!\n"); - } + /* force a reset on strobe dll */ + writel(ESDHC_STROBE_DLL_CTRL_RESET, + host->ioaddr + ESDHC_STROBE_DLL_CTRL); + /* + * enable strobe dll ctrl and adjust the delay target + * for the uSDHC loopback read clock + */ + v = ESDHC_STROBE_DLL_CTRL_ENABLE | + (7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT); + writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL); + /* wait 1us to make sure strobe dll status register stable */ + udelay(1); + v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS); + if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK)) + dev_warn(mmc_dev(host->mmc), + "warning! HS400 strobe DLL status REF not lock!\n"); + if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK)) + dev_warn(mmc_dev(host->mmc), + "warning! HS400 strobe DLL status SLV not lock!\n"); } static void esdhc_reset_tuning(struct sdhci_host *host) @@ -979,6 +1040,7 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) case MMC_TIMING_UHS_SDR25: case MMC_TIMING_UHS_SDR50: case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS: case MMC_TIMING_MMC_HS200: writel(m, host->ioaddr + ESDHC_MIX_CTRL); break; @@ -1042,6 +1104,19 @@ static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) SDHCI_TIMEOUT_CONTROL); } +static u32 esdhc_cqhci_irq(struct sdhci_host *host, u32 intmask) +{ + int cmd_error = 0; + int data_error = 0; + + if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) + return intmask; + + cqhci_irq(host->mmc, intmask, cmd_error, data_error); + + return 0; +} + static struct sdhci_ops sdhci_esdhc_ops = { .read_l = esdhc_readl_le, .read_w = esdhc_readw_le, @@ -1058,6 +1133,7 @@ static struct sdhci_ops sdhci_esdhc_ops = { .set_bus_width = esdhc_pltfm_set_bus_width, .set_uhs_signaling = esdhc_set_uhs_signaling, .reset = esdhc_reset, + .irq = esdhc_cqhci_irq, }; static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { @@ -1095,16 +1171,34 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host) writel(readl(host->ioaddr + SDHCI_HOST_CONTROL) | ESDHC_BURST_LEN_EN_INCR, host->ioaddr + SDHCI_HOST_CONTROL); + /* - * erratum ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL - * TO1.1, it's harmless for MX6SL - */ - writel(readl(host->ioaddr + 0x6c) | BIT(7), + * erratum ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL + * TO1.1, it's harmless for MX6SL + */ + writel(readl(host->ioaddr + 0x6c) & ~BIT(7), host->ioaddr + 0x6c); /* disable DLL_CTRL delay line settings */ writel(0x0, host->ioaddr + ESDHC_DLL_CTRL); + /* + * For the case of command with busy, if set the bit + * ESDHC_VEND_SPEC2_EN_BUSY_IRQ, USDHC will generate a + * transfer complete interrupt when busy is deasserted. + * When CQHCI use DCMD to send a CMD need R1b respons, + * CQHCI require to set ESDHC_VEND_SPEC2_EN_BUSY_IRQ, + * otherwise DCMD will always meet timeout waiting for + * hardware interrupt issue. + */ + if (imx_data->socdata->flags & ESDHC_FLAG_CQHCI) { + tmp = readl(host->ioaddr + ESDHC_VEND_SPEC2); + tmp |= ESDHC_VEND_SPEC2_EN_BUSY_IRQ; + writel(tmp, host->ioaddr + ESDHC_VEND_SPEC2); + + host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; + } + if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL); tmp |= ESDHC_STD_TUNING_EN | @@ -1120,10 +1214,81 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host) << ESDHC_TUNING_STEP_SHIFT; } writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL); + } else if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { + /* + * ESDHC_STD_TUNING_EN may be configed in bootloader + * or ROM code, so clear this bit here to make sure + * the manual tuning can work. + */ + tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL); + tmp &= ~ESDHC_STD_TUNING_EN; + writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL); } } } +static void esdhc_cqe_enable(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct cqhci_host *cq_host = mmc->cqe_private; + u32 reg; + u16 mode; + int count = 10; + + /* + * CQE gets stuck if it sees Buffer Read Enable bit set, which can be + * the case after tuning, so ensure the buffer is drained. + */ + reg = sdhci_readl(host, SDHCI_PRESENT_STATE); + while (reg & SDHCI_DATA_AVAILABLE) { + sdhci_readl(host, SDHCI_BUFFER); + reg = sdhci_readl(host, SDHCI_PRESENT_STATE); + if (count-- == 0) { + dev_warn(mmc_dev(host->mmc), + "CQE may get stuck because the Buffer Read Enable bit is set\n"); + break; + } + mdelay(1); + } + + /* + * Runtime resume will reset the entire host controller, which + * will also clear the DMAEN/BCEN of register ESDHC_MIX_CTRL. + * Here set DMAEN and BCEN when enable CMDQ. + */ + mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); + if (host->flags & SDHCI_REQ_USE_DMA) + mode |= SDHCI_TRNS_DMA; + if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE)) + mode |= SDHCI_TRNS_BLK_CNT_EN; + sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); + + /* + * Though Runtime resume reset the entire host controller, + * but do not impact the CQHCI side, need to clear the + * HALT bit, avoid CQHCI stuck in the first request when + * system resume back. + */ + cqhci_writel(cq_host, 0, CQHCI_CTL); + if (cqhci_readl(cq_host, CQHCI_CTL) && CQHCI_HALT) + dev_err(mmc_dev(host->mmc), + "failed to exit halt state when enable CQE\n"); + + + sdhci_cqe_enable(mmc); +} + +static void esdhc_sdhci_dumpregs(struct mmc_host *mmc) +{ + sdhci_dumpregs(mmc_priv(mmc)); +} + +static const struct cqhci_host_ops esdhc_cqhci_ops = { + .enable = esdhc_cqe_enable, + .disable = sdhci_cqe_disable, + .dumpregs = esdhc_sdhci_dumpregs, +}; + #ifdef CONFIG_OF static int sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, @@ -1200,7 +1365,7 @@ static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev, host->mmc->parent->platform_data); /* write_protect */ if (boarddata->wp_type == ESDHC_WP_GPIO) { - err = mmc_gpiod_request_ro(host->mmc, "wp", 0, false, 0, NULL); + err = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0, NULL); if (err) { dev_err(mmc_dev(host->mmc), "failed to request write-protect gpio!\n"); @@ -1255,6 +1420,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) of_match_device(imx_esdhc_dt_ids, &pdev->dev); struct sdhci_pltfm_host *pltfm_host; struct sdhci_host *host; + struct cqhci_host *cq_host; int err; struct pltfm_imx_data *imx_data; @@ -1321,6 +1487,12 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) writel(0x0, host->ioaddr + ESDHC_MIX_CTRL); writel(0x0, host->ioaddr + SDHCI_AUTO_CMD_STATUS); writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); + + /* + * Link usdhc specific mmc_host_ops execute_tuning function, + * to replace the standard one in sdhci_ops. + */ + host->mmc_host_ops.execute_tuning = usdhc_execute_tuning; } if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) @@ -1333,6 +1505,28 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) if (imx_data->socdata->flags & ESDHC_FLAG_HS400) host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400; + if (imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) { + host->mmc->caps2 |= MMC_CAP2_HS400_ES; + host->mmc_host_ops.hs400_enhanced_strobe = + esdhc_hs400_enhanced_strobe; + } + + if (imx_data->socdata->flags & ESDHC_FLAG_CQHCI) { + host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; + cq_host = devm_kzalloc(&pdev->dev, sizeof(*cq_host), GFP_KERNEL); + if (!cq_host) { + err = -ENOMEM; + goto disable_ahb_clk; + } + + cq_host->mmio = host->ioaddr + ESDHC_CQHCI_ADDR_OFFSET; + cq_host->ops = &esdhc_cqhci_ops; + + err = cqhci_init(cq_host, host->mmc, false); + if (err) + goto disable_ahb_clk; + } + if (of_id) err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); else @@ -1340,6 +1534,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) if (err) goto disable_ahb_clk; + host->tuning_delay = 1; + sdhci_esdhc_imx_hwinit(host); err = sdhci_add_host(host); @@ -1391,6 +1587,13 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev) static int sdhci_esdhc_suspend(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); + int ret; + + if (host->mmc->caps2 & MMC_CAP2_CQE) { + ret = cqhci_suspend(host->mmc); + if (ret) + return ret; + } if (host->tuning_mode != SDHCI_TUNING_MODE_3) mmc_retune_needed(host->mmc); @@ -1401,11 +1604,19 @@ static int sdhci_esdhc_suspend(struct device *dev) static int sdhci_esdhc_resume(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); + int ret; /* re-initialize hw state in case it's lost in low power mode */ sdhci_esdhc_imx_hwinit(host); - return sdhci_resume_host(host); + ret = sdhci_resume_host(host); + if (ret) + return ret; + + if (host->mmc->caps2 & MMC_CAP2_CQE) + ret = cqhci_resume(host->mmc); + + return ret; } #endif @@ -1417,6 +1628,12 @@ static int sdhci_esdhc_runtime_suspend(struct device *dev) struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); int ret; + if (host->mmc->caps2 & MMC_CAP2_CQE) { + ret = cqhci_suspend(host->mmc); + if (ret) + return ret; + } + ret = sdhci_runtime_suspend_host(host); if (ret) return ret; @@ -1460,7 +1677,10 @@ static int sdhci_esdhc_runtime_resume(struct device *dev) if (err) goto disable_ipg_clk; - return 0; + if (host->mmc->caps2 & MMC_CAP2_CQE) + err = cqhci_resume(host->mmc); + + return err; disable_ipg_clk: if (!sdhci_sdio_irq_enabled(host)) diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c index 0db99057c44f..9d12c06c7fd6 100644 --- a/drivers/mmc/host/sdhci-iproc.c +++ b/drivers/mmc/host/sdhci-iproc.c @@ -296,7 +296,10 @@ static int sdhci_iproc_probe(struct platform_device *pdev) iproc_host->data = iproc_data; - mmc_of_parse(host->mmc); + ret = mmc_of_parse(host->mmc); + if (ret) + goto err; + sdhci_get_property(pdev); host->mmc->caps |= iproc_host->data->mmc_caps; diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index c11c18a9aacb..b1a66ca3821a 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -1097,7 +1097,6 @@ static int sdhci_omap_probe(struct platform_device *pdev) goto err_put_sync; } - host->mmc_host_ops.get_ro = mmc_gpio_get_ro; host->mmc_host_ops.start_signal_voltage_switch = sdhci_omap_start_signal_voltage_switch; host->mmc_host_ops.set_ios = sdhci_omap_set_ios; diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 2a6eba74b94e..99b0fec2836b 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -1257,16 +1257,6 @@ static int jmicron_resume(struct sdhci_pci_chip *chip) } #endif -static const struct sdhci_pci_fixes sdhci_o2 = { - .probe = sdhci_pci_o2_probe, - .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, - .quirks2 = SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD, - .probe_slot = sdhci_pci_o2_probe_slot, -#ifdef CONFIG_PM_SLEEP - .resume = sdhci_pci_o2_resume, -#endif -}; - static const struct sdhci_pci_fixes sdhci_jmicron = { .probe = jmicron_probe, diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c index cc3ffeffd7a2..05a012a694b2 100644 --- a/drivers/mmc/host/sdhci-pci-o2micro.c +++ b/drivers/mmc/host/sdhci-pci-o2micro.c @@ -60,6 +60,13 @@ #define O2_SD_VENDOR_SETTING2 0x1C8 #define O2_SD_HW_TUNING_DISABLE BIT(4) +#define O2_PLL_WDT_CONTROL1 0x1CC +#define O2_PLL_FORCE_ACTIVE BIT(18) +#define O2_PLL_LOCK_STATUS BIT(14) +#define O2_PLL_SOFT_RESET BIT(12) + +#define O2_SD_DETECT_SETTING 0x324 + static void sdhci_o2_set_tuning_mode(struct sdhci_host *host) { u16 reg; @@ -283,6 +290,113 @@ static void sdhci_pci_o2_enable_msi(struct sdhci_pci_chip *chip, host->irq = pci_irq_vector(chip->pdev, 0); } +static void sdhci_o2_wait_card_detect_stable(struct sdhci_host *host) +{ + ktime_t timeout; + u32 scratch32; + + /* Wait max 50 ms */ + timeout = ktime_add_ms(ktime_get(), 50); + while (1) { + bool timedout = ktime_after(ktime_get(), timeout); + + scratch32 = sdhci_readl(host, SDHCI_PRESENT_STATE); + if ((scratch32 & SDHCI_CARD_PRESENT) >> SDHCI_CARD_PRES_SHIFT + == (scratch32 & SDHCI_CD_LVL) >> SDHCI_CD_LVL_SHIFT) + break; + + if (timedout) { + pr_err("%s: Card Detect debounce never finished.\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + return; + } + udelay(10); + } +} + +static void sdhci_o2_enable_internal_clock(struct sdhci_host *host) +{ + ktime_t timeout; + u16 scratch; + u32 scratch32; + + /* PLL software reset */ + scratch32 = sdhci_readl(host, O2_PLL_WDT_CONTROL1); + scratch32 |= O2_PLL_SOFT_RESET; + sdhci_writel(host, scratch32, O2_PLL_WDT_CONTROL1); + udelay(1); + scratch32 &= ~(O2_PLL_SOFT_RESET); + sdhci_writel(host, scratch32, O2_PLL_WDT_CONTROL1); + + /* PLL force active */ + scratch32 |= O2_PLL_FORCE_ACTIVE; + sdhci_writel(host, scratch32, O2_PLL_WDT_CONTROL1); + + /* Wait max 20 ms */ + timeout = ktime_add_ms(ktime_get(), 20); + while (1) { + bool timedout = ktime_after(ktime_get(), timeout); + + scratch = sdhci_readw(host, O2_PLL_WDT_CONTROL1); + if (scratch & O2_PLL_LOCK_STATUS) + break; + if (timedout) { + pr_err("%s: Internal clock never stabilised.\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + goto out; + } + udelay(10); + } + + /* Wait for card detect finish */ + udelay(1); + sdhci_o2_wait_card_detect_stable(host); + +out: + /* Cancel PLL force active */ + scratch32 = sdhci_readl(host, O2_PLL_WDT_CONTROL1); + scratch32 &= ~O2_PLL_FORCE_ACTIVE; + sdhci_writel(host, scratch32, O2_PLL_WDT_CONTROL1); +} + +static int sdhci_o2_get_cd(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + + sdhci_o2_enable_internal_clock(host); + + return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); +} + +static void sdhci_o2_enable_clk(struct sdhci_host *host, u16 clk) +{ + /* Enable internal clock */ + clk |= SDHCI_CLOCK_INT_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + + if (sdhci_o2_get_cd(host->mmc)) { + clk |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + } +} + +void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock) +{ + u16 clk; + + host->mmc->actual_clock = 0; + + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + + if (clock == 0) + return; + + clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); + sdhci_o2_enable_clk(host, clk); +} + int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) { struct sdhci_pci_chip *chip; @@ -314,9 +428,14 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) mmc_hostname(host->mmc)); host->flags &= ~SDHCI_SIGNALING_330; host->flags |= SDHCI_SIGNALING_180; + host->quirks2 |= SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD; host->mmc->caps2 |= MMC_CAP2_NO_SD; host->mmc->caps2 |= MMC_CAP2_NO_SDIO; + pci_write_config_dword(chip->pdev, + O2_SD_DETECT_SETTING, 3); } + + slot->host->mmc_host_ops.get_cd = sdhci_o2_get_cd; } host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning; @@ -490,9 +609,6 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); break; case PCI_DEVICE_ID_O2_SEABIRD0: - if (chip->pdev->revision == 0x01) - chip->quirks |= SDHCI_QUIRK_DELAY_AFTER_POWER; - /* fall through */ case PCI_DEVICE_ID_O2_SEABIRD1: /* UnLock WP */ ret = pci_read_config_byte(chip->pdev, @@ -550,3 +666,21 @@ int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip) return sdhci_pci_resume_host(chip); } #endif + +static const struct sdhci_ops sdhci_pci_o2_ops = { + .set_clock = sdhci_pci_o2_set_clock, + .enable_dma = sdhci_pci_enable_dma, + .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, +}; + +const struct sdhci_pci_fixes sdhci_o2 = { + .probe = sdhci_pci_o2_probe, + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, + .probe_slot = sdhci_pci_o2_probe_slot, +#ifdef CONFIG_PM_SLEEP + .resume = sdhci_pci_o2_resume, +#endif + .ops = &sdhci_pci_o2_ops, +}; diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index 2ef0bdca9197..4ddb69a15cd7 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h @@ -179,13 +179,9 @@ static inline void *sdhci_pci_priv(struct sdhci_pci_slot *slot) int sdhci_pci_resume_host(struct sdhci_pci_chip *chip); #endif int sdhci_pci_enable_dma(struct sdhci_host *host); -int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot); -int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip); -#ifdef CONFIG_PM_SLEEP -int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip); -#endif extern const struct sdhci_pci_fixes sdhci_arasan; extern const struct sdhci_pci_fixes sdhci_snps; +extern const struct sdhci_pci_fixes sdhci_o2; #endif /* __SDHCI_PCI_H */ diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index 2c3827f54927..cdc8e16b4567 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c @@ -23,7 +23,6 @@ #include <linux/clk.h> #include <linux/module.h> #include <linux/io.h> -#include <linux/gpio.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> #include <linux/platform_data/pxa_sdhci.h> diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index e6ace31e2a41..32e62904c0d3 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -33,6 +33,7 @@ #include <linux/ktime.h> #include "sdhci-pltfm.h" +#include "cqhci.h" /* Tegra SDHOST controller vendor register definitions */ #define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100 @@ -75,6 +76,7 @@ #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK 0x0000000f #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL 0x7 #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD BIT(31) +#define SDHCI_COMP_PADCTRL_DRVUPDN_OFFSET_MASK 0x07FFF000 #define SDHCI_TEGRA_AUTO_CAL_STATUS 0x1ec #define SDHCI_TEGRA_AUTO_CAL_ACTIVE BIT(31) @@ -89,6 +91,9 @@ #define NVQUIRK_NEEDS_PAD_CONTROL BIT(7) #define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP BIT(8) +/* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */ +#define SDHCI_TEGRA_CQE_BASE_ADDR 0xF000 + struct sdhci_tegra_soc_data { const struct sdhci_pltfm_data *pdata; u32 nvquirks; @@ -121,6 +126,8 @@ struct sdhci_tegra { struct pinctrl *pinctrl_sdmmc; struct pinctrl_state *pinctrl_state_3v3; struct pinctrl_state *pinctrl_state_1v8; + struct pinctrl_state *pinctrl_state_3v3_drv; + struct pinctrl_state *pinctrl_state_1v8_drv; struct sdhci_tegra_autocal_offsets autocal_offsets; ktime_t last_calib; @@ -128,6 +135,7 @@ struct sdhci_tegra { u32 default_tap; u32 default_trim; u32 dqs_trim; + bool enable_hwcq; }; static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) @@ -237,11 +245,6 @@ static void tegra210_sdhci_writew(struct sdhci_host *host, u16 val, int reg) } } -static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host) -{ - return mmc_gpio_get_ro(host->mmc); -} - static bool tegra_sdhci_is_pad_and_regulator_valid(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -411,6 +414,76 @@ static void tegra_sdhci_set_pad_autocal_offset(struct sdhci_host *host, sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG); } +static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage, + bool state_drvupdn) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); + struct sdhci_tegra_autocal_offsets *offsets = + &tegra_host->autocal_offsets; + struct pinctrl_state *pinctrl_drvupdn = NULL; + int ret = 0; + u8 drvup = 0, drvdn = 0; + u32 reg; + + if (!state_drvupdn) { + /* PADS Drive Strength */ + if (voltage == MMC_SIGNAL_VOLTAGE_180) { + if (tegra_host->pinctrl_state_1v8_drv) { + pinctrl_drvupdn = + tegra_host->pinctrl_state_1v8_drv; + } else { + drvup = offsets->pull_up_1v8_timeout; + drvdn = offsets->pull_down_1v8_timeout; + } + } else { + if (tegra_host->pinctrl_state_3v3_drv) { + pinctrl_drvupdn = + tegra_host->pinctrl_state_3v3_drv; + } else { + drvup = offsets->pull_up_3v3_timeout; + drvdn = offsets->pull_down_3v3_timeout; + } + } + + if (pinctrl_drvupdn != NULL) { + ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc, + pinctrl_drvupdn); + if (ret < 0) + dev_err(mmc_dev(host->mmc), + "failed pads drvupdn, ret: %d\n", ret); + } else if ((drvup) || (drvdn)) { + reg = sdhci_readl(host, + SDHCI_TEGRA_SDMEM_COMP_PADCTRL); + reg &= ~SDHCI_COMP_PADCTRL_DRVUPDN_OFFSET_MASK; + reg |= (drvup << 20) | (drvdn << 12); + sdhci_writel(host, reg, + SDHCI_TEGRA_SDMEM_COMP_PADCTRL); + } + + } else { + /* Dual Voltage PADS Voltage selection */ + if (!tegra_host->pad_control_available) + return 0; + + if (voltage == MMC_SIGNAL_VOLTAGE_180) { + ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc, + tegra_host->pinctrl_state_1v8); + if (ret < 0) + dev_err(mmc_dev(host->mmc), + "setting 1.8V failed, ret: %d\n", ret); + } else { + ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc, + tegra_host->pinctrl_state_3v3); + if (ret < 0) + dev_err(mmc_dev(host->mmc), + "setting 3.3V failed, ret: %d\n", ret); + } + } + + return ret; +} + static void tegra_sdhci_pad_autocalib(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -437,6 +510,7 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host) pdpu = offsets.pull_down_3v3 << 8 | offsets.pull_up_3v3; } + /* Set initial offset before auto-calibration */ tegra_sdhci_set_pad_autocal_offset(host, pdpu); card_clk_enabled = tegra_sdhci_configure_card_clk(host, false); @@ -460,19 +534,15 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host) if (ret) { dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n"); - if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) - pdpu = offsets.pull_down_1v8_timeout << 8 | - offsets.pull_up_1v8_timeout; - else - pdpu = offsets.pull_down_3v3_timeout << 8 | - offsets.pull_up_3v3_timeout; - - /* Disable automatic calibration and use fixed offsets */ + /* Disable automatic cal and use fixed Drive Strengths */ reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG); reg &= ~SDHCI_AUTO_CAL_ENABLE; sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG); - tegra_sdhci_set_pad_autocal_offset(host, pdpu); + ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage, false); + if (ret < 0) + dev_err(mmc_dev(host->mmc), + "Setting drive strengths failed: %d\n", ret); } } @@ -511,26 +581,46 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host) err = device_property_read_u32(host->mmc->parent, "nvidia,pad-autocal-pull-up-offset-3v3-timeout", &autocal->pull_up_3v3_timeout); - if (err) + if (err) { + if (!IS_ERR(tegra_host->pinctrl_state_3v3) && + (tegra_host->pinctrl_state_3v3_drv == NULL)) + pr_warn("%s: Missing autocal timeout 3v3-pad drvs\n", + mmc_hostname(host->mmc)); autocal->pull_up_3v3_timeout = 0; + } err = device_property_read_u32(host->mmc->parent, "nvidia,pad-autocal-pull-down-offset-3v3-timeout", &autocal->pull_down_3v3_timeout); - if (err) + if (err) { + if (!IS_ERR(tegra_host->pinctrl_state_3v3) && + (tegra_host->pinctrl_state_3v3_drv == NULL)) + pr_warn("%s: Missing autocal timeout 3v3-pad drvs\n", + mmc_hostname(host->mmc)); autocal->pull_down_3v3_timeout = 0; + } err = device_property_read_u32(host->mmc->parent, "nvidia,pad-autocal-pull-up-offset-1v8-timeout", &autocal->pull_up_1v8_timeout); - if (err) + if (err) { + if (!IS_ERR(tegra_host->pinctrl_state_1v8) && + (tegra_host->pinctrl_state_1v8_drv == NULL)) + pr_warn("%s: Missing autocal timeout 1v8-pad drvs\n", + mmc_hostname(host->mmc)); autocal->pull_up_1v8_timeout = 0; + } err = device_property_read_u32(host->mmc->parent, "nvidia,pad-autocal-pull-down-offset-1v8-timeout", &autocal->pull_down_1v8_timeout); - if (err) + if (err) { + if (!IS_ERR(tegra_host->pinctrl_state_1v8) && + (tegra_host->pinctrl_state_1v8_drv == NULL)) + pr_warn("%s: Missing autocal timeout 1v8-pad drvs\n", + mmc_hostname(host->mmc)); autocal->pull_down_1v8_timeout = 0; + } err = device_property_read_u32(host->mmc->parent, "nvidia,pad-autocal-pull-up-offset-sdr104", @@ -595,6 +685,20 @@ static void tegra_sdhci_parse_tap_and_trim(struct sdhci_host *host) tegra_host->dqs_trim = 0x11; } +static void tegra_sdhci_parse_dt(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); + + if (device_property_read_bool(host->mmc->parent, "supports-cqe")) + tegra_host->enable_hwcq = true; + else + tegra_host->enable_hwcq = false; + + tegra_sdhci_parse_pad_autocal_dt(host); + tegra_sdhci_parse_tap_and_trim(host); +} + static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -743,32 +847,6 @@ static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) return mmc_send_tuning(host->mmc, opcode, NULL); } -static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage) -{ - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); - int ret; - - if (!tegra_host->pad_control_available) - return 0; - - if (voltage == MMC_SIGNAL_VOLTAGE_180) { - ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc, - tegra_host->pinctrl_state_1v8); - if (ret < 0) - dev_err(mmc_dev(host->mmc), - "setting 1.8V failed, ret: %d\n", ret); - } else { - ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc, - tegra_host->pinctrl_state_3v3); - if (ret < 0) - dev_err(mmc_dev(host->mmc), - "setting 3.3V failed, ret: %d\n", ret); - } - - return ret; -} - static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios) { @@ -778,7 +856,7 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc, int ret = 0; if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { - ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage); + ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage, true); if (ret < 0) return ret; ret = sdhci_start_signal_voltage_switch(mmc, ios); @@ -786,7 +864,7 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc, ret = sdhci_start_signal_voltage_switch(mmc, ios); if (ret < 0) return ret; - ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage); + ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage, true); } if (tegra_host->pad_calib_required) @@ -805,6 +883,20 @@ static int tegra_sdhci_init_pinctrl_info(struct device *dev, return -1; } + tegra_host->pinctrl_state_1v8_drv = pinctrl_lookup_state( + tegra_host->pinctrl_sdmmc, "sdmmc-1v8-drv"); + if (IS_ERR(tegra_host->pinctrl_state_1v8_drv)) { + if (PTR_ERR(tegra_host->pinctrl_state_1v8_drv) == -ENODEV) + tegra_host->pinctrl_state_1v8_drv = NULL; + } + + tegra_host->pinctrl_state_3v3_drv = pinctrl_lookup_state( + tegra_host->pinctrl_sdmmc, "sdmmc-3v3-drv"); + if (IS_ERR(tegra_host->pinctrl_state_3v3_drv)) { + if (PTR_ERR(tegra_host->pinctrl_state_3v3_drv) == -ENODEV) + tegra_host->pinctrl_state_3v3_drv = NULL; + } + tegra_host->pinctrl_state_3v3 = pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-3v3"); if (IS_ERR(tegra_host->pinctrl_state_3v3)) { @@ -836,8 +928,50 @@ static void tegra_sdhci_voltage_switch(struct sdhci_host *host) tegra_host->pad_calib_required = true; } +static void sdhci_tegra_cqe_enable(struct mmc_host *mmc) +{ + struct cqhci_host *cq_host = mmc->cqe_private; + u32 cqcfg = 0; + + /* + * Tegra SDMMC Controller design prevents write access to BLOCK_COUNT + * registers when CQE is enabled. + */ + cqcfg = cqhci_readl(cq_host, CQHCI_CFG); + if (cqcfg & CQHCI_ENABLE) + cqhci_writel(cq_host, (cqcfg & ~CQHCI_ENABLE), CQHCI_CFG); + + sdhci_cqe_enable(mmc); + + if (cqcfg & CQHCI_ENABLE) + cqhci_writel(cq_host, cqcfg, CQHCI_CFG); +} + +static void sdhci_tegra_dumpregs(struct mmc_host *mmc) +{ + sdhci_dumpregs(mmc_priv(mmc)); +} + +static u32 sdhci_tegra_cqhci_irq(struct sdhci_host *host, u32 intmask) +{ + int cmd_error = 0; + int data_error = 0; + + if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) + return intmask; + + cqhci_irq(host->mmc, intmask, cmd_error, data_error); + + return 0; +} + +static const struct cqhci_host_ops sdhci_tegra_cqhci_ops = { + .enable = sdhci_tegra_cqe_enable, + .disable = sdhci_cqe_disable, + .dumpregs = sdhci_tegra_dumpregs, +}; + static const struct sdhci_ops tegra_sdhci_ops = { - .get_ro = tegra_sdhci_get_ro, .read_w = tegra_sdhci_readw, .write_l = tegra_sdhci_writel, .set_clock = tegra_sdhci_set_clock, @@ -893,7 +1027,6 @@ static const struct sdhci_tegra_soc_data soc_data_tegra30 = { }; static const struct sdhci_ops tegra114_sdhci_ops = { - .get_ro = tegra_sdhci_get_ro, .read_w = tegra_sdhci_readw, .write_w = tegra_sdhci_writew, .write_l = tegra_sdhci_writel, @@ -947,7 +1080,6 @@ static const struct sdhci_tegra_soc_data soc_data_tegra124 = { }; static const struct sdhci_ops tegra210_sdhci_ops = { - .get_ro = tegra_sdhci_get_ro, .read_w = tegra_sdhci_readw, .write_w = tegra210_sdhci_writew, .write_l = tegra_sdhci_writel, @@ -980,7 +1112,6 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 = { }; static const struct sdhci_ops tegra186_sdhci_ops = { - .get_ro = tegra_sdhci_get_ro, .read_w = tegra_sdhci_readw, .write_l = tegra_sdhci_writel, .set_clock = tegra_sdhci_set_clock, @@ -989,6 +1120,7 @@ static const struct sdhci_ops tegra186_sdhci_ops = { .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, .voltage_switch = tegra_sdhci_voltage_switch, .get_max_clock = tegra_sdhci_get_max_clock, + .irq = sdhci_tegra_cqhci_irq, }; static const struct sdhci_pltfm_data sdhci_tegra186_pdata = { @@ -1030,6 +1162,54 @@ static const struct of_device_id sdhci_tegra_dt_match[] = { }; MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); +static int sdhci_tegra_add_host(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); + struct cqhci_host *cq_host; + bool dma64; + int ret; + + if (!tegra_host->enable_hwcq) + return sdhci_add_host(host); + + sdhci_enable_v4_mode(host); + + ret = sdhci_setup_host(host); + if (ret) + return ret; + + host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; + + cq_host = devm_kzalloc(host->mmc->parent, + sizeof(*cq_host), GFP_KERNEL); + if (!cq_host) { + ret = -ENOMEM; + goto cleanup; + } + + cq_host->mmio = host->ioaddr + SDHCI_TEGRA_CQE_BASE_ADDR; + cq_host->ops = &sdhci_tegra_cqhci_ops; + + dma64 = host->flags & SDHCI_USE_64_BIT_DMA; + if (dma64) + cq_host->caps |= CQHCI_TASK_DESC_SZ_128; + + ret = cqhci_init(cq_host, host->mmc, dma64); + if (ret) + goto cleanup; + + ret = __sdhci_add_host(host); + if (ret) + goto cleanup; + + return 0; + +cleanup: + sdhci_cleanup_host(host); + return ret; +} + static int sdhci_tegra_probe(struct platform_device *pdev) { const struct of_device_id *match; @@ -1077,9 +1257,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) host->mmc->caps |= MMC_CAP_1_8V_DDR; - tegra_sdhci_parse_pad_autocal_dt(host); - - tegra_sdhci_parse_tap_and_trim(host); + tegra_sdhci_parse_dt(host); tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power", GPIOD_OUT_HIGH); @@ -1117,7 +1295,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) usleep_range(2000, 4000); - rc = sdhci_add_host(host); + rc = sdhci_tegra_add_host(host); if (rc) goto err_add_host; diff --git a/drivers/mmc/host/sdhci-xenon-phy.c b/drivers/mmc/host/sdhci-xenon-phy.c index 5b5eb53a63d2..8d07ee1b8f08 100644 --- a/drivers/mmc/host/sdhci-xenon-phy.c +++ b/drivers/mmc/host/sdhci-xenon-phy.c @@ -530,7 +530,7 @@ static bool xenon_emmc_phy_slow_mode(struct sdhci_host *host, ret = true; break; } - /* else: fall through */ + /* fall through */ default: reg &= ~XENON_TIMING_ADJUST_SLOW_MODE; ret = false; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index a22e11a65658..a8141ff9be03 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -883,7 +883,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd, bool *too_big) { u8 count; - struct mmc_data *data = cmd->data; + struct mmc_data *data; unsigned target_timeout, current_timeout; *too_big = true; @@ -897,6 +897,11 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd, if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) return 0xE; + /* Unspecified command, asume max */ + if (cmd == NULL) + return 0xE; + + data = cmd->data; /* Unspecified timeout, assume max */ if (!data && !cmd->busy_timeout) return 0xE; @@ -2048,6 +2053,8 @@ static int sdhci_check_ro(struct sdhci_host *host) is_readonly = 0; else if (host->ops->get_ro) is_readonly = host->ops->get_ro(host); + else if (mmc_can_gpio_ro(host->mmc)) + is_readonly = mmc_gpio_get_ro(host->mmc); else is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_WRITE_PROTECT); @@ -2376,6 +2383,10 @@ static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) return -ETIMEDOUT; } + /* Spec does not require a delay between tuning cycles */ + if (host->tuning_delay > 0) + mdelay(host->tuning_delay); + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { if (ctrl & SDHCI_CTRL_TUNED_CLK) @@ -2383,9 +2394,6 @@ static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) break; } - /* Spec does not require a delay between tuning cycles */ - if (host->tuning_delay > 0) - mdelay(host->tuning_delay); } pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", @@ -3353,7 +3361,14 @@ void sdhci_cqe_enable(struct mmc_host *mmc) ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); ctrl &= ~SDHCI_CTRL_DMA_MASK; - if (host->flags & SDHCI_USE_64_BIT_DMA) + /* + * Host from V4.10 supports ADMA3 DMA type. + * ADMA3 performs integrated descriptor which is more suitable + * for cmd queuing to fetch both command and transfer descriptors. + */ + if (host->v4_mode && (host->caps1 & SDHCI_CAN_DO_ADMA3)) + ctrl |= SDHCI_CTRL_ADMA3; + else if (host->flags & SDHCI_USE_64_BIT_DMA) ctrl |= SDHCI_CTRL_ADMA64; else ctrl |= SDHCI_CTRL_ADMA32; @@ -3363,7 +3378,7 @@ void sdhci_cqe_enable(struct mmc_host *mmc) SDHCI_BLOCK_SIZE); /* Set maximum timeout */ - sdhci_writeb(host, 0xE, SDHCI_TIMEOUT_CONTROL); + sdhci_set_timeout(host, NULL); host->ier = host->cqe_ier; @@ -3763,8 +3778,9 @@ int sdhci_setup_host(struct sdhci_host *host) * Use zalloc to zero the reserved high 32-bits of 128-bit * descriptors so that they never need to be written. */ - buf = dma_zalloc_coherent(mmc_dev(mmc), host->align_buffer_sz + - host->adma_table_sz, &dma, GFP_KERNEL); + buf = dma_alloc_coherent(mmc_dev(mmc), + host->align_buffer_sz + host->adma_table_sz, + &dma, GFP_KERNEL); if (!buf) { pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n", mmc_hostname(mmc)); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 6cc9a3c2ac66..01002cba1359 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -73,6 +73,10 @@ #define SDHCI_SPACE_AVAILABLE 0x00000400 #define SDHCI_DATA_AVAILABLE 0x00000800 #define SDHCI_CARD_PRESENT 0x00010000 +#define SDHCI_CARD_PRES_SHIFT 16 +#define SDHCI_CD_STABLE 0x00020000 +#define SDHCI_CD_LVL 0x00040000 +#define SDHCI_CD_LVL_SHIFT 18 #define SDHCI_WRITE_PROTECT 0x00080000 #define SDHCI_DATA_LVL_MASK 0x00F00000 #define SDHCI_DATA_LVL_SHIFT 20 @@ -88,6 +92,7 @@ #define SDHCI_CTRL_ADMA1 0x08 #define SDHCI_CTRL_ADMA32 0x10 #define SDHCI_CTRL_ADMA64 0x18 +#define SDHCI_CTRL_ADMA3 0x18 #define SDHCI_CTRL_8BITBUS 0x20 #define SDHCI_CTRL_CDTEST_INS 0x40 #define SDHCI_CTRL_CDTEST_EN 0x80 @@ -230,6 +235,7 @@ #define SDHCI_RETUNING_MODE_SHIFT 14 #define SDHCI_CLOCK_MUL_MASK 0x00FF0000 #define SDHCI_CLOCK_MUL_SHIFT 16 +#define SDHCI_CAN_DO_ADMA3 0x08000000 #define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */ #define SDHCI_CAPABILITIES_1 0x44 diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 8c05879850a0..eea183e90f1b 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -158,7 +158,7 @@ static void sdhci_am654_set_power(struct sdhci_host *host, unsigned char mode, sdhci_set_power_noreg(host, mode, vdd); } -struct sdhci_ops sdhci_am654_ops = { +static struct sdhci_ops sdhci_am654_ops = { .get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_timeout_clock = sdhci_pltfm_clk_get_max_clock, .set_uhs_signaling = sdhci_set_uhs_signaling, diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 279e326e397e..2901a5773d83 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -19,7 +19,6 @@ #include <linux/device.h> #include <linux/dma-mapping.h> #include <linux/err.h> -#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/kernel.h> @@ -32,7 +31,6 @@ #include <linux/mmc/slot-gpio.h> #include <linux/module.h> #include <linux/of_address.h> -#include <linux/of_gpio.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -1399,13 +1397,37 @@ static int sunxi_mmc_probe(struct platform_device *pdev) mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ; - if (host->cfg->clk_delays || host->use_new_timings) + /* + * Some H5 devices do not have signal traces precise enough to + * use HS DDR mode for their eMMC chips. + * + * We still enable HS DDR modes for all the other controller + * variants that support them. + */ + if ((host->cfg->clk_delays || host->use_new_timings) && + !of_device_is_compatible(pdev->dev.of_node, + "allwinner,sun50i-h5-emmc")) mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR; ret = mmc_of_parse(mmc); if (ret) goto error_free_dma; + /* + * If we don't support delay chains in the SoC, we can't use any + * of the higher speed modes. Mask them out in case the device + * tree specifies the properties for them, which gets added to + * the caps by mmc_of_parse() above. + */ + if (!(host->cfg->clk_delays || host->use_new_timings)) { + mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR | + MMC_CAP_1_2V_DDR | MMC_CAP_UHS); + mmc->caps2 &= ~MMC_CAP2_HS200; + } + + /* TODO: This driver doesn't support HS400 mode yet */ + mmc->caps2 &= ~MMC_CAP2_HS400; + ret = sunxi_mmc_init_host(host); if (ret) goto error_free_dma; diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index c03529e3f01a..2adb0d24360f 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -277,6 +277,11 @@ static inline void sd_ctrl_write32_as_16_and_16(struct tmio_mmc_host *host, iowrite16(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); } +static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val) +{ + iowrite32(val, host->ctl + (addr << host->bus_shift)); +} + static inline void sd_ctrl_write32_rep(struct tmio_mmc_host *host, int addr, const u32 *buf, int count) { diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 085a0fab769c..595949f1f001 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -43,6 +43,7 @@ #include <linux/regulator/consumer.h> #include <linux/mmc/sdio.h> #include <linux/scatterlist.h> +#include <linux/sizes.h> #include <linux/spinlock.h> #include <linux/swiotlb.h> #include <linux/workqueue.h> @@ -629,7 +630,7 @@ static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host, int ireg, return false; } -static void __tmio_mmc_sdio_irq(struct tmio_mmc_host *host) +static bool __tmio_mmc_sdio_irq(struct tmio_mmc_host *host) { struct mmc_host *mmc = host->mmc; struct tmio_mmc_data *pdata = host->pdata; @@ -637,7 +638,7 @@ static void __tmio_mmc_sdio_irq(struct tmio_mmc_host *host) unsigned int sdio_status; if (!(pdata->flags & TMIO_MMC_SDIO_IRQ)) - return; + return false; status = sd_ctrl_read16(host, CTL_SDIO_STATUS); ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdio_irq_mask; @@ -650,6 +651,8 @@ static void __tmio_mmc_sdio_irq(struct tmio_mmc_host *host) if (mmc->caps & MMC_CAP_SDIO_IRQ && ireg & TMIO_SDIO_STAT_IOIRQ) mmc_signal_sdio_irq(mmc); + + return ireg; } irqreturn_t tmio_mmc_irq(int irq, void *devid) @@ -668,9 +671,10 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) if (__tmio_mmc_sdcard_irq(host, ireg, status)) return IRQ_HANDLED; - __tmio_mmc_sdio_irq(host); + if (__tmio_mmc_sdio_irq(host)) + return IRQ_HANDLED; - return IRQ_HANDLED; + return IRQ_NONE; } EXPORT_SYMBOL_GPL(tmio_mmc_irq); @@ -700,7 +704,10 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host, /* Set transfer length / blocksize */ sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz); - sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks); + if (host->mmc->max_blk_count >= SZ_64K) + sd_ctrl_write32(host, CTL_XFER_BLK_COUNT, data->blocks); + else + sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks); tmio_mmc_start_dma(host, data); @@ -1066,7 +1073,7 @@ static int tmio_mmc_init_ocr(struct tmio_mmc_host *host) /* use ocr_mask if no regulator */ if (!mmc->ocr_avail) - mmc->ocr_avail = pdata->ocr_mask; + mmc->ocr_avail = pdata->ocr_mask; /* * try again. @@ -1287,6 +1294,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) cancel_delayed_work_sync(&host->delayed_reset_work); tmio_mmc_release_dma(host); + pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); } diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c index 3ba42f508014..4fd6da29489e 100644 --- a/drivers/mmc/host/wmt-sdmmc.c +++ b/drivers/mmc/host/wmt-sdmmc.c @@ -19,7 +19,6 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/clk.h> -#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/of.h> diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 6e8e7b1bb34b..79a53cb8507b 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -756,7 +756,8 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, } numvirtchips = cfi->numchips * numparts; - newcfi = kmalloc(sizeof(struct cfi_private) + numvirtchips * sizeof(struct flchip), GFP_KERNEL); + newcfi = kmalloc(struct_size(newcfi, chips, numvirtchips), + GFP_KERNEL); if (!newcfi) return -ENOMEM; shared = kmalloc_array(cfi->numchips, diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index 837b04ab96a9..839ed40625d6 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c @@ -135,7 +135,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi * our caller, and copy the appropriate data into them. */ - retcfi = kmalloc(sizeof(struct cfi_private) + cfi.numchips * sizeof(struct flchip), GFP_KERNEL); + retcfi = kmalloc(struct_size(retcfi, chips, cfi.numchips), GFP_KERNEL); if (!retcfi) { kfree(cfi.cfiq); diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index 4c94fc096696..7754803e3463 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c @@ -1767,8 +1767,8 @@ static int __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) switch (chip_id) { case DOC_CHIPID_G3: - mtd->name = kasprintf(GFP_KERNEL, "docg3.%d", - docg3->device_id); + mtd->name = devm_kasprintf(docg3->dev, GFP_KERNEL, "docg3.%d", + docg3->device_id); if (!mtd->name) return -ENOMEM; docg3->max_block = 2047; @@ -1872,7 +1872,7 @@ nomem3: nomem2: kfree(docg3); nomem1: - return ERR_PTR(ret); + return ret ? ERR_PTR(ret) : NULL; } /** @@ -1886,7 +1886,6 @@ static void doc_release_device(struct mtd_info *mtd) mtd_device_unregister(mtd); kfree(docg3->bbt); kfree(docg3); - kfree(mtd->name); kfree(mtd); } diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index c4a1d04b8c80..651bab6d4e31 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -195,7 +195,14 @@ static int m25p_probe(struct spi_mem *spimem) spi_mem_set_drvdata(spimem, flash); flash->spimem = spimem; - if (spi->mode & SPI_RX_QUAD) { + if (spi->mode & SPI_RX_OCTAL) { + hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8; + + if (spi->mode & SPI_TX_OCTAL) + hwcaps.mask |= (SNOR_HWCAPS_READ_1_8_8 | + SNOR_HWCAPS_PP_1_1_8 | + SNOR_HWCAPS_PP_1_8_8); + } else if (spi->mode & SPI_RX_QUAD) { hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; if (spi->mode & SPI_TX_QUAD) diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index 46238796145f..1c97fabc4bf9 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c @@ -24,14 +24,12 @@ static unsigned long writebuf_size = 64; #define MTDRAM_TOTAL_SIZE (total_size * 1024) #define MTDRAM_ERASE_SIZE (erase_size * 1024) -#ifdef MODULE module_param(total_size, ulong, 0); MODULE_PARM_DESC(total_size, "Total device size in KiB"); module_param(erase_size, ulong, 0); MODULE_PARM_DESC(erase_size, "Device erase block size in KiB"); module_param(writebuf_size, ulong, 0); MODULE_PARM_DESC(writebuf_size, "Device write buf size in Bytes (Default: 64)"); -#endif // We could store these in the mtd structure, but we only support 1 device.. static struct mtd_info *mtd_info; diff --git a/drivers/mtd/devices/powernv_flash.c b/drivers/mtd/devices/powernv_flash.c index 22f753e555ac..83f88b8b5d9f 100644 --- a/drivers/mtd/devices/powernv_flash.c +++ b/drivers/mtd/devices/powernv_flash.c @@ -212,7 +212,7 @@ static int powernv_flash_set_driver_info(struct device *dev, * Going to have to check what details I need to set and how to * get them */ - mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node); + mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node); mtd->type = MTD_NORFLASH; mtd->flags = MTD_WRITEABLE; mtd->size = size; diff --git a/drivers/mtd/lpddr/qinfo_probe.c b/drivers/mtd/lpddr/qinfo_probe.c index 69f2112340b1..175bdc3b72f4 100644 --- a/drivers/mtd/lpddr/qinfo_probe.c +++ b/drivers/mtd/lpddr/qinfo_probe.c @@ -181,8 +181,8 @@ static struct lpddr_private *lpddr_probe_chip(struct map_info *map) lpddr.numchips = 1; numvirtchips = lpddr.numchips * lpddr.qinfo->HWPartsNum; - retlpddr = kzalloc(sizeof(struct lpddr_private) + - numvirtchips * sizeof(struct flchip), GFP_KERNEL); + retlpddr = kzalloc(struct_size(retlpddr, chips, numvirtchips), + GFP_KERNEL); if (!retlpddr) return NULL; diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 21e3cdc04036..76b4264936ff 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -155,7 +155,6 @@ static ssize_t mtd_flags_show(struct device *dev, struct mtd_info *mtd = dev_get_drvdata(dev); return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags); - } static DEVICE_ATTR(flags, S_IRUGO, mtd_flags_show, NULL); @@ -166,7 +165,6 @@ static ssize_t mtd_size_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%llu\n", (unsigned long long)mtd->size); - } static DEVICE_ATTR(size, S_IRUGO, mtd_size_show, NULL); @@ -176,7 +174,6 @@ static ssize_t mtd_erasesize_show(struct device *dev, struct mtd_info *mtd = dev_get_drvdata(dev); return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize); - } static DEVICE_ATTR(erasesize, S_IRUGO, mtd_erasesize_show, NULL); @@ -186,7 +183,6 @@ static ssize_t mtd_writesize_show(struct device *dev, struct mtd_info *mtd = dev_get_drvdata(dev); return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize); - } static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL); @@ -197,7 +193,6 @@ static ssize_t mtd_subpagesize_show(struct device *dev, unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft; return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize); - } static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL); @@ -207,7 +202,6 @@ static ssize_t mtd_oobsize_show(struct device *dev, struct mtd_info *mtd = dev_get_drvdata(dev); return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->oobsize); - } static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL); @@ -226,7 +220,6 @@ static ssize_t mtd_numeraseregions_show(struct device *dev, struct mtd_info *mtd = dev_get_drvdata(dev); return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions); - } static DEVICE_ATTR(numeraseregions, S_IRUGO, mtd_numeraseregions_show, NULL); @@ -237,7 +230,6 @@ static ssize_t mtd_name_show(struct device *dev, struct mtd_info *mtd = dev_get_drvdata(dev); return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name); - } static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); @@ -507,6 +499,7 @@ static int mtd_nvmem_add(struct mtd_info *mtd) { struct nvmem_config config = {}; + config.id = -1; config.dev = &mtd->dev; config.name = mtd->name; config.owner = THIS_MODULE; @@ -522,7 +515,7 @@ static int mtd_nvmem_add(struct mtd_info *mtd) mtd->nvmem = nvmem_register(&config); if (IS_ERR(mtd->nvmem)) { /* Just ignore if there is no NVMEM support in the kernel */ - if (PTR_ERR(mtd->nvmem) == -ENOSYS) { + if (PTR_ERR(mtd->nvmem) == -EOPNOTSUPP) { mtd->nvmem = NULL; } else { dev_err(&mtd->dev, "Failed to register NVMEM device\n"); @@ -559,6 +552,14 @@ int add_mtd_device(struct mtd_info *mtd) BUG_ON(mtd->writesize == 0); + /* + * MTD drivers should implement ->_{write,read}() or + * ->_{write,read}_oob(), but not both. + */ + if (WARN_ON((mtd->_write && mtd->_write_oob) || + (mtd->_read && mtd->_read_oob))) + return -EINVAL; + if (WARN_ON((!mtd->erasesize || !mtd->_erase) && !(mtd->flags & MTD_NO_ERASE))) return -EINVAL; @@ -1089,67 +1090,32 @@ EXPORT_SYMBOL_GPL(mtd_get_unmapped_area); int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - int ret_code; - *retlen = 0; - if (from < 0 || from >= mtd->size || len > mtd->size - from) - return -EINVAL; - if (!len) - return 0; + struct mtd_oob_ops ops = { + .len = len, + .datbuf = buf, + }; + int ret; - ledtrig_mtd_activity(); - /* - * In the absence of an error, drivers return a non-negative integer - * representing the maximum number of bitflips that were corrected on - * any one ecc region (if applicable; zero otherwise). - */ - if (mtd->_read) { - ret_code = mtd->_read(mtd, from, len, retlen, buf); - } else if (mtd->_read_oob) { - struct mtd_oob_ops ops = { - .len = len, - .datbuf = buf, - }; - - ret_code = mtd->_read_oob(mtd, from, &ops); - *retlen = ops.retlen; - } else { - return -ENOTSUPP; - } + ret = mtd_read_oob(mtd, from, &ops); + *retlen = ops.retlen; - if (unlikely(ret_code < 0)) - return ret_code; - if (mtd->ecc_strength == 0) - return 0; /* device lacks ecc */ - return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0; + return ret; } EXPORT_SYMBOL_GPL(mtd_read); int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { - *retlen = 0; - if (to < 0 || to >= mtd->size || len > mtd->size - to) - return -EINVAL; - if ((!mtd->_write && !mtd->_write_oob) || - !(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - if (!len) - return 0; - ledtrig_mtd_activity(); + struct mtd_oob_ops ops = { + .len = len, + .datbuf = (u8 *)buf, + }; + int ret; - if (!mtd->_write) { - struct mtd_oob_ops ops = { - .len = len, - .datbuf = (u8 *)buf, - }; - int ret; + ret = mtd_write_oob(mtd, to, &ops); + *retlen = ops.retlen; - ret = mtd->_write_oob(mtd, to, &ops); - *retlen = ops.retlen; - return ret; - } - - return mtd->_write(mtd, to, len, retlen, buf); + return ret; } EXPORT_SYMBOL_GPL(mtd_write); diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h index 9887bda317cd..b31c868019ad 100644 --- a/drivers/mtd/mtdcore.h +++ b/drivers/mtd/mtdcore.h @@ -7,7 +7,7 @@ extern struct mutex mtd_table_mutex; struct mtd_info *__mtd_next_device(int i); -int add_mtd_device(struct mtd_info *mtd); +int __must_check add_mtd_device(struct mtd_info *mtd); int del_mtd_device(struct mtd_info *mtd); int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); int del_mtd_partitions(struct mtd_info *); diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index b6af41b04622..37f174ccbcec 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -480,6 +480,10 @@ static struct mtd_part *allocate_partition(struct mtd_info *parent, /* let's register it anyway to preserve ordering */ slave->offset = 0; slave->mtd.size = 0; + + /* Initialize ->erasesize to make add_mtd_device() happy. */ + slave->mtd.erasesize = parent->erasesize; + printk(KERN_ERR"mtd: partition \"%s\" is out of reach -- disabled\n", part->name); goto out_register; @@ -618,10 +622,21 @@ int mtd_add_partition(struct mtd_info *parent, const char *name, list_add(&new->list, &mtd_partitions); mutex_unlock(&mtd_partitions_mutex); - add_mtd_device(&new->mtd); + ret = add_mtd_device(&new->mtd); + if (ret) + goto err_remove_part; mtd_add_partition_attrs(new); + return 0; + +err_remove_part: + mutex_lock(&mtd_partitions_mutex); + list_del(&new->list); + mutex_unlock(&mtd_partitions_mutex); + + free_partition(new); + return ret; } EXPORT_SYMBOL_GPL(mtd_add_partition); @@ -712,22 +727,31 @@ int add_mtd_partitions(struct mtd_info *master, { struct mtd_part *slave; uint64_t cur_offset = 0; - int i; + int i, ret; printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); for (i = 0; i < nbparts; i++) { slave = allocate_partition(master, parts + i, i, cur_offset); if (IS_ERR(slave)) { - del_mtd_partitions(master); - return PTR_ERR(slave); + ret = PTR_ERR(slave); + goto err_del_partitions; } mutex_lock(&mtd_partitions_mutex); list_add(&slave->list, &mtd_partitions); mutex_unlock(&mtd_partitions_mutex); - add_mtd_device(&slave->mtd); + ret = add_mtd_device(&slave->mtd); + if (ret) { + mutex_lock(&mtd_partitions_mutex); + list_del(&slave->list); + mutex_unlock(&mtd_partitions_mutex); + + free_partition(slave); + goto err_del_partitions; + } + mtd_add_partition_attrs(slave); /* Look for subpartitions */ parse_mtd_partitions(&slave->mtd, parts[i].types, NULL); @@ -736,6 +760,11 @@ int add_mtd_partitions(struct mtd_info *master, } return 0; + +err_del_partitions: + del_mtd_partitions(master); + + return ret; } static DEFINE_SPINLOCK(part_parser_lock); diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 1a55d3e3d4c5..e604625e2dfa 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -541,4 +541,21 @@ config MTD_NAND_TEGRA is supported. Extra OOB bytes when using HW ECC are currently not supported. +config MTD_NAND_STM32_FMC2 + tristate "Support for NAND controller on STM32MP SoCs" + depends on MACH_STM32MP157 || COMPILE_TEST + help + Enables support for NAND Flash chips on SoCs containing the FMC2 + NAND controller. This controller is found on STM32MP SoCs. + The controller supports a maximum 8k page size and supports + a maximum 8-bit correction error per sector of 512 bytes. + +config MTD_NAND_MESON + tristate "Support for NAND controller on Amlogic's Meson SoCs" + depends on ARCH_MESON || COMPILE_TEST + select MFD_SYSCON + help + Enables support for NAND controller on Amlogic's Meson SoCs. + This controller is found on Meson SoCs. + endif # MTD_NAND diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index 57159b349054..5a5a72f0793e 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -56,6 +56,8 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o +obj-$(CONFIG_MTD_NAND_STM32_FMC2) += stm32_fmc2_nand.o +obj-$(CONFIG_MTD_NAND_MESON) += meson_nand.o nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_onfi.o diff --git a/drivers/mtd/nand/raw/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c index 555a74e15269..9d3997840889 100644 --- a/drivers/mtd/nand/raw/atmel/pmecc.c +++ b/drivers/mtd/nand/raw/atmel/pmecc.c @@ -876,23 +876,32 @@ static struct atmel_pmecc *atmel_pmecc_get_by_node(struct device *userdev, { struct platform_device *pdev; struct atmel_pmecc *pmecc, **ptr; + int ret; pdev = of_find_device_by_node(np); - if (!pdev || !platform_get_drvdata(pdev)) + if (!pdev) return ERR_PTR(-EPROBE_DEFER); + pmecc = platform_get_drvdata(pdev); + if (!pmecc) { + ret = -EPROBE_DEFER; + goto err_put_device; + } ptr = devres_alloc(devm_atmel_pmecc_put, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); - - get_device(&pdev->dev); - pmecc = platform_get_drvdata(pdev); + if (!ptr) { + ret = -ENOMEM; + goto err_put_device; + } *ptr = pmecc; devres_add(userdev, ptr); return pmecc; + +err_put_device: + put_device(&pdev->dev); + return ERR_PTR(ret); } static const int atmel_pmecc_strengths[] = { 2, 4, 8, 12, 24, 32 }; diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index eebac35304c6..24aeafc67cd4 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -37,9 +37,6 @@ #define DENALI_MAP11_ADDR ((DENALI_MAP11) | 1) /* address cycle */ #define DENALI_MAP11_DATA ((DENALI_MAP11) | 2) /* data cycle */ -/* MAP10 commands */ -#define DENALI_ERASE 0x01 - #define DENALI_BANK(denali) ((denali)->active_bank << 24) #define DENALI_INVALID_BANK -1 @@ -476,7 +473,7 @@ static void denali_setup_dma32(struct denali_nand_info *denali, } static int denali_pio_read(struct denali_nand_info *denali, void *buf, - size_t size, int page, int raw) + size_t size, int page) { u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; uint32_t *buf32 = (uint32_t *)buf; @@ -504,7 +501,7 @@ static int denali_pio_read(struct denali_nand_info *denali, void *buf, } static int denali_pio_write(struct denali_nand_info *denali, - const void *buf, size_t size, int page, int raw) + const void *buf, size_t size, int page) { u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; const uint32_t *buf32 = (uint32_t *)buf; @@ -525,16 +522,16 @@ static int denali_pio_write(struct denali_nand_info *denali, } static int denali_pio_xfer(struct denali_nand_info *denali, void *buf, - size_t size, int page, int raw, int write) + size_t size, int page, int write) { if (write) - return denali_pio_write(denali, buf, size, page, raw); + return denali_pio_write(denali, buf, size, page); else - return denali_pio_read(denali, buf, size, page, raw); + return denali_pio_read(denali, buf, size, page); } static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, - size_t size, int page, int raw, int write) + size_t size, int page, int write) { dma_addr_t dma_addr; uint32_t irq_mask, irq_status, ecc_err_mask; @@ -544,7 +541,7 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, dma_addr = dma_map_single(denali->dev, buf, size, dir); if (dma_mapping_error(denali->dev, dma_addr)) { dev_dbg(denali->dev, "Failed to DMA-map buffer. Trying PIO.\n"); - return denali_pio_xfer(denali, buf, size, page, raw, write); + return denali_pio_xfer(denali, buf, size, page, write); } if (write) { @@ -598,9 +595,9 @@ static int denali_data_xfer(struct denali_nand_info *denali, void *buf, denali->reg + TRANSFER_SPARE_REG); if (denali->dma_avail) - return denali_dma_xfer(denali, buf, size, page, raw, write); + return denali_dma_xfer(denali, buf, size, page, write); else - return denali_pio_xfer(denali, buf, size, page, raw, write); + return denali_pio_xfer(denali, buf, size, page, write); } static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip, @@ -754,9 +751,6 @@ static int denali_read_oob(struct nand_chip *chip, int page) static int denali_write_oob(struct nand_chip *chip, int page) { struct mtd_info *mtd = nand_to_mtd(chip); - struct denali_nand_info *denali = mtd_to_denali(mtd); - - denali_reset_irq(denali); denali_oob_xfer(mtd, chip, page, 1); @@ -903,23 +897,6 @@ static int denali_waitfunc(struct nand_chip *chip) return irq_status & INTR__INT_ACT ? 0 : NAND_STATUS_FAIL; } -static int denali_erase(struct nand_chip *chip, int page) -{ - struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); - uint32_t irq_status; - - denali_reset_irq(denali); - - denali->host_write(denali, DENALI_MAP10 | DENALI_BANK(denali) | page, - DENALI_ERASE); - - /* wait for erase to complete or failure to occur */ - irq_status = denali_wait_for_irq(denali, - INTR__ERASE_COMP | INTR__ERASE_FAIL); - - return irq_status & INTR__ERASE_COMP ? 0 : -EIO; -} - static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, const struct nand_data_interface *conf) { @@ -1244,7 +1221,6 @@ static int denali_attach_chip(struct nand_chip *chip) chip->ecc.write_page_raw = denali_write_page_raw; chip->ecc.read_oob = denali_read_oob; chip->ecc.write_oob = denali_write_oob; - chip->legacy.erase = denali_erase; ret = denali_multidev_fixup(denali); if (ret) @@ -1322,7 +1298,7 @@ int denali_init(struct denali_nand_info *denali) } /* clk rate info is needed for setup_data_interface */ - if (denali->clk_rate && denali->clk_x_rate) + if (!denali->clk_rate || !denali->clk_x_rate) chip->options |= NAND_KEEP_TIMINGS; chip->legacy.dummy_controller.ops = &denali_controller_ops; diff --git a/drivers/mtd/nand/raw/denali.h b/drivers/mtd/nand/raw/denali.h index 25c00601b8b3..c8c2620fc736 100644 --- a/drivers/mtd/nand/raw/denali.h +++ b/drivers/mtd/nand/raw/denali.h @@ -304,7 +304,6 @@ struct denali_nand_info { u32 irq_status; /* interrupts that have happened */ int irq; void *buf; /* for syndrome layout conversion */ - dma_addr_t dma_addr; int dma_avail; /* can support DMA? */ int devs_per_cs; /* devices connected in parallel */ int oob_skip_bytes; /* number of bytes reserved for BBM */ diff --git a/drivers/mtd/nand/raw/denali_dt.c b/drivers/mtd/nand/raw/denali_dt.c index 7c6a8a426606..0b5ae2418815 100644 --- a/drivers/mtd/nand/raw/denali_dt.c +++ b/drivers/mtd/nand/raw/denali_dt.c @@ -109,25 +109,17 @@ static int denali_dt_probe(struct platform_device *pdev) if (IS_ERR(denali->host)) return PTR_ERR(denali->host); - /* - * A single anonymous clock is supported for the backward compatibility. - * New platforms should support all the named clocks. - */ dt->clk = devm_clk_get(dev, "nand"); if (IS_ERR(dt->clk)) - dt->clk = devm_clk_get(dev, NULL); - if (IS_ERR(dt->clk)) { - dev_err(dev, "no clk available\n"); return PTR_ERR(dt->clk); - } dt->clk_x = devm_clk_get(dev, "nand_x"); if (IS_ERR(dt->clk_x)) - dt->clk_x = NULL; + return PTR_ERR(dt->clk_x); dt->clk_ecc = devm_clk_get(dev, "ecc"); if (IS_ERR(dt->clk_ecc)) - dt->clk_ecc = NULL; + return PTR_ERR(dt->clk_ecc); ret = clk_prepare_enable(dt->clk); if (ret) @@ -141,19 +133,8 @@ static int denali_dt_probe(struct platform_device *pdev) if (ret) goto out_disable_clk_x; - if (dt->clk_x) { - denali->clk_rate = clk_get_rate(dt->clk); - denali->clk_x_rate = clk_get_rate(dt->clk_x); - } else { - /* - * Hardcode the clock rates for the backward compatibility. - * This works for both SOCFPGA and UniPhier. - */ - dev_notice(dev, - "necessary clock is missing. default clock rates are used.\n"); - denali->clk_rate = 50000000; - denali->clk_x_rate = 200000000; - } + denali->clk_rate = clk_get_rate(dt->clk); + denali->clk_x_rate = clk_get_rate(dt->clk_x); ret = denali_init(denali); if (ret) diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index 325b4414dccc..6c7ca41354be 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -593,23 +593,6 @@ static void fsmc_write_buf_dma(struct fsmc_nand_data *host, const u8 *buf, dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE); } -/* fsmc_select_chip - assert or deassert nCE */ -static void fsmc_ce_ctrl(struct fsmc_nand_data *host, bool assert) -{ - u32 pc = readl(host->regs_va + FSMC_PC); - - if (!assert) - writel_relaxed(pc & ~FSMC_ENABLE, host->regs_va + FSMC_PC); - else - writel_relaxed(pc | FSMC_ENABLE, host->regs_va + FSMC_PC); - - /* - * nCE line changes must be applied before returning from this - * function. - */ - mb(); -} - /* * fsmc_exec_op - hook called by the core to execute NAND operations * @@ -627,8 +610,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op, pr_debug("Executing operation [%d instructions]:\n", op->ninstrs); - fsmc_ce_ctrl(host, true); - for (op_id = 0; op_id < op->ninstrs; op_id++) { instr = &op->instrs[op_id]; @@ -686,8 +667,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op, } } - fsmc_ce_ctrl(host, false); - return ret; } @@ -986,6 +965,19 @@ static const struct nand_controller_ops fsmc_nand_controller_ops = { .setup_data_interface = fsmc_setup_data_interface, }; +/** + * fsmc_nand_disable() - Disables the NAND bank + * @host: The instance to disable + */ +static void fsmc_nand_disable(struct fsmc_nand_data *host) +{ + u32 val; + + val = readl(host->regs_va + FSMC_PC); + val &= ~FSMC_ENABLE; + writel(val, host->regs_va + FSMC_PC); +} + /* * fsmc_nand_probe - Probe function * @pdev: platform device structure @@ -1141,6 +1133,7 @@ release_dma_read_chan: if (host->mode == USE_DMA_ACCESS) dma_release_channel(host->read_dma_chan); disable_clk: + fsmc_nand_disable(host); clk_disable_unprepare(host->clk); return ret; @@ -1155,6 +1148,7 @@ static int fsmc_nand_remove(struct platform_device *pdev) if (host) { nand_release(&host->nand); + fsmc_nand_disable(host); if (host->mode == USE_DMA_ACCESS) { dma_release_channel(host->write_dma_chan); @@ -1185,6 +1179,7 @@ static int fsmc_nand_resume(struct device *dev) clk_prepare_enable(host->clk); if (host->dev_timings) fsmc_nand_setup(host, host->dev_timings); + nand_reset(&host->nand, 0); } return 0; diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c index bd4cfac6b5aa..a4768df5083f 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c @@ -155,9 +155,10 @@ int gpmi_init(struct gpmi_nand_data *this) /* * Reset BCH here, too. We got failures otherwise :( - * See later BCH reset for explanation of MX23 handling + * See later BCH reset for explanation of MX23 and MX28 handling */ - ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); + ret = gpmi_reset_block(r->bch_regs, + GPMI_IS_MX23(this) || GPMI_IS_MX28(this)); if (ret) goto err_out; @@ -263,12 +264,10 @@ int bch_set_geometry(struct gpmi_nand_data *this) /* * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this * chip, otherwise it will lock up. So we skip resetting BCH on the MX23. - * On the other hand, the MX28 needs the reset, because one case has been - * seen where the BCH produced ECC errors constantly after 10000 - * consecutive reboots. The latter case has not been seen on the MX23 - * yet, still we don't know if it could happen there as well. + * and MX28. */ - ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); + ret = gpmi_reset_block(r->bch_regs, + GPMI_IS_MX23(this) || GPMI_IS_MX28(this)); if (ret) goto err_out; diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index f92ae5aa2a54..9526d5b23c80 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -260,7 +260,7 @@ static int jz_nand_correct_ecc_rs(struct nand_chip *chip, uint8_t *dat, } static int jz_nand_ioremap_resource(struct platform_device *pdev, - const char *name, struct resource **res, void *__iomem *base) + const char *name, struct resource **res, void __iomem **base) { int ret; diff --git a/drivers/mtd/nand/raw/jz4780_bch.c b/drivers/mtd/nand/raw/jz4780_bch.c index 7201827809e9..c5f74ed85862 100644 --- a/drivers/mtd/nand/raw/jz4780_bch.c +++ b/drivers/mtd/nand/raw/jz4780_bch.c @@ -281,12 +281,15 @@ static struct jz4780_bch *jz4780_bch_get(struct device_node *np) struct jz4780_bch *bch; pdev = of_find_device_by_node(np); - if (!pdev || !platform_get_drvdata(pdev)) + if (!pdev) return ERR_PTR(-EPROBE_DEFER); - get_device(&pdev->dev); - bch = platform_get_drvdata(pdev); + if (!bch) { + put_device(&pdev->dev); + return ERR_PTR(-EPROBE_DEFER); + } + clk_prepare_enable(bch->clk); return bch; diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 84283c6bb0ff..f38e5c1b87e4 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2550,9 +2550,8 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc, } /* Alloc the nand chip structure */ - marvell_nand = devm_kzalloc(dev, sizeof(*marvell_nand) + - (nsels * - sizeof(struct marvell_nand_chip_sel)), + marvell_nand = devm_kzalloc(dev, + struct_size(marvell_nand, sels, nsels), GFP_KERNEL); if (!marvell_nand) { dev_err(dev, "could not allocate chip structure\n"); diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c new file mode 100644 index 000000000000..3e8aa71407b5 --- /dev/null +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -0,0 +1,1464 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Amlogic Meson Nand Flash Controller Driver + * + * Copyright (c) 2018 Amlogic, inc. + * Author: Liang Yang <liang.yang@amlogic.com> + */ + +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/clk.h> +#include <linux/mtd/rawnand.h> +#include <linux/mtd/mtd.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/iopoll.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/sched/task_stack.h> + +#define NFC_REG_CMD 0x00 +#define NFC_CMD_IDLE (0xc << 14) +#define NFC_CMD_CLE (0x5 << 14) +#define NFC_CMD_ALE (0x6 << 14) +#define NFC_CMD_ADL ((0 << 16) | (3 << 20)) +#define NFC_CMD_ADH ((1 << 16) | (3 << 20)) +#define NFC_CMD_AIL ((2 << 16) | (3 << 20)) +#define NFC_CMD_AIH ((3 << 16) | (3 << 20)) +#define NFC_CMD_SEED ((8 << 16) | (3 << 20)) +#define NFC_CMD_M2N ((0 << 17) | (2 << 20)) +#define NFC_CMD_N2M ((1 << 17) | (2 << 20)) +#define NFC_CMD_RB BIT(20) +#define NFC_CMD_SCRAMBLER_ENABLE BIT(19) +#define NFC_CMD_SCRAMBLER_DISABLE 0 +#define NFC_CMD_SHORTMODE_DISABLE 0 +#define NFC_CMD_RB_INT BIT(14) + +#define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) + +#define NFC_REG_CFG 0x04 +#define NFC_REG_DADR 0x08 +#define NFC_REG_IADR 0x0c +#define NFC_REG_BUF 0x10 +#define NFC_REG_INFO 0x14 +#define NFC_REG_DC 0x18 +#define NFC_REG_ADR 0x1c +#define NFC_REG_DL 0x20 +#define NFC_REG_DH 0x24 +#define NFC_REG_CADR 0x28 +#define NFC_REG_SADR 0x2c +#define NFC_REG_PINS 0x30 +#define NFC_REG_VER 0x38 + +#define NFC_RB_IRQ_EN BIT(21) + +#define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages) \ + ( \ + (cmd_dir) | \ + ((ran) << 19) | \ + ((bch) << 14) | \ + ((short_mode) << 13) | \ + (((page_size) & 0x7f) << 6) | \ + ((pages) & 0x3f) \ + ) + +#define GENCMDDADDRL(adl, addr) ((adl) | ((addr) & 0xffff)) +#define GENCMDDADDRH(adh, addr) ((adh) | (((addr) >> 16) & 0xffff)) +#define GENCMDIADDRL(ail, addr) ((ail) | ((addr) & 0xffff)) +#define GENCMDIADDRH(aih, addr) ((aih) | (((addr) >> 16) & 0xffff)) + +#define DMA_DIR(dir) ((dir) ? NFC_CMD_N2M : NFC_CMD_M2N) + +#define ECC_CHECK_RETURN_FF (-1) + +#define NAND_CE0 (0xe << 10) +#define NAND_CE1 (0xd << 10) + +#define DMA_BUSY_TIMEOUT 0x100000 +#define CMD_FIFO_EMPTY_TIMEOUT 1000 + +#define MAX_CE_NUM 2 + +/* eMMC clock register, misc control */ +#define CLK_SELECT_NAND BIT(31) + +#define NFC_CLK_CYCLE 6 + +/* nand flash controller delay 3 ns */ +#define NFC_DEFAULT_DELAY 3000 + +#define ROW_ADDER(page, index) (((page) >> (8 * (index))) & 0xff) +#define MAX_CYCLE_ADDRS 5 +#define DIRREAD 1 +#define DIRWRITE 0 + +#define ECC_PARITY_BCH8_512B 14 +#define ECC_COMPLETE BIT(31) +#define ECC_ERR_CNT(x) (((x) >> 24) & GENMASK(5, 0)) +#define ECC_ZERO_CNT(x) (((x) >> 16) & GENMASK(5, 0)) +#define ECC_UNCORRECTABLE 0x3f + +#define PER_INFO_BYTE 8 + +struct meson_nfc_nand_chip { + struct list_head node; + struct nand_chip nand; + unsigned long clk_rate; + unsigned long level1_divider; + u32 bus_timing; + u32 twb; + u32 tadl; + u32 tbers_max; + + u32 bch_mode; + u8 *data_buf; + __le64 *info_buf; + u32 nsels; + u8 sels[0]; +}; + +struct meson_nand_ecc { + u32 bch; + u32 strength; +}; + +struct meson_nfc_data { + const struct nand_ecc_caps *ecc_caps; +}; + +struct meson_nfc_param { + u32 chip_select; + u32 rb_select; +}; + +struct nand_rw_cmd { + u32 cmd0; + u32 addrs[MAX_CYCLE_ADDRS]; + u32 cmd1; +}; + +struct nand_timing { + u32 twb; + u32 tadl; + u32 tbers_max; +}; + +struct meson_nfc { + struct nand_controller controller; + struct clk *core_clk; + struct clk *device_clk; + struct clk *phase_tx; + struct clk *phase_rx; + + unsigned long clk_rate; + u32 bus_timing; + + struct device *dev; + void __iomem *reg_base; + struct regmap *reg_clk; + struct completion completion; + struct list_head chips; + const struct meson_nfc_data *data; + struct meson_nfc_param param; + struct nand_timing timing; + union { + int cmd[32]; + struct nand_rw_cmd rw; + } cmdfifo; + + dma_addr_t daddr; + dma_addr_t iaddr; + + unsigned long assigned_cs; +}; + +enum { + NFC_ECC_BCH8_1K = 2, + NFC_ECC_BCH24_1K, + NFC_ECC_BCH30_1K, + NFC_ECC_BCH40_1K, + NFC_ECC_BCH50_1K, + NFC_ECC_BCH60_1K, +}; + +#define MESON_ECC_DATA(b, s) { .bch = (b), .strength = (s)} + +static struct meson_nand_ecc meson_ecc[] = { + MESON_ECC_DATA(NFC_ECC_BCH8_1K, 8), + MESON_ECC_DATA(NFC_ECC_BCH24_1K, 24), + MESON_ECC_DATA(NFC_ECC_BCH30_1K, 30), + MESON_ECC_DATA(NFC_ECC_BCH40_1K, 40), + MESON_ECC_DATA(NFC_ECC_BCH50_1K, 50), + MESON_ECC_DATA(NFC_ECC_BCH60_1K, 60), +}; + +static int meson_nand_calc_ecc_bytes(int step_size, int strength) +{ + int ecc_bytes; + + if (step_size == 512 && strength == 8) + return ECC_PARITY_BCH8_512B; + + ecc_bytes = DIV_ROUND_UP(strength * fls(step_size * 8), 8); + ecc_bytes = ALIGN(ecc_bytes, 2); + + return ecc_bytes; +} + +NAND_ECC_CAPS_SINGLE(meson_gxl_ecc_caps, + meson_nand_calc_ecc_bytes, 1024, 8, 24, 30, 40, 50, 60); +NAND_ECC_CAPS_SINGLE(meson_axg_ecc_caps, + meson_nand_calc_ecc_bytes, 1024, 8); + +static struct meson_nfc_nand_chip *to_meson_nand(struct nand_chip *nand) +{ + return container_of(nand, struct meson_nfc_nand_chip, nand); +} + +static void meson_nfc_select_chip(struct nand_chip *nand, int chip) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + struct meson_nfc *nfc = nand_get_controller_data(nand); + int ret, value; + + if (chip < 0 || WARN_ON_ONCE(chip >= meson_chip->nsels)) + return; + + nfc->param.chip_select = meson_chip->sels[chip] ? NAND_CE1 : NAND_CE0; + nfc->param.rb_select = nfc->param.chip_select; + nfc->timing.twb = meson_chip->twb; + nfc->timing.tadl = meson_chip->tadl; + nfc->timing.tbers_max = meson_chip->tbers_max; + + if (nfc->clk_rate != meson_chip->clk_rate) { + ret = clk_set_rate(nfc->device_clk, meson_chip->clk_rate); + if (ret) { + dev_err(nfc->dev, "failed to set clock rate\n"); + return; + } + nfc->clk_rate = meson_chip->clk_rate; + } + if (nfc->bus_timing != meson_chip->bus_timing) { + value = (NFC_CLK_CYCLE - 1) | (meson_chip->bus_timing << 5); + writel(value, nfc->reg_base + NFC_REG_CFG); + writel((1 << 31), nfc->reg_base + NFC_REG_CMD); + nfc->bus_timing = meson_chip->bus_timing; + } +} + +static void meson_nfc_cmd_idle(struct meson_nfc *nfc, u32 time) +{ + writel(nfc->param.chip_select | NFC_CMD_IDLE | (time & 0x3ff), + nfc->reg_base + NFC_REG_CMD); +} + +static void meson_nfc_cmd_seed(struct meson_nfc *nfc, u32 seed) +{ + writel(NFC_CMD_SEED | (0xc2 + (seed & 0x7fff)), + nfc->reg_base + NFC_REG_CMD); +} + +static void meson_nfc_cmd_access(struct nand_chip *nand, int raw, bool dir, + int scrambler) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + struct meson_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + u32 bch = meson_chip->bch_mode, cmd; + int len = mtd->writesize, pagesize, pages; + + pagesize = nand->ecc.size; + + if (raw) { + len = mtd->writesize + mtd->oobsize; + cmd = (len & GENMASK(5, 0)) | scrambler | DMA_DIR(dir); + writel(cmd, nfc->reg_base + NFC_REG_CMD); + return; + } + + pages = len / nand->ecc.size; + + cmd = CMDRWGEN(DMA_DIR(dir), scrambler, bch, + NFC_CMD_SHORTMODE_DISABLE, pagesize, pages); + + writel(cmd, nfc->reg_base + NFC_REG_CMD); +} + +static void meson_nfc_drain_cmd(struct meson_nfc *nfc) +{ + /* + * Insert two commands to make sure all valid commands are finished. + * + * The Nand flash controller is designed as two stages pipleline - + * a) fetch and b) excute. + * There might be cases when the driver see command queue is empty, + * but the Nand flash controller still has two commands buffered, + * one is fetched into NFC request queue (ready to run), and another + * is actively executing. So pushing 2 "IDLE" commands guarantees that + * the pipeline is emptied. + */ + meson_nfc_cmd_idle(nfc, 0); + meson_nfc_cmd_idle(nfc, 0); +} + +static int meson_nfc_wait_cmd_finish(struct meson_nfc *nfc, + unsigned int timeout_ms) +{ + u32 cmd_size = 0; + int ret; + + /* wait cmd fifo is empty */ + ret = readl_relaxed_poll_timeout(nfc->reg_base + NFC_REG_CMD, cmd_size, + !NFC_CMD_GET_SIZE(cmd_size), + 10, timeout_ms * 1000); + if (ret) + dev_err(nfc->dev, "wait for empty CMD FIFO time out\n"); + + return ret; +} + +static int meson_nfc_wait_dma_finish(struct meson_nfc *nfc) +{ + meson_nfc_drain_cmd(nfc); + + return meson_nfc_wait_cmd_finish(nfc, DMA_BUSY_TIMEOUT); +} + +static u8 *meson_nfc_oob_ptr(struct nand_chip *nand, int i) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + int len; + + len = nand->ecc.size * (i + 1) + (nand->ecc.bytes + 2) * i; + + return meson_chip->data_buf + len; +} + +static u8 *meson_nfc_data_ptr(struct nand_chip *nand, int i) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + int len, temp; + + temp = nand->ecc.size + nand->ecc.bytes; + len = (temp + 2) * i; + + return meson_chip->data_buf + len; +} + +static void meson_nfc_get_data_oob(struct nand_chip *nand, + u8 *buf, u8 *oobbuf) +{ + int i, oob_len = 0; + u8 *dsrc, *osrc; + + oob_len = nand->ecc.bytes + 2; + for (i = 0; i < nand->ecc.steps; i++) { + if (buf) { + dsrc = meson_nfc_data_ptr(nand, i); + memcpy(buf, dsrc, nand->ecc.size); + buf += nand->ecc.size; + } + osrc = meson_nfc_oob_ptr(nand, i); + memcpy(oobbuf, osrc, oob_len); + oobbuf += oob_len; + } +} + +static void meson_nfc_set_data_oob(struct nand_chip *nand, + const u8 *buf, u8 *oobbuf) +{ + int i, oob_len = 0; + u8 *dsrc, *osrc; + + oob_len = nand->ecc.bytes + 2; + for (i = 0; i < nand->ecc.steps; i++) { + if (buf) { + dsrc = meson_nfc_data_ptr(nand, i); + memcpy(dsrc, buf, nand->ecc.size); + buf += nand->ecc.size; + } + osrc = meson_nfc_oob_ptr(nand, i); + memcpy(osrc, oobbuf, oob_len); + oobbuf += oob_len; + } +} + +static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) +{ + u32 cmd, cfg; + int ret = 0; + + meson_nfc_cmd_idle(nfc, nfc->timing.twb); + meson_nfc_drain_cmd(nfc); + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); + + cfg = readl(nfc->reg_base + NFC_REG_CFG); + cfg |= NFC_RB_IRQ_EN; + writel(cfg, nfc->reg_base + NFC_REG_CFG); + + init_completion(&nfc->completion); + + /* use the max erase time as the maximum clock for waiting R/B */ + cmd = NFC_CMD_RB | NFC_CMD_RB_INT + | nfc->param.chip_select | nfc->timing.tbers_max; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + ret = wait_for_completion_timeout(&nfc->completion, + msecs_to_jiffies(timeout_ms)); + if (ret == 0) + ret = -1; + + return ret; +} + +static void meson_nfc_set_user_byte(struct nand_chip *nand, u8 *oob_buf) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + __le64 *info; + int i, count; + + for (i = 0, count = 0; i < nand->ecc.steps; i++, count += 2) { + info = &meson_chip->info_buf[i]; + *info |= oob_buf[count]; + *info |= oob_buf[count + 1] << 8; + } +} + +static void meson_nfc_get_user_byte(struct nand_chip *nand, u8 *oob_buf) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + __le64 *info; + int i, count; + + for (i = 0, count = 0; i < nand->ecc.steps; i++, count += 2) { + info = &meson_chip->info_buf[i]; + oob_buf[count] = *info; + oob_buf[count + 1] = *info >> 8; + } +} + +static int meson_nfc_ecc_correct(struct nand_chip *nand, u32 *bitflips, + u64 *correct_bitmap) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + __le64 *info; + int ret = 0, i; + + for (i = 0; i < nand->ecc.steps; i++) { + info = &meson_chip->info_buf[i]; + if (ECC_ERR_CNT(*info) != ECC_UNCORRECTABLE) { + mtd->ecc_stats.corrected += ECC_ERR_CNT(*info); + *bitflips = max_t(u32, *bitflips, ECC_ERR_CNT(*info)); + *correct_bitmap |= 1 >> i; + continue; + } + if ((nand->options & NAND_NEED_SCRAMBLING) && + ECC_ZERO_CNT(*info) < nand->ecc.strength) { + mtd->ecc_stats.corrected += ECC_ZERO_CNT(*info); + *bitflips = max_t(u32, *bitflips, + ECC_ZERO_CNT(*info)); + ret = ECC_CHECK_RETURN_FF; + } else { + ret = -EBADMSG; + } + } + return ret; +} + +static int meson_nfc_dma_buffer_setup(struct nand_chip *nand, u8 *databuf, + int datalen, u8 *infobuf, int infolen, + enum dma_data_direction dir) +{ + struct meson_nfc *nfc = nand_get_controller_data(nand); + u32 cmd; + int ret = 0; + + nfc->daddr = dma_map_single(nfc->dev, (void *)databuf, datalen, dir); + ret = dma_mapping_error(nfc->dev, nfc->daddr); + if (ret) { + dev_err(nfc->dev, "DMA mapping error\n"); + return ret; + } + cmd = GENCMDDADDRL(NFC_CMD_ADL, nfc->daddr); + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + cmd = GENCMDDADDRH(NFC_CMD_ADH, nfc->daddr); + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + if (infobuf) { + nfc->iaddr = dma_map_single(nfc->dev, infobuf, infolen, dir); + ret = dma_mapping_error(nfc->dev, nfc->iaddr); + if (ret) { + dev_err(nfc->dev, "DMA mapping error\n"); + dma_unmap_single(nfc->dev, + nfc->daddr, datalen, dir); + return ret; + } + cmd = GENCMDIADDRL(NFC_CMD_AIL, nfc->iaddr); + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + cmd = GENCMDIADDRH(NFC_CMD_AIH, nfc->iaddr); + writel(cmd, nfc->reg_base + NFC_REG_CMD); + } + + return ret; +} + +static void meson_nfc_dma_buffer_release(struct nand_chip *nand, + int infolen, int datalen, + enum dma_data_direction dir) +{ + struct meson_nfc *nfc = nand_get_controller_data(nand); + + dma_unmap_single(nfc->dev, nfc->daddr, datalen, dir); + if (infolen) + dma_unmap_single(nfc->dev, nfc->iaddr, infolen, dir); +} + +static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len) +{ + struct meson_nfc *nfc = nand_get_controller_data(nand); + int ret = 0; + u32 cmd; + u8 *info; + + info = kzalloc(PER_INFO_BYTE, GFP_KERNEL); + ret = meson_nfc_dma_buffer_setup(nand, buf, len, info, + PER_INFO_BYTE, DMA_FROM_DEVICE); + if (ret) + return ret; + + cmd = NFC_CMD_N2M | (len & GENMASK(5, 0)); + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + meson_nfc_drain_cmd(nfc); + meson_nfc_wait_cmd_finish(nfc, 1000); + meson_nfc_dma_buffer_release(nand, len, PER_INFO_BYTE, DMA_FROM_DEVICE); + kfree(info); + + return ret; +} + +static int meson_nfc_write_buf(struct nand_chip *nand, u8 *buf, int len) +{ + struct meson_nfc *nfc = nand_get_controller_data(nand); + int ret = 0; + u32 cmd; + + ret = meson_nfc_dma_buffer_setup(nand, buf, len, NULL, + 0, DMA_TO_DEVICE); + if (ret) + return ret; + + cmd = NFC_CMD_M2N | (len & GENMASK(5, 0)); + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + meson_nfc_drain_cmd(nfc); + meson_nfc_wait_cmd_finish(nfc, 1000); + meson_nfc_dma_buffer_release(nand, len, 0, DMA_TO_DEVICE); + + return ret; +} + +static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand, + int page, bool in) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + struct meson_nfc *nfc = nand_get_controller_data(nand); + const struct nand_sdr_timings *sdr = + nand_get_sdr_timings(&nand->data_interface); + u32 *addrs = nfc->cmdfifo.rw.addrs; + u32 cs = nfc->param.chip_select; + u32 cmd0, cmd_num, row_start; + int ret = 0, i; + + cmd_num = sizeof(struct nand_rw_cmd) / sizeof(int); + + cmd0 = in ? NAND_CMD_READ0 : NAND_CMD_SEQIN; + nfc->cmdfifo.rw.cmd0 = cs | NFC_CMD_CLE | cmd0; + + addrs[0] = cs | NFC_CMD_ALE | 0; + if (mtd->writesize <= 512) { + cmd_num--; + row_start = 1; + } else { + addrs[1] = cs | NFC_CMD_ALE | 0; + row_start = 2; + } + + addrs[row_start] = cs | NFC_CMD_ALE | ROW_ADDER(page, 0); + addrs[row_start + 1] = cs | NFC_CMD_ALE | ROW_ADDER(page, 1); + + if (nand->options & NAND_ROW_ADDR_3) + addrs[row_start + 2] = + cs | NFC_CMD_ALE | ROW_ADDER(page, 2); + else + cmd_num--; + + /* subtract cmd1 */ + cmd_num--; + + for (i = 0; i < cmd_num; i++) + writel_relaxed(nfc->cmdfifo.cmd[i], + nfc->reg_base + NFC_REG_CMD); + + if (in) { + nfc->cmdfifo.rw.cmd1 = cs | NFC_CMD_CLE | NAND_CMD_READSTART; + writel(nfc->cmdfifo.rw.cmd1, nfc->reg_base + NFC_REG_CMD); + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max)); + } else { + meson_nfc_cmd_idle(nfc, nfc->timing.tadl); + } + + return ret; +} + +static int meson_nfc_write_page_sub(struct nand_chip *nand, + int page, int raw) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + const struct nand_sdr_timings *sdr = + nand_get_sdr_timings(&nand->data_interface); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + struct meson_nfc *nfc = nand_get_controller_data(nand); + int data_len, info_len; + u32 cmd; + int ret; + + meson_nfc_select_chip(nand, nand->cur_cs); + + data_len = mtd->writesize + mtd->oobsize; + info_len = nand->ecc.steps * PER_INFO_BYTE; + + ret = meson_nfc_rw_cmd_prepare_and_execute(nand, page, DIRWRITE); + if (ret) + return ret; + + ret = meson_nfc_dma_buffer_setup(nand, meson_chip->data_buf, + data_len, (u8 *)meson_chip->info_buf, + info_len, DMA_TO_DEVICE); + if (ret) + return ret; + + if (nand->options & NAND_NEED_SCRAMBLING) { + meson_nfc_cmd_seed(nfc, page); + meson_nfc_cmd_access(nand, raw, DIRWRITE, + NFC_CMD_SCRAMBLER_ENABLE); + } else { + meson_nfc_cmd_access(nand, raw, DIRWRITE, + NFC_CMD_SCRAMBLER_DISABLE); + } + + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_PAGEPROG; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max)); + + meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE); + + return ret; +} + +static int meson_nfc_write_page_raw(struct nand_chip *nand, const u8 *buf, + int oob_required, int page) +{ + u8 *oob_buf = nand->oob_poi; + + meson_nfc_set_data_oob(nand, buf, oob_buf); + + return meson_nfc_write_page_sub(nand, page, 1); +} + +static int meson_nfc_write_page_hwecc(struct nand_chip *nand, + const u8 *buf, int oob_required, int page) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + u8 *oob_buf = nand->oob_poi; + + memcpy(meson_chip->data_buf, buf, mtd->writesize); + memset(meson_chip->info_buf, 0, nand->ecc.steps * PER_INFO_BYTE); + meson_nfc_set_user_byte(nand, oob_buf); + + return meson_nfc_write_page_sub(nand, page, 0); +} + +static void meson_nfc_check_ecc_pages_valid(struct meson_nfc *nfc, + struct nand_chip *nand, int raw) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + __le64 *info; + u32 neccpages; + int ret; + + neccpages = raw ? 1 : nand->ecc.steps; + info = &meson_chip->info_buf[neccpages - 1]; + do { + usleep_range(10, 15); + /* info is updated by nfc dma engine*/ + smp_rmb(); + ret = *info & ECC_COMPLETE; + } while (!ret); +} + +static int meson_nfc_read_page_sub(struct nand_chip *nand, + int page, int raw) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + struct meson_nfc *nfc = nand_get_controller_data(nand); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + int data_len, info_len; + int ret; + + meson_nfc_select_chip(nand, nand->cur_cs); + + data_len = mtd->writesize + mtd->oobsize; + info_len = nand->ecc.steps * PER_INFO_BYTE; + + ret = meson_nfc_rw_cmd_prepare_and_execute(nand, page, DIRREAD); + if (ret) + return ret; + + ret = meson_nfc_dma_buffer_setup(nand, meson_chip->data_buf, + data_len, (u8 *)meson_chip->info_buf, + info_len, DMA_FROM_DEVICE); + if (ret) + return ret; + + if (nand->options & NAND_NEED_SCRAMBLING) { + meson_nfc_cmd_seed(nfc, page); + meson_nfc_cmd_access(nand, raw, DIRREAD, + NFC_CMD_SCRAMBLER_ENABLE); + } else { + meson_nfc_cmd_access(nand, raw, DIRREAD, + NFC_CMD_SCRAMBLER_DISABLE); + } + + ret = meson_nfc_wait_dma_finish(nfc); + meson_nfc_check_ecc_pages_valid(nfc, nand, raw); + + meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_FROM_DEVICE); + + return ret; +} + +static int meson_nfc_read_page_raw(struct nand_chip *nand, u8 *buf, + int oob_required, int page) +{ + u8 *oob_buf = nand->oob_poi; + int ret; + + ret = meson_nfc_read_page_sub(nand, page, 1); + if (ret) + return ret; + + meson_nfc_get_data_oob(nand, buf, oob_buf); + + return 0; +} + +static int meson_nfc_read_page_hwecc(struct nand_chip *nand, u8 *buf, + int oob_required, int page) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + struct nand_ecc_ctrl *ecc = &nand->ecc; + u64 correct_bitmap = 0; + u32 bitflips = 0; + u8 *oob_buf = nand->oob_poi; + int ret, i; + + ret = meson_nfc_read_page_sub(nand, page, 0); + if (ret) + return ret; + + meson_nfc_get_user_byte(nand, oob_buf); + ret = meson_nfc_ecc_correct(nand, &bitflips, &correct_bitmap); + if (ret == ECC_CHECK_RETURN_FF) { + if (buf) + memset(buf, 0xff, mtd->writesize); + memset(oob_buf, 0xff, mtd->oobsize); + } else if (ret < 0) { + if ((nand->options & NAND_NEED_SCRAMBLING) || !buf) { + mtd->ecc_stats.failed++; + return bitflips; + } + ret = meson_nfc_read_page_raw(nand, buf, 0, page); + if (ret) + return ret; + + for (i = 0; i < nand->ecc.steps ; i++) { + u8 *data = buf + i * ecc->size; + u8 *oob = nand->oob_poi + i * (ecc->bytes + 2); + + if (correct_bitmap & (1 << i)) + continue; + ret = nand_check_erased_ecc_chunk(data, ecc->size, + oob, ecc->bytes + 2, + NULL, 0, + ecc->strength); + if (ret < 0) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += ret; + bitflips = max_t(u32, bitflips, ret); + } + } + } else if (buf && buf != meson_chip->data_buf) { + memcpy(buf, meson_chip->data_buf, mtd->writesize); + } + + return bitflips; +} + +static int meson_nfc_read_oob_raw(struct nand_chip *nand, int page) +{ + return meson_nfc_read_page_raw(nand, NULL, 1, page); +} + +static int meson_nfc_read_oob(struct nand_chip *nand, int page) +{ + return meson_nfc_read_page_hwecc(nand, NULL, 1, page); +} + +static bool meson_nfc_is_buffer_dma_safe(const void *buffer) +{ + if (virt_addr_valid(buffer) && (!object_is_on_stack(buffer))) + return true; + return false; +} + +static void * +meson_nand_op_get_dma_safe_input_buf(const struct nand_op_instr *instr) +{ + if (WARN_ON(instr->type != NAND_OP_DATA_IN_INSTR)) + return NULL; + + if (meson_nfc_is_buffer_dma_safe(instr->ctx.data.buf.in)) + return instr->ctx.data.buf.in; + + return kzalloc(instr->ctx.data.len, GFP_KERNEL); +} + +static void +meson_nand_op_put_dma_safe_input_buf(const struct nand_op_instr *instr, + void *buf) +{ + if (WARN_ON(instr->type != NAND_OP_DATA_IN_INSTR) || + WARN_ON(!buf)) + return; + + if (buf == instr->ctx.data.buf.in) + return; + + memcpy(instr->ctx.data.buf.in, buf, instr->ctx.data.len); + kfree(buf); +} + +static void * +meson_nand_op_get_dma_safe_output_buf(const struct nand_op_instr *instr) +{ + if (WARN_ON(instr->type != NAND_OP_DATA_OUT_INSTR)) + return NULL; + + if (meson_nfc_is_buffer_dma_safe(instr->ctx.data.buf.out)) + return (void *)instr->ctx.data.buf.out; + + return kmemdup(instr->ctx.data.buf.out, + instr->ctx.data.len, GFP_KERNEL); +} + +static void +meson_nand_op_put_dma_safe_output_buf(const struct nand_op_instr *instr, + const void *buf) +{ + if (WARN_ON(instr->type != NAND_OP_DATA_OUT_INSTR) || + WARN_ON(!buf)) + return; + + if (buf != instr->ctx.data.buf.out) + kfree(buf); +} + +static int meson_nfc_exec_op(struct nand_chip *nand, + const struct nand_operation *op, bool check_only) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + struct meson_nfc *nfc = nand_get_controller_data(nand); + const struct nand_op_instr *instr = NULL; + void *buf; + u32 op_id, delay_idle, cmd; + int i; + + meson_nfc_select_chip(nand, op->cs); + for (op_id = 0; op_id < op->ninstrs; op_id++) { + instr = &op->instrs[op_id]; + delay_idle = DIV_ROUND_UP(PSEC_TO_NSEC(instr->delay_ns), + meson_chip->level1_divider * + NFC_CLK_CYCLE); + switch (instr->type) { + case NAND_OP_CMD_INSTR: + cmd = nfc->param.chip_select | NFC_CMD_CLE; + cmd |= instr->ctx.cmd.opcode & 0xff; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + meson_nfc_cmd_idle(nfc, delay_idle); + break; + + case NAND_OP_ADDR_INSTR: + for (i = 0; i < instr->ctx.addr.naddrs; i++) { + cmd = nfc->param.chip_select | NFC_CMD_ALE; + cmd |= instr->ctx.addr.addrs[i] & 0xff; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + } + meson_nfc_cmd_idle(nfc, delay_idle); + break; + + case NAND_OP_DATA_IN_INSTR: + buf = meson_nand_op_get_dma_safe_input_buf(instr); + if (!buf) + return -ENOMEM; + meson_nfc_read_buf(nand, buf, instr->ctx.data.len); + meson_nand_op_put_dma_safe_input_buf(instr, buf); + break; + + case NAND_OP_DATA_OUT_INSTR: + buf = meson_nand_op_get_dma_safe_output_buf(instr); + if (!buf) + return -ENOMEM; + meson_nfc_write_buf(nand, buf, instr->ctx.data.len); + meson_nand_op_put_dma_safe_output_buf(instr, buf); + break; + + case NAND_OP_WAITRDY_INSTR: + meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms); + if (instr->delay_ns) + meson_nfc_cmd_idle(nfc, delay_idle); + break; + } + } + meson_nfc_wait_cmd_finish(nfc, 1000); + return 0; +} + +static int meson_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + + if (section >= nand->ecc.steps) + return -ERANGE; + + oobregion->offset = 2 + (section * (2 + nand->ecc.bytes)); + oobregion->length = nand->ecc.bytes; + + return 0; +} + +static int meson_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + + if (section >= nand->ecc.steps) + return -ERANGE; + + oobregion->offset = section * (2 + nand->ecc.bytes); + oobregion->length = 2; + + return 0; +} + +static const struct mtd_ooblayout_ops meson_ooblayout_ops = { + .ecc = meson_ooblayout_ecc, + .free = meson_ooblayout_free, +}; + +static int meson_nfc_clk_init(struct meson_nfc *nfc) +{ + int ret; + + /* request core clock */ + nfc->core_clk = devm_clk_get(nfc->dev, "core"); + if (IS_ERR(nfc->core_clk)) { + dev_err(nfc->dev, "failed to get core clock\n"); + return PTR_ERR(nfc->core_clk); + } + + nfc->device_clk = devm_clk_get(nfc->dev, "device"); + if (IS_ERR(nfc->device_clk)) { + dev_err(nfc->dev, "failed to get device clock\n"); + return PTR_ERR(nfc->device_clk); + } + + nfc->phase_tx = devm_clk_get(nfc->dev, "tx"); + if (IS_ERR(nfc->phase_tx)) { + dev_err(nfc->dev, "failed to get TX clk\n"); + return PTR_ERR(nfc->phase_tx); + } + + nfc->phase_rx = devm_clk_get(nfc->dev, "rx"); + if (IS_ERR(nfc->phase_rx)) { + dev_err(nfc->dev, "failed to get RX clk\n"); + return PTR_ERR(nfc->phase_rx); + } + + /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */ + regmap_update_bits(nfc->reg_clk, + 0, CLK_SELECT_NAND, CLK_SELECT_NAND); + + ret = clk_prepare_enable(nfc->core_clk); + if (ret) { + dev_err(nfc->dev, "failed to enable core clock\n"); + return ret; + } + + ret = clk_prepare_enable(nfc->device_clk); + if (ret) { + dev_err(nfc->dev, "failed to enable device clock\n"); + goto err_device_clk; + } + + ret = clk_prepare_enable(nfc->phase_tx); + if (ret) { + dev_err(nfc->dev, "failed to enable TX clock\n"); + goto err_phase_tx; + } + + ret = clk_prepare_enable(nfc->phase_rx); + if (ret) { + dev_err(nfc->dev, "failed to enable RX clock\n"); + goto err_phase_rx; + } + + ret = clk_set_rate(nfc->device_clk, 24000000); + if (ret) + goto err_phase_rx; + + return 0; +err_phase_rx: + clk_disable_unprepare(nfc->phase_tx); +err_phase_tx: + clk_disable_unprepare(nfc->device_clk); +err_device_clk: + clk_disable_unprepare(nfc->core_clk); + return ret; +} + +static void meson_nfc_disable_clk(struct meson_nfc *nfc) +{ + clk_disable_unprepare(nfc->phase_rx); + clk_disable_unprepare(nfc->phase_tx); + clk_disable_unprepare(nfc->device_clk); + clk_disable_unprepare(nfc->core_clk); +} + +static void meson_nfc_free_buffer(struct nand_chip *nand) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + + kfree(meson_chip->info_buf); + kfree(meson_chip->data_buf); +} + +static int meson_chip_buffer_init(struct nand_chip *nand) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + u32 page_bytes, info_bytes, nsectors; + + nsectors = mtd->writesize / nand->ecc.size; + + page_bytes = mtd->writesize + mtd->oobsize; + info_bytes = nsectors * PER_INFO_BYTE; + + meson_chip->data_buf = kmalloc(page_bytes, GFP_KERNEL); + if (!meson_chip->data_buf) + return -ENOMEM; + + meson_chip->info_buf = kmalloc(info_bytes, GFP_KERNEL); + if (!meson_chip->info_buf) { + kfree(meson_chip->data_buf); + return -ENOMEM; + } + + return 0; +} + +static +int meson_nfc_setup_data_interface(struct nand_chip *nand, int csline, + const struct nand_data_interface *conf) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + const struct nand_sdr_timings *timings; + u32 div, bt_min, bt_max, tbers_clocks; + + timings = nand_get_sdr_timings(conf); + if (IS_ERR(timings)) + return -ENOTSUPP; + + if (csline == NAND_DATA_IFACE_CHECK_ONLY) + return 0; + + div = DIV_ROUND_UP((timings->tRC_min / 1000), NFC_CLK_CYCLE); + bt_min = (timings->tREA_max + NFC_DEFAULT_DELAY) / div; + bt_max = (NFC_DEFAULT_DELAY + timings->tRHOH_min + + timings->tRC_min / 2) / div; + + meson_chip->twb = DIV_ROUND_UP(PSEC_TO_NSEC(timings->tWB_max), + div * NFC_CLK_CYCLE); + meson_chip->tadl = DIV_ROUND_UP(PSEC_TO_NSEC(timings->tADL_min), + div * NFC_CLK_CYCLE); + tbers_clocks = DIV_ROUND_UP_ULL(PSEC_TO_NSEC(timings->tBERS_max), + div * NFC_CLK_CYCLE); + meson_chip->tbers_max = ilog2(tbers_clocks); + if (!is_power_of_2(tbers_clocks)) + meson_chip->tbers_max++; + + bt_min = DIV_ROUND_UP(bt_min, 1000); + bt_max = DIV_ROUND_UP(bt_max, 1000); + + if (bt_max < bt_min) + return -EINVAL; + + meson_chip->level1_divider = div; + meson_chip->clk_rate = 1000000000 / meson_chip->level1_divider; + meson_chip->bus_timing = (bt_min + bt_max) / 2 + 1; + + return 0; +} + +static int meson_nand_bch_mode(struct nand_chip *nand) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + int i; + + if (nand->ecc.strength > 60 || nand->ecc.strength < 8) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(meson_ecc); i++) { + if (meson_ecc[i].strength == nand->ecc.strength) { + meson_chip->bch_mode = meson_ecc[i].bch; + return 0; + } + } + + return -EINVAL; +} + +static void meson_nand_detach_chip(struct nand_chip *nand) +{ + meson_nfc_free_buffer(nand); +} + +static int meson_nand_attach_chip(struct nand_chip *nand) +{ + struct meson_nfc *nfc = nand_get_controller_data(nand); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + struct mtd_info *mtd = nand_to_mtd(nand); + int nsectors = mtd->writesize / 1024; + int ret; + + if (!mtd->name) { + mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL, + "%s:nand%d", + dev_name(nfc->dev), + meson_chip->sels[0]); + if (!mtd->name) + return -ENOMEM; + } + + if (nand->bbt_options & NAND_BBT_USE_FLASH) + nand->bbt_options |= NAND_BBT_NO_OOB; + + nand->options |= NAND_NO_SUBPAGE_WRITE; + + ret = nand_ecc_choose_conf(nand, nfc->data->ecc_caps, + mtd->oobsize - 2 * nsectors); + if (ret) { + dev_err(nfc->dev, "failed to ECC init\n"); + return -EINVAL; + } + + ret = meson_nand_bch_mode(nand); + if (ret) + return -EINVAL; + + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.write_page_raw = meson_nfc_write_page_raw; + nand->ecc.write_page = meson_nfc_write_page_hwecc; + nand->ecc.write_oob_raw = nand_write_oob_std; + nand->ecc.write_oob = nand_write_oob_std; + + nand->ecc.read_page_raw = meson_nfc_read_page_raw; + nand->ecc.read_page = meson_nfc_read_page_hwecc; + nand->ecc.read_oob_raw = meson_nfc_read_oob_raw; + nand->ecc.read_oob = meson_nfc_read_oob; + + if (nand->options & NAND_BUSWIDTH_16) { + dev_err(nfc->dev, "16bits bus width not supported"); + return -EINVAL; + } + ret = meson_chip_buffer_init(nand); + if (ret) + return -ENOMEM; + + return ret; +} + +static const struct nand_controller_ops meson_nand_controller_ops = { + .attach_chip = meson_nand_attach_chip, + .detach_chip = meson_nand_detach_chip, + .setup_data_interface = meson_nfc_setup_data_interface, + .exec_op = meson_nfc_exec_op, +}; + +static int +meson_nfc_nand_chip_init(struct device *dev, + struct meson_nfc *nfc, struct device_node *np) +{ + struct meson_nfc_nand_chip *meson_chip; + struct nand_chip *nand; + struct mtd_info *mtd; + int ret, i; + u32 tmp, nsels; + + if (!of_get_property(np, "reg", &nsels)) + return -EINVAL; + + nsels /= sizeof(u32); + if (!nsels || nsels > MAX_CE_NUM) { + dev_err(dev, "invalid register property size\n"); + return -EINVAL; + } + + meson_chip = devm_kzalloc(dev, + sizeof(*meson_chip) + (nsels * sizeof(u8)), + GFP_KERNEL); + if (!meson_chip) + return -ENOMEM; + + meson_chip->nsels = nsels; + + for (i = 0; i < nsels; i++) { + ret = of_property_read_u32_index(np, "reg", i, &tmp); + if (ret) { + dev_err(dev, "could not retrieve register property: %d\n", + ret); + return ret; + } + + if (test_and_set_bit(tmp, &nfc->assigned_cs)) { + dev_err(dev, "CS %d already assigned\n", tmp); + return -EINVAL; + } + } + + nand = &meson_chip->nand; + nand->controller = &nfc->controller; + nand->controller->ops = &meson_nand_controller_ops; + nand_set_flash_node(nand, np); + nand_set_controller_data(nand, nfc); + + nand->options |= NAND_USE_BOUNCE_BUFFER; + mtd = nand_to_mtd(nand); + mtd->owner = THIS_MODULE; + mtd->dev.parent = dev; + + ret = nand_scan(nand, nsels); + if (ret) + return ret; + + ret = mtd_device_register(mtd, NULL, 0); + if (ret) { + dev_err(dev, "failed to register MTD device: %d\n", ret); + nand_cleanup(nand); + return ret; + } + + list_add_tail(&meson_chip->node, &nfc->chips); + + return 0; +} + +static int meson_nfc_nand_chip_cleanup(struct meson_nfc *nfc) +{ + struct meson_nfc_nand_chip *meson_chip; + struct mtd_info *mtd; + int ret; + + while (!list_empty(&nfc->chips)) { + meson_chip = list_first_entry(&nfc->chips, + struct meson_nfc_nand_chip, node); + mtd = nand_to_mtd(&meson_chip->nand); + ret = mtd_device_unregister(mtd); + if (ret) + return ret; + + meson_nfc_free_buffer(&meson_chip->nand); + nand_cleanup(&meson_chip->nand); + list_del(&meson_chip->node); + } + + return 0; +} + +static int meson_nfc_nand_chips_init(struct device *dev, + struct meson_nfc *nfc) +{ + struct device_node *np = dev->of_node; + struct device_node *nand_np; + int ret; + + for_each_child_of_node(np, nand_np) { + ret = meson_nfc_nand_chip_init(dev, nfc, nand_np); + if (ret) { + meson_nfc_nand_chip_cleanup(nfc); + return ret; + } + } + + return 0; +} + +static irqreturn_t meson_nfc_irq(int irq, void *id) +{ + struct meson_nfc *nfc = id; + u32 cfg; + + cfg = readl(nfc->reg_base + NFC_REG_CFG); + if (!(cfg & NFC_RB_IRQ_EN)) + return IRQ_NONE; + + cfg &= ~(NFC_RB_IRQ_EN); + writel(cfg, nfc->reg_base + NFC_REG_CFG); + + complete(&nfc->completion); + return IRQ_HANDLED; +} + +static const struct meson_nfc_data meson_gxl_data = { + .ecc_caps = &meson_gxl_ecc_caps, +}; + +static const struct meson_nfc_data meson_axg_data = { + .ecc_caps = &meson_axg_ecc_caps, +}; + +static const struct of_device_id meson_nfc_id_table[] = { + { + .compatible = "amlogic,meson-gxl-nfc", + .data = &meson_gxl_data, + }, { + .compatible = "amlogic,meson-axg-nfc", + .data = &meson_axg_data, + }, + {} +}; +MODULE_DEVICE_TABLE(of, meson_nfc_id_table); + +static int meson_nfc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct meson_nfc *nfc; + struct resource *res; + int ret, irq; + + nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL); + if (!nfc) + return -ENOMEM; + + nfc->data = of_device_get_match_data(&pdev->dev); + if (!nfc->data) + return -ENODEV; + + nand_controller_init(&nfc->controller); + INIT_LIST_HEAD(&nfc->chips); + + nfc->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + nfc->reg_base = devm_ioremap_resource(dev, res); + if (IS_ERR(nfc->reg_base)) + return PTR_ERR(nfc->reg_base); + + nfc->reg_clk = + syscon_regmap_lookup_by_phandle(dev->of_node, + "amlogic,mmc-syscon"); + if (IS_ERR(nfc->reg_clk)) { + dev_err(dev, "Failed to lookup clock base\n"); + return PTR_ERR(nfc->reg_clk); + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "no NFC IRQ resource\n"); + return -EINVAL; + } + + ret = meson_nfc_clk_init(nfc); + if (ret) { + dev_err(dev, "failed to initialize NAND clock\n"); + return ret; + } + + writel(0, nfc->reg_base + NFC_REG_CFG); + ret = devm_request_irq(dev, irq, meson_nfc_irq, 0, dev_name(dev), nfc); + if (ret) { + dev_err(dev, "failed to request NFC IRQ\n"); + ret = -EINVAL; + goto err_clk; + } + + ret = dma_set_mask(dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(dev, "failed to set DMA mask\n"); + goto err_clk; + } + + platform_set_drvdata(pdev, nfc); + + ret = meson_nfc_nand_chips_init(dev, nfc); + if (ret) { + dev_err(dev, "failed to init NAND chips\n"); + goto err_clk; + } + + return 0; +err_clk: + meson_nfc_disable_clk(nfc); + return ret; +} + +static int meson_nfc_remove(struct platform_device *pdev) +{ + struct meson_nfc *nfc = platform_get_drvdata(pdev); + int ret; + + ret = meson_nfc_nand_chip_cleanup(nfc); + if (ret) + return ret; + + meson_nfc_disable_clk(nfc); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver meson_nfc_driver = { + .probe = meson_nfc_probe, + .remove = meson_nfc_remove, + .driver = { + .name = "meson-nand", + .of_match_table = meson_nfc_id_table, + }, +}; +module_platform_driver(meson_nfc_driver); + +MODULE_LICENSE("Dual MIT/GPL"); +MODULE_AUTHOR("Liang Yang <liang.yang@amlogic.com>"); +MODULE_DESCRIPTION("Amlogic's Meson NAND Flash Controller driver"); diff --git a/drivers/mtd/nand/raw/mtk_ecc.c b/drivers/mtd/nand/raw/mtk_ecc.c index 6432bd70c3b3..05b0c19d72d9 100644 --- a/drivers/mtd/nand/raw/mtk_ecc.c +++ b/drivers/mtd/nand/raw/mtk_ecc.c @@ -267,11 +267,15 @@ static struct mtk_ecc *mtk_ecc_get(struct device_node *np) struct mtk_ecc *ecc; pdev = of_find_device_by_node(np); - if (!pdev || !platform_get_drvdata(pdev)) + if (!pdev) return ERR_PTR(-EPROBE_DEFER); - get_device(&pdev->dev); ecc = platform_get_drvdata(pdev); + if (!ecc) { + put_device(&pdev->dev); + return ERR_PTR(-EPROBE_DEFER); + } + clk_prepare_enable(ecc->clk); mtk_ecc_hw_init(ecc); diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index b6b4602f5132..2c0e09187773 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -1451,8 +1451,7 @@ static int mtk_nfc_probe(struct platform_device *pdev) if (!nfc) return -ENOMEM; - spin_lock_init(&nfc->controller.lock); - init_waitqueue_head(&nfc->controller.wq); + nand_controller_init(&nfc->controller); INIT_LIST_HEAD(&nfc->chips); nfc->controller.ops = &mtk_nfc_controller_ops; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index cca4b24d2ffa..ddd396e93e32 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -278,11 +278,8 @@ EXPORT_SYMBOL_GPL(nand_deselect_target); static void nand_release_device(struct nand_chip *chip) { /* Release the controller and the chip */ - spin_lock(&chip->controller->lock); - chip->controller->active = NULL; - chip->state = FL_READY; - wake_up(&chip->controller->wq); - spin_unlock(&chip->controller->lock); + mutex_unlock(&chip->controller->lock); + mutex_unlock(&chip->lock); } /** @@ -331,57 +328,23 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs) } /** - * panic_nand_get_device - [GENERIC] Get chip for selected access - * @chip: the nand chip descriptor - * @new_state: the state which is requested - * - * Used when in panic, no locks are taken. - */ -static void panic_nand_get_device(struct nand_chip *chip, int new_state) -{ - /* Hardware controller shared among independent devices */ - chip->controller->active = chip; - chip->state = new_state; -} - -/** * nand_get_device - [GENERIC] Get chip for selected access * @chip: NAND chip structure - * @new_state: the state which is requested * - * Get the device and lock it for exclusive access + * Lock the device and its controller for exclusive access + * + * Return: -EBUSY if the chip has been suspended, 0 otherwise */ -static int -nand_get_device(struct nand_chip *chip, int new_state) +static int nand_get_device(struct nand_chip *chip) { - spinlock_t *lock = &chip->controller->lock; - wait_queue_head_t *wq = &chip->controller->wq; - DECLARE_WAITQUEUE(wait, current); -retry: - spin_lock(lock); - - /* Hardware controller shared among independent devices */ - if (!chip->controller->active) - chip->controller->active = chip; - - if (chip->controller->active == chip && chip->state == FL_READY) { - chip->state = new_state; - spin_unlock(lock); - return 0; - } - if (new_state == FL_PM_SUSPENDED) { - if (chip->controller->active->state == FL_PM_SUSPENDED) { - chip->state = FL_PM_SUSPENDED; - spin_unlock(lock); - return 0; - } + mutex_lock(&chip->lock); + if (chip->suspended) { + mutex_unlock(&chip->lock); + return -EBUSY; } - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(wq, &wait); - spin_unlock(lock); - schedule(); - remove_wait_queue(wq, &wait); - goto retry; + mutex_lock(&chip->controller->lock); + + return 0; } /** @@ -410,6 +373,7 @@ static int nand_check_wp(struct nand_chip *chip) /** * nand_fill_oob - [INTERN] Transfer client buffer to oob + * @chip: NAND chip object * @oob: oob data buffer * @len: oob data write length * @ops: oob ops structure @@ -457,7 +421,7 @@ static int nand_do_write_oob(struct nand_chip *chip, loff_t to, struct mtd_oob_ops *ops) { struct mtd_info *mtd = nand_to_mtd(chip); - int chipnr, page, status, len; + int chipnr, page, status, len, ret; pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to, (int)ops->ooblen); @@ -479,7 +443,9 @@ static int nand_do_write_oob(struct nand_chip *chip, loff_t to, * if we don't do this. I have no clue why, but I seem to have 'fixed' * it in the doc2000 driver in August 1999. dwmw2. */ - nand_reset(chip, chipnr); + ret = nand_reset(chip, chipnr); + if (ret) + return ret; nand_select_target(chip, chipnr); @@ -602,7 +568,10 @@ static int nand_block_markbad_lowlevel(struct nand_chip *chip, loff_t ofs) nand_erase_nand(chip, &einfo, 0); /* Write bad block marker to OOB */ - nand_get_device(chip, FL_WRITING); + ret = nand_get_device(chip); + if (ret) + return ret; + ret = nand_markbad_bbm(chip, ofs); nand_release_device(chip); } @@ -3580,7 +3549,9 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, ops->mode != MTD_OPS_RAW) return -ENOTSUPP; - nand_get_device(chip, FL_READING); + ret = nand_get_device(chip); + if (ret) + return ret; if (!ops->datbuf) ret = nand_do_read_oob(chip, from, ops); @@ -4099,9 +4070,6 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len, struct mtd_oob_ops ops; int ret; - /* Grab the device */ - panic_nand_get_device(chip, FL_WRITING); - nand_select_target(chip, chipnr); /* Wait for the device to get ready */ @@ -4132,7 +4100,9 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, ops->retlen = 0; - nand_get_device(chip, FL_WRITING); + ret = nand_get_device(chip); + if (ret) + return ret; switch (ops->mode) { case MTD_OPS_PLACE_OOB: @@ -4155,23 +4125,6 @@ out: } /** - * single_erase - [GENERIC] NAND standard block erase command function - * @chip: NAND chip object - * @page: the page address of the block which will be erased - * - * Standard erase command for NAND chips. Returns NAND status. - */ -static int single_erase(struct nand_chip *chip, int page) -{ - unsigned int eraseblock; - - /* Send commands to erase a block */ - eraseblock = page >> (chip->phys_erase_shift - chip->page_shift); - - return nand_erase_op(chip, eraseblock); -} - -/** * nand_erase - [MTD Interface] erase block(s) * @mtd: MTD device structure * @instr: erase instruction @@ -4194,7 +4147,7 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr) int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, int allowbbt) { - int page, status, pages_per_block, ret, chipnr; + int page, pages_per_block, ret, chipnr; loff_t len; pr_debug("%s: start = 0x%012llx, len = %llu\n", @@ -4205,7 +4158,9 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, return -EINVAL; /* Grab the lock and see if the device is available */ - nand_get_device(chip, FL_ERASING); + ret = nand_get_device(chip); + if (ret) + return ret; /* Shift to get first page */ page = (int)(instr->addr >> chip->page_shift); @@ -4246,17 +4201,11 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, (page + pages_per_block)) chip->pagebuf = -1; - if (chip->legacy.erase) - status = chip->legacy.erase(chip, - page & chip->pagemask); - else - status = single_erase(chip, page & chip->pagemask); - - /* See if block erase succeeded */ - if (status) { + ret = nand_erase_op(chip, (page & chip->pagemask) >> + (chip->phys_erase_shift - chip->page_shift)); + if (ret) { pr_debug("%s: failed erase, page 0x%08x\n", __func__, page); - ret = -EIO; instr->fail_addr = ((loff_t)page << chip->page_shift); goto erase_exit; @@ -4298,7 +4247,7 @@ static void nand_sync(struct mtd_info *mtd) pr_debug("%s: called\n", __func__); /* Grab the lock and see if the device is available */ - nand_get_device(chip, FL_SYNCING); + WARN_ON(nand_get_device(chip)); /* Release it and go back */ nand_release_device(chip); } @@ -4315,7 +4264,10 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) int ret; /* Select the NAND device */ - nand_get_device(chip, FL_READING); + ret = nand_get_device(chip); + if (ret) + return ret; + nand_select_target(chip, chipnr); ret = nand_block_checkbad(chip, offs, 0); @@ -4388,7 +4340,13 @@ static int nand_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len) */ static int nand_suspend(struct mtd_info *mtd) { - return nand_get_device(mtd_to_nand(mtd), FL_PM_SUSPENDED); + struct nand_chip *chip = mtd_to_nand(mtd); + + mutex_lock(&chip->lock); + chip->suspended = 1; + mutex_unlock(&chip->lock); + + return 0; } /** @@ -4399,11 +4357,13 @@ static void nand_resume(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - if (chip->state == FL_PM_SUSPENDED) - nand_release_device(chip); + mutex_lock(&chip->lock); + if (chip->suspended) + chip->suspended = 0; else pr_err("%s called for a chip which is not in suspended state\n", __func__); + mutex_unlock(&chip->lock); } /** @@ -4413,7 +4373,7 @@ static void nand_resume(struct mtd_info *mtd) */ static void nand_shutdown(struct mtd_info *mtd) { - nand_get_device(mtd_to_nand(mtd), FL_PM_SUSPENDED); + nand_suspend(mtd); } /* Set default functions */ @@ -5018,6 +4978,8 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, /* Assume all dies are deselected when we enter nand_scan_ident(). */ chip->cur_cs = -1; + mutex_init(&chip->lock); + /* Enforce the right timings for reset/detection */ onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0); @@ -5060,11 +5022,15 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, u8 id[2]; /* See comment in nand_get_flash_type for reset */ - nand_reset(chip, i); + ret = nand_reset(chip, i); + if (ret) + break; nand_select_target(chip, i); /* Send the command for reading device ID */ - nand_readid_op(chip, 0, id, sizeof(id)); + ret = nand_readid_op(chip, 0, id, sizeof(id)); + if (ret) + break; /* Read manufacturer and device IDs */ if (nand_maf_id != id[0] || nand_dev_id != id[1]) { nand_deselect_target(chip); @@ -5555,6 +5521,7 @@ static int nand_scan_tail(struct nand_chip *chip) } if (!ecc->read_page) ecc->read_page = nand_read_page_hwecc_oob_first; + /* fall through */ case NAND_ECC_HW: /* Use standard hwecc read page function? */ @@ -5574,6 +5541,7 @@ static int nand_scan_tail(struct nand_chip *chip) ecc->read_subpage = nand_read_subpage; if (!ecc->write_subpage && ecc->hwctl && ecc->calculate) ecc->write_subpage = nand_write_subpage_hwecc; + /* fall through */ case NAND_ECC_HW_SYNDROME: if ((!ecc->calculate || !ecc->correct || !ecc->hwctl) && @@ -5611,6 +5579,7 @@ static int nand_scan_tail(struct nand_chip *chip) ecc->size, mtd->writesize); ecc->mode = NAND_ECC_SOFT; ecc->algo = NAND_ECC_HAMMING; + /* fall through */ case NAND_ECC_SOFT: ret = nand_set_ecc_soft_ops(chip); @@ -5717,9 +5686,6 @@ static int nand_scan_tail(struct nand_chip *chip) } chip->subpagesize = mtd->writesize >> mtd->subpage_sft; - /* Initialize state */ - chip->state = FL_READY; - /* Invalidate the pagebuffer reference */ chip->pagebuf = -1; diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c index 1b722fe9213c..19a2b563acdf 100644 --- a/drivers/mtd/nand/raw/nand_bbt.c +++ b/drivers/mtd/nand/raw/nand_bbt.c @@ -158,7 +158,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td) /** * read_bbt - [GENERIC] Read the bad block table starting from page - * @chip: NAND chip object + * @this: NAND chip object * @buf: temporary buffer * @page: the starting page * @num: the number of bbt descriptors to read diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c index 43575943f13b..f2526ec616a6 100644 --- a/drivers/mtd/nand/raw/nand_legacy.c +++ b/drivers/mtd/nand/raw/nand_legacy.c @@ -331,6 +331,7 @@ static void nand_command(struct nand_chip *chip, unsigned int command, */ if (column == -1 && page_addr == -1) return; + /* fall through */ default: /* @@ -483,7 +484,7 @@ static void nand_command_lp(struct nand_chip *chip, unsigned int command, chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); - /* This applies to read commands */ + /* fall through - This applies to read commands */ default: /* * If we don't have access to the busy pin, we apply the given diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index 68e8b9f7f372..8f280a2962c8 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -994,12 +994,9 @@ static int omap_wait(struct nand_chip *this) { struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(this)); unsigned long timeo = jiffies; - int status, state = this->state; + int status; - if (state == FL_ERASING) - timeo += msecs_to_jiffies(400); - else - timeo += msecs_to_jiffies(20); + timeo += msecs_to_jiffies(400); writeb(NAND_CMD_STATUS & 0xFF, info->reg.gpmc_nand_command); while (time_before(jiffies, timeo)) { @@ -2173,11 +2170,8 @@ static const struct nand_controller_ops omap_nand_controller_ops = { }; /* Shared among all NAND instances to synchronize access to the ECC Engine */ -static struct nand_controller omap_gpmc_controller = { - .lock = __SPIN_LOCK_UNLOCKED(omap_gpmc_controller.lock), - .wq = __WAIT_QUEUE_HEAD_INITIALIZER(omap_gpmc_controller.wq), - .ops = &omap_nand_controller_ops, -}; +static struct nand_controller omap_gpmc_controller; +static bool omap_gpmc_controller_initialized; static int omap_nand_probe(struct platform_device *pdev) { @@ -2227,6 +2221,12 @@ static int omap_nand_probe(struct platform_device *pdev) info->phys_base = res->start; + if (!omap_gpmc_controller_initialized) { + omap_gpmc_controller.ops = &omap_nand_controller_ops; + nand_controller_init(&omap_gpmc_controller); + omap_gpmc_controller_initialized = true; + } + nand_chip->controller = &omap_gpmc_controller; nand_chip->legacy.IO_ADDR_W = nand_chip->legacy.IO_ADDR_R; diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 46c62a31fa46..920e7375084f 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2833,6 +2833,16 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc, if (ret) return ret; + if (nandc->props->is_bam) { + free_bam_transaction(nandc); + nandc->bam_txn = alloc_bam_transaction(nandc); + if (!nandc->bam_txn) { + dev_err(nandc->dev, + "failed to allocate bam transaction\n"); + return -ENOMEM; + } + } + ret = mtd_device_register(mtd, NULL, 0); if (ret) nand_cleanup(chip); @@ -2847,16 +2857,6 @@ static int qcom_probe_nand_devices(struct qcom_nand_controller *nandc) struct qcom_nand_host *host; int ret; - if (nandc->props->is_bam) { - free_bam_transaction(nandc); - nandc->bam_txn = alloc_bam_transaction(nandc); - if (!nandc->bam_txn) { - dev_err(nandc->dev, - "failed to allocate bam transaction\n"); - return -ENOMEM; - } - } - for_each_available_child_of_node(dn, child) { host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); if (!host) { diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index c01422d953dd..86456216fb93 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -369,8 +369,7 @@ static int r852_wait(struct nand_chip *chip) unsigned long timeout; u8 status; - timeout = jiffies + (chip->state == FL_ERASING ? - msecs_to_jiffies(400) : msecs_to_jiffies(20)); + timeout = jiffies + msecs_to_jiffies(400); while (time_before(jiffies, timeout)) if (chip->legacy.dev_ready(chip)) diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c new file mode 100644 index 000000000000..999ca6a66036 --- /dev/null +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -0,0 +1,2073 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2018 + * Author: Christophe Kerello <christophe.kerello@st.com> + */ + +#include <linux/clk.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/iopoll.h> +#include <linux/module.h> +#include <linux/mtd/rawnand.h> +#include <linux/pinctrl/consumer.h> +#include <linux/platform_device.h> +#include <linux/reset.h> + +/* Bad block marker length */ +#define FMC2_BBM_LEN 2 + +/* ECC step size */ +#define FMC2_ECC_STEP_SIZE 512 + +/* BCHDSRx registers length */ +#define FMC2_BCHDSRS_LEN 20 + +/* HECCR length */ +#define FMC2_HECCR_LEN 4 + +/* Max requests done for a 8k nand page size */ +#define FMC2_MAX_SG 16 + +/* Max chip enable */ +#define FMC2_MAX_CE 2 + +/* Max ECC buffer length */ +#define FMC2_MAX_ECC_BUF_LEN (FMC2_BCHDSRS_LEN * FMC2_MAX_SG) + +/* Timings */ +#define FMC2_THIZ 1 +#define FMC2_TIO 8000 +#define FMC2_TSYNC 3000 +#define FMC2_PCR_TIMING_MASK 0xf +#define FMC2_PMEM_PATT_TIMING_MASK 0xff + +/* FMC2 Controller Registers */ +#define FMC2_BCR1 0x0 +#define FMC2_PCR 0x80 +#define FMC2_SR 0x84 +#define FMC2_PMEM 0x88 +#define FMC2_PATT 0x8c +#define FMC2_HECCR 0x94 +#define FMC2_CSQCR 0x200 +#define FMC2_CSQCFGR1 0x204 +#define FMC2_CSQCFGR2 0x208 +#define FMC2_CSQCFGR3 0x20c +#define FMC2_CSQAR1 0x210 +#define FMC2_CSQAR2 0x214 +#define FMC2_CSQIER 0x220 +#define FMC2_CSQISR 0x224 +#define FMC2_CSQICR 0x228 +#define FMC2_CSQEMSR 0x230 +#define FMC2_BCHIER 0x250 +#define FMC2_BCHISR 0x254 +#define FMC2_BCHICR 0x258 +#define FMC2_BCHPBR1 0x260 +#define FMC2_BCHPBR2 0x264 +#define FMC2_BCHPBR3 0x268 +#define FMC2_BCHPBR4 0x26c +#define FMC2_BCHDSR0 0x27c +#define FMC2_BCHDSR1 0x280 +#define FMC2_BCHDSR2 0x284 +#define FMC2_BCHDSR3 0x288 +#define FMC2_BCHDSR4 0x28c + +/* Register: FMC2_BCR1 */ +#define FMC2_BCR1_FMC2EN BIT(31) + +/* Register: FMC2_PCR */ +#define FMC2_PCR_PWAITEN BIT(1) +#define FMC2_PCR_PBKEN BIT(2) +#define FMC2_PCR_PWID_MASK GENMASK(5, 4) +#define FMC2_PCR_PWID(x) (((x) & 0x3) << 4) +#define FMC2_PCR_PWID_BUSWIDTH_8 0 +#define FMC2_PCR_PWID_BUSWIDTH_16 1 +#define FMC2_PCR_ECCEN BIT(6) +#define FMC2_PCR_ECCALG BIT(8) +#define FMC2_PCR_TCLR_MASK GENMASK(12, 9) +#define FMC2_PCR_TCLR(x) (((x) & 0xf) << 9) +#define FMC2_PCR_TCLR_DEFAULT 0xf +#define FMC2_PCR_TAR_MASK GENMASK(16, 13) +#define FMC2_PCR_TAR(x) (((x) & 0xf) << 13) +#define FMC2_PCR_TAR_DEFAULT 0xf +#define FMC2_PCR_ECCSS_MASK GENMASK(19, 17) +#define FMC2_PCR_ECCSS(x) (((x) & 0x7) << 17) +#define FMC2_PCR_ECCSS_512 1 +#define FMC2_PCR_ECCSS_2048 3 +#define FMC2_PCR_BCHECC BIT(24) +#define FMC2_PCR_WEN BIT(25) + +/* Register: FMC2_SR */ +#define FMC2_SR_NWRF BIT(6) + +/* Register: FMC2_PMEM */ +#define FMC2_PMEM_MEMSET(x) (((x) & 0xff) << 0) +#define FMC2_PMEM_MEMWAIT(x) (((x) & 0xff) << 8) +#define FMC2_PMEM_MEMHOLD(x) (((x) & 0xff) << 16) +#define FMC2_PMEM_MEMHIZ(x) (((x) & 0xff) << 24) +#define FMC2_PMEM_DEFAULT 0x0a0a0a0a + +/* Register: FMC2_PATT */ +#define FMC2_PATT_ATTSET(x) (((x) & 0xff) << 0) +#define FMC2_PATT_ATTWAIT(x) (((x) & 0xff) << 8) +#define FMC2_PATT_ATTHOLD(x) (((x) & 0xff) << 16) +#define FMC2_PATT_ATTHIZ(x) (((x) & 0xff) << 24) +#define FMC2_PATT_DEFAULT 0x0a0a0a0a + +/* Register: FMC2_CSQCR */ +#define FMC2_CSQCR_CSQSTART BIT(0) + +/* Register: FMC2_CSQCFGR1 */ +#define FMC2_CSQCFGR1_CMD2EN BIT(1) +#define FMC2_CSQCFGR1_DMADEN BIT(2) +#define FMC2_CSQCFGR1_ACYNBR(x) (((x) & 0x7) << 4) +#define FMC2_CSQCFGR1_CMD1(x) (((x) & 0xff) << 8) +#define FMC2_CSQCFGR1_CMD2(x) (((x) & 0xff) << 16) +#define FMC2_CSQCFGR1_CMD1T BIT(24) +#define FMC2_CSQCFGR1_CMD2T BIT(25) + +/* Register: FMC2_CSQCFGR2 */ +#define FMC2_CSQCFGR2_SQSDTEN BIT(0) +#define FMC2_CSQCFGR2_RCMD2EN BIT(1) +#define FMC2_CSQCFGR2_DMASEN BIT(2) +#define FMC2_CSQCFGR2_RCMD1(x) (((x) & 0xff) << 8) +#define FMC2_CSQCFGR2_RCMD2(x) (((x) & 0xff) << 16) +#define FMC2_CSQCFGR2_RCMD1T BIT(24) +#define FMC2_CSQCFGR2_RCMD2T BIT(25) + +/* Register: FMC2_CSQCFGR3 */ +#define FMC2_CSQCFGR3_SNBR(x) (((x) & 0x1f) << 8) +#define FMC2_CSQCFGR3_AC1T BIT(16) +#define FMC2_CSQCFGR3_AC2T BIT(17) +#define FMC2_CSQCFGR3_AC3T BIT(18) +#define FMC2_CSQCFGR3_AC4T BIT(19) +#define FMC2_CSQCFGR3_AC5T BIT(20) +#define FMC2_CSQCFGR3_SDT BIT(21) +#define FMC2_CSQCFGR3_RAC1T BIT(22) +#define FMC2_CSQCFGR3_RAC2T BIT(23) + +/* Register: FMC2_CSQCAR1 */ +#define FMC2_CSQCAR1_ADDC1(x) (((x) & 0xff) << 0) +#define FMC2_CSQCAR1_ADDC2(x) (((x) & 0xff) << 8) +#define FMC2_CSQCAR1_ADDC3(x) (((x) & 0xff) << 16) +#define FMC2_CSQCAR1_ADDC4(x) (((x) & 0xff) << 24) + +/* Register: FMC2_CSQCAR2 */ +#define FMC2_CSQCAR2_ADDC5(x) (((x) & 0xff) << 0) +#define FMC2_CSQCAR2_NANDCEN(x) (((x) & 0x3) << 10) +#define FMC2_CSQCAR2_SAO(x) (((x) & 0xffff) << 16) + +/* Register: FMC2_CSQIER */ +#define FMC2_CSQIER_TCIE BIT(0) + +/* Register: FMC2_CSQICR */ +#define FMC2_CSQICR_CLEAR_IRQ GENMASK(4, 0) + +/* Register: FMC2_CSQEMSR */ +#define FMC2_CSQEMSR_SEM GENMASK(15, 0) + +/* Register: FMC2_BCHIER */ +#define FMC2_BCHIER_DERIE BIT(1) +#define FMC2_BCHIER_EPBRIE BIT(4) + +/* Register: FMC2_BCHICR */ +#define FMC2_BCHICR_CLEAR_IRQ GENMASK(4, 0) + +/* Register: FMC2_BCHDSR0 */ +#define FMC2_BCHDSR0_DUE BIT(0) +#define FMC2_BCHDSR0_DEF BIT(1) +#define FMC2_BCHDSR0_DEN_MASK GENMASK(7, 4) +#define FMC2_BCHDSR0_DEN_SHIFT 4 + +/* Register: FMC2_BCHDSR1 */ +#define FMC2_BCHDSR1_EBP1_MASK GENMASK(12, 0) +#define FMC2_BCHDSR1_EBP2_MASK GENMASK(28, 16) +#define FMC2_BCHDSR1_EBP2_SHIFT 16 + +/* Register: FMC2_BCHDSR2 */ +#define FMC2_BCHDSR2_EBP3_MASK GENMASK(12, 0) +#define FMC2_BCHDSR2_EBP4_MASK GENMASK(28, 16) +#define FMC2_BCHDSR2_EBP4_SHIFT 16 + +/* Register: FMC2_BCHDSR3 */ +#define FMC2_BCHDSR3_EBP5_MASK GENMASK(12, 0) +#define FMC2_BCHDSR3_EBP6_MASK GENMASK(28, 16) +#define FMC2_BCHDSR3_EBP6_SHIFT 16 + +/* Register: FMC2_BCHDSR4 */ +#define FMC2_BCHDSR4_EBP7_MASK GENMASK(12, 0) +#define FMC2_BCHDSR4_EBP8_MASK GENMASK(28, 16) +#define FMC2_BCHDSR4_EBP8_SHIFT 16 + +enum stm32_fmc2_ecc { + FMC2_ECC_HAM = 1, + FMC2_ECC_BCH4 = 4, + FMC2_ECC_BCH8 = 8 +}; + +enum stm32_fmc2_irq_state { + FMC2_IRQ_UNKNOWN = 0, + FMC2_IRQ_BCH, + FMC2_IRQ_SEQ +}; + +struct stm32_fmc2_timings { + u8 tclr; + u8 tar; + u8 thiz; + u8 twait; + u8 thold_mem; + u8 tset_mem; + u8 thold_att; + u8 tset_att; +}; + +struct stm32_fmc2_nand { + struct nand_chip chip; + struct stm32_fmc2_timings timings; + int ncs; + int cs_used[FMC2_MAX_CE]; +}; + +static inline struct stm32_fmc2_nand *to_fmc2_nand(struct nand_chip *chip) +{ + return container_of(chip, struct stm32_fmc2_nand, chip); +} + +struct stm32_fmc2_nfc { + struct nand_controller base; + struct stm32_fmc2_nand nand; + struct device *dev; + void __iomem *io_base; + void __iomem *data_base[FMC2_MAX_CE]; + void __iomem *cmd_base[FMC2_MAX_CE]; + void __iomem *addr_base[FMC2_MAX_CE]; + phys_addr_t io_phys_addr; + phys_addr_t data_phys_addr[FMC2_MAX_CE]; + struct clk *clk; + u8 irq_state; + + struct dma_chan *dma_tx_ch; + struct dma_chan *dma_rx_ch; + struct dma_chan *dma_ecc_ch; + struct sg_table dma_data_sg; + struct sg_table dma_ecc_sg; + u8 *ecc_buf; + int dma_ecc_len; + + struct completion complete; + struct completion dma_data_complete; + struct completion dma_ecc_complete; + + u8 cs_assigned; + int cs_sel; +}; + +static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_controller *base) +{ + return container_of(base, struct stm32_fmc2_nfc, base); +} + +/* Timings configuration */ +static void stm32_fmc2_timings_init(struct nand_chip *chip) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); + struct stm32_fmc2_timings *timings = &nand->timings; + u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR); + u32 pmem, patt; + + /* Set tclr/tar timings */ + pcr &= ~FMC2_PCR_TCLR_MASK; + pcr |= FMC2_PCR_TCLR(timings->tclr); + pcr &= ~FMC2_PCR_TAR_MASK; + pcr |= FMC2_PCR_TAR(timings->tar); + + /* Set tset/twait/thold/thiz timings in common bank */ + pmem = FMC2_PMEM_MEMSET(timings->tset_mem); + pmem |= FMC2_PMEM_MEMWAIT(timings->twait); + pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem); + pmem |= FMC2_PMEM_MEMHIZ(timings->thiz); + + /* Set tset/twait/thold/thiz timings in attribut bank */ + patt = FMC2_PATT_ATTSET(timings->tset_att); + patt |= FMC2_PATT_ATTWAIT(timings->twait); + patt |= FMC2_PATT_ATTHOLD(timings->thold_att); + patt |= FMC2_PATT_ATTHIZ(timings->thiz); + + writel_relaxed(pcr, fmc2->io_base + FMC2_PCR); + writel_relaxed(pmem, fmc2->io_base + FMC2_PMEM); + writel_relaxed(patt, fmc2->io_base + FMC2_PATT); +} + +/* Controller configuration */ +static void stm32_fmc2_setup(struct nand_chip *chip) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR); + + /* Configure ECC algorithm (default configuration is Hamming) */ + pcr &= ~FMC2_PCR_ECCALG; + pcr &= ~FMC2_PCR_BCHECC; + if (chip->ecc.strength == FMC2_ECC_BCH8) { + pcr |= FMC2_PCR_ECCALG; + pcr |= FMC2_PCR_BCHECC; + } else if (chip->ecc.strength == FMC2_ECC_BCH4) { + pcr |= FMC2_PCR_ECCALG; + } + + /* Set buswidth */ + pcr &= ~FMC2_PCR_PWID_MASK; + if (chip->options & NAND_BUSWIDTH_16) + pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16); + + /* Set ECC sector size */ + pcr &= ~FMC2_PCR_ECCSS_MASK; + pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512); + + writel_relaxed(pcr, fmc2->io_base + FMC2_PCR); +} + +/* Select target */ +static int stm32_fmc2_select_chip(struct nand_chip *chip, int chipnr) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); + struct dma_slave_config dma_cfg; + int ret; + + if (nand->cs_used[chipnr] == fmc2->cs_sel) + return 0; + + fmc2->cs_sel = nand->cs_used[chipnr]; + + /* FMC2 setup routine */ + stm32_fmc2_setup(chip); + + /* Apply timings */ + stm32_fmc2_timings_init(chip); + + if (fmc2->dma_tx_ch && fmc2->dma_rx_ch) { + memset(&dma_cfg, 0, sizeof(dma_cfg)); + dma_cfg.src_addr = fmc2->data_phys_addr[fmc2->cs_sel]; + dma_cfg.dst_addr = fmc2->data_phys_addr[fmc2->cs_sel]; + dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + dma_cfg.src_maxburst = 32; + dma_cfg.dst_maxburst = 32; + + ret = dmaengine_slave_config(fmc2->dma_tx_ch, &dma_cfg); + if (ret) { + dev_err(fmc2->dev, "tx DMA engine slave config failed\n"); + return ret; + } + + ret = dmaengine_slave_config(fmc2->dma_rx_ch, &dma_cfg); + if (ret) { + dev_err(fmc2->dev, "rx DMA engine slave config failed\n"); + return ret; + } + } + + if (fmc2->dma_ecc_ch) { + /* + * Hamming: we read HECCR register + * BCH4/BCH8: we read BCHDSRSx registers + */ + memset(&dma_cfg, 0, sizeof(dma_cfg)); + dma_cfg.src_addr = fmc2->io_phys_addr; + dma_cfg.src_addr += chip->ecc.strength == FMC2_ECC_HAM ? + FMC2_HECCR : FMC2_BCHDSR0; + dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + + ret = dmaengine_slave_config(fmc2->dma_ecc_ch, &dma_cfg); + if (ret) { + dev_err(fmc2->dev, "ECC DMA engine slave config failed\n"); + return ret; + } + + /* Calculate ECC length needed for one sector */ + fmc2->dma_ecc_len = chip->ecc.strength == FMC2_ECC_HAM ? + FMC2_HECCR_LEN : FMC2_BCHDSRS_LEN; + } + + return 0; +} + +/* Set bus width to 16-bit or 8-bit */ +static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set) +{ + u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR); + + pcr &= ~FMC2_PCR_PWID_MASK; + if (set) + pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16); + writel_relaxed(pcr, fmc2->io_base + FMC2_PCR); +} + +/* Enable/disable ECC */ +static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable) +{ + u32 pcr = readl(fmc2->io_base + FMC2_PCR); + + pcr &= ~FMC2_PCR_ECCEN; + if (enable) + pcr |= FMC2_PCR_ECCEN; + writel(pcr, fmc2->io_base + FMC2_PCR); +} + +/* Enable irq sources in case of the sequencer is used */ +static inline void stm32_fmc2_enable_seq_irq(struct stm32_fmc2_nfc *fmc2) +{ + u32 csqier = readl_relaxed(fmc2->io_base + FMC2_CSQIER); + + csqier |= FMC2_CSQIER_TCIE; + + fmc2->irq_state = FMC2_IRQ_SEQ; + + writel_relaxed(csqier, fmc2->io_base + FMC2_CSQIER); +} + +/* Disable irq sources in case of the sequencer is used */ +static inline void stm32_fmc2_disable_seq_irq(struct stm32_fmc2_nfc *fmc2) +{ + u32 csqier = readl_relaxed(fmc2->io_base + FMC2_CSQIER); + + csqier &= ~FMC2_CSQIER_TCIE; + + writel_relaxed(csqier, fmc2->io_base + FMC2_CSQIER); + + fmc2->irq_state = FMC2_IRQ_UNKNOWN; +} + +/* Clear irq sources in case of the sequencer is used */ +static inline void stm32_fmc2_clear_seq_irq(struct stm32_fmc2_nfc *fmc2) +{ + writel_relaxed(FMC2_CSQICR_CLEAR_IRQ, fmc2->io_base + FMC2_CSQICR); +} + +/* Enable irq sources in case of bch is used */ +static inline void stm32_fmc2_enable_bch_irq(struct stm32_fmc2_nfc *fmc2, + int mode) +{ + u32 bchier = readl_relaxed(fmc2->io_base + FMC2_BCHIER); + + if (mode == NAND_ECC_WRITE) + bchier |= FMC2_BCHIER_EPBRIE; + else + bchier |= FMC2_BCHIER_DERIE; + + fmc2->irq_state = FMC2_IRQ_BCH; + + writel_relaxed(bchier, fmc2->io_base + FMC2_BCHIER); +} + +/* Disable irq sources in case of bch is used */ +static inline void stm32_fmc2_disable_bch_irq(struct stm32_fmc2_nfc *fmc2) +{ + u32 bchier = readl_relaxed(fmc2->io_base + FMC2_BCHIER); + + bchier &= ~FMC2_BCHIER_DERIE; + bchier &= ~FMC2_BCHIER_EPBRIE; + + writel_relaxed(bchier, fmc2->io_base + FMC2_BCHIER); + + fmc2->irq_state = FMC2_IRQ_UNKNOWN; +} + +/* Clear irq sources in case of bch is used */ +static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2) +{ + writel_relaxed(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR); +} + +/* + * Enable ECC logic and reset syndrome/parity bits previously calculated + * Syndrome/parity bits is cleared by setting the ECCEN bit to 0 + */ +static void stm32_fmc2_hwctl(struct nand_chip *chip, int mode) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + + stm32_fmc2_set_ecc(fmc2, false); + + if (chip->ecc.strength != FMC2_ECC_HAM) { + u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR); + + if (mode == NAND_ECC_WRITE) + pcr |= FMC2_PCR_WEN; + else + pcr &= ~FMC2_PCR_WEN; + writel_relaxed(pcr, fmc2->io_base + FMC2_PCR); + + reinit_completion(&fmc2->complete); + stm32_fmc2_clear_bch_irq(fmc2); + stm32_fmc2_enable_bch_irq(fmc2, mode); + } + + stm32_fmc2_set_ecc(fmc2, true); +} + +/* + * ECC Hamming calculation + * ECC is 3 bytes for 512 bytes of data (supports error correction up to + * max of 1-bit) + */ +static inline void stm32_fmc2_ham_set_ecc(const u32 ecc_sta, u8 *ecc) +{ + ecc[0] = ecc_sta; + ecc[1] = ecc_sta >> 8; + ecc[2] = ecc_sta >> 16; +} + +static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data, + u8 *ecc) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + u32 sr, heccr; + int ret; + + ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR, + sr, sr & FMC2_SR_NWRF, 10, 1000); + if (ret) { + dev_err(fmc2->dev, "ham timeout\n"); + return ret; + } + + heccr = readl_relaxed(fmc2->io_base + FMC2_HECCR); + + stm32_fmc2_ham_set_ecc(heccr, ecc); + + /* Disable ECC */ + stm32_fmc2_set_ecc(fmc2, false); + + return 0; +} + +static int stm32_fmc2_ham_correct(struct nand_chip *chip, u8 *dat, + u8 *read_ecc, u8 *calc_ecc) +{ + u8 bit_position = 0, b0, b1, b2; + u32 byte_addr = 0, b; + u32 i, shifting = 1; + + /* Indicate which bit and byte is faulty (if any) */ + b0 = read_ecc[0] ^ calc_ecc[0]; + b1 = read_ecc[1] ^ calc_ecc[1]; + b2 = read_ecc[2] ^ calc_ecc[2]; + b = b0 | (b1 << 8) | (b2 << 16); + + /* No errors */ + if (likely(!b)) + return 0; + + /* Calculate bit position */ + for (i = 0; i < 3; i++) { + switch (b % 4) { + case 2: + bit_position += shifting; + case 1: + break; + default: + return -EBADMSG; + } + shifting <<= 1; + b >>= 2; + } + + /* Calculate byte position */ + shifting = 1; + for (i = 0; i < 9; i++) { + switch (b % 4) { + case 2: + byte_addr += shifting; + case 1: + break; + default: + return -EBADMSG; + } + shifting <<= 1; + b >>= 2; + } + + /* Flip the bit */ + dat[byte_addr] ^= (1 << bit_position); + + return 1; +} + +/* + * ECC BCH calculation and correction + * ECC is 7/13 bytes for 512 bytes of data (supports error correction up to + * max of 4-bit/8-bit) + */ +static int stm32_fmc2_bch_calculate(struct nand_chip *chip, const u8 *data, + u8 *ecc) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + u32 bchpbr; + + /* Wait until the BCH code is ready */ + if (!wait_for_completion_timeout(&fmc2->complete, + msecs_to_jiffies(1000))) { + dev_err(fmc2->dev, "bch timeout\n"); + stm32_fmc2_disable_bch_irq(fmc2); + return -ETIMEDOUT; + } + + /* Read parity bits */ + bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR1); + ecc[0] = bchpbr; + ecc[1] = bchpbr >> 8; + ecc[2] = bchpbr >> 16; + ecc[3] = bchpbr >> 24; + + bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR2); + ecc[4] = bchpbr; + ecc[5] = bchpbr >> 8; + ecc[6] = bchpbr >> 16; + + if (chip->ecc.strength == FMC2_ECC_BCH8) { + ecc[7] = bchpbr >> 24; + + bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR3); + ecc[8] = bchpbr; + ecc[9] = bchpbr >> 8; + ecc[10] = bchpbr >> 16; + ecc[11] = bchpbr >> 24; + + bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR4); + ecc[12] = bchpbr; + } + + /* Disable ECC */ + stm32_fmc2_set_ecc(fmc2, false); + + return 0; +} + +/* BCH algorithm correction */ +static int stm32_fmc2_bch_decode(int eccsize, u8 *dat, u32 *ecc_sta) +{ + u32 bchdsr0 = ecc_sta[0]; + u32 bchdsr1 = ecc_sta[1]; + u32 bchdsr2 = ecc_sta[2]; + u32 bchdsr3 = ecc_sta[3]; + u32 bchdsr4 = ecc_sta[4]; + u16 pos[8]; + int i, den; + unsigned int nb_errs = 0; + + /* No errors found */ + if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF))) + return 0; + + /* Too many errors detected */ + if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE)) + return -EBADMSG; + + pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK; + pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT; + pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK; + pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT; + pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK; + pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT; + pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK; + pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT; + + den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT; + for (i = 0; i < den; i++) { + if (pos[i] < eccsize * 8) { + change_bit(pos[i], (unsigned long *)dat); + nb_errs++; + } + } + + return nb_errs; +} + +static int stm32_fmc2_bch_correct(struct nand_chip *chip, u8 *dat, + u8 *read_ecc, u8 *calc_ecc) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + u32 ecc_sta[5]; + + /* Wait until the decoding error is ready */ + if (!wait_for_completion_timeout(&fmc2->complete, + msecs_to_jiffies(1000))) { + dev_err(fmc2->dev, "bch timeout\n"); + stm32_fmc2_disable_bch_irq(fmc2); + return -ETIMEDOUT; + } + + ecc_sta[0] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR0); + ecc_sta[1] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR1); + ecc_sta[2] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR2); + ecc_sta[3] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR3); + ecc_sta[4] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR4); + + /* Disable ECC */ + stm32_fmc2_set_ecc(fmc2, false); + + return stm32_fmc2_bch_decode(chip->ecc.size, dat, ecc_sta); +} + +static int stm32_fmc2_read_page(struct nand_chip *chip, u8 *buf, + int oob_required, int page) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + int ret, i, s, stat, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + int eccstrength = chip->ecc.strength; + u8 *p = buf; + u8 *ecc_calc = chip->ecc.calc_buf; + u8 *ecc_code = chip->ecc.code_buf; + unsigned int max_bitflips = 0; + + ret = nand_read_page_op(chip, page, 0, NULL, 0); + if (ret) + return ret; + + for (i = mtd->writesize + FMC2_BBM_LEN, s = 0; s < eccsteps; + s++, i += eccbytes, p += eccsize) { + chip->ecc.hwctl(chip, NAND_ECC_READ); + + /* Read the nand page sector (512 bytes) */ + ret = nand_change_read_column_op(chip, s * eccsize, p, + eccsize, false); + if (ret) + return ret; + + /* Read the corresponding ECC bytes */ + ret = nand_change_read_column_op(chip, i, ecc_code, + eccbytes, false); + if (ret) + return ret; + + /* Correct the data */ + stat = chip->ecc.correct(chip, p, ecc_code, ecc_calc); + if (stat == -EBADMSG) + /* Check for empty pages with bitflips */ + stat = nand_check_erased_ecc_chunk(p, eccsize, + ecc_code, eccbytes, + NULL, 0, + eccstrength); + + if (stat < 0) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += stat; + max_bitflips = max_t(unsigned int, max_bitflips, stat); + } + } + + /* Read oob */ + if (oob_required) { + ret = nand_change_read_column_op(chip, mtd->writesize, + chip->oob_poi, mtd->oobsize, + false); + if (ret) + return ret; + } + + return max_bitflips; +} + +/* Sequencer read/write configuration */ +static void stm32_fmc2_rw_page_init(struct nand_chip *chip, int page, + int raw, bool write_data) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + struct mtd_info *mtd = nand_to_mtd(chip); + u32 csqcfgr1, csqcfgr2, csqcfgr3; + u32 csqar1, csqar2; + u32 ecc_offset = mtd->writesize + FMC2_BBM_LEN; + u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR); + + if (write_data) + pcr |= FMC2_PCR_WEN; + else + pcr &= ~FMC2_PCR_WEN; + writel_relaxed(pcr, fmc2->io_base + FMC2_PCR); + + /* + * - Set Program Page/Page Read command + * - Enable DMA request data + * - Set timings + */ + csqcfgr1 = FMC2_CSQCFGR1_DMADEN | FMC2_CSQCFGR1_CMD1T; + if (write_data) + csqcfgr1 |= FMC2_CSQCFGR1_CMD1(NAND_CMD_SEQIN); + else + csqcfgr1 |= FMC2_CSQCFGR1_CMD1(NAND_CMD_READ0) | + FMC2_CSQCFGR1_CMD2EN | + FMC2_CSQCFGR1_CMD2(NAND_CMD_READSTART) | + FMC2_CSQCFGR1_CMD2T; + + /* + * - Set Random Data Input/Random Data Read command + * - Enable the sequencer to access the Spare data area + * - Enable DMA request status decoding for read + * - Set timings + */ + if (write_data) + csqcfgr2 = FMC2_CSQCFGR2_RCMD1(NAND_CMD_RNDIN); + else + csqcfgr2 = FMC2_CSQCFGR2_RCMD1(NAND_CMD_RNDOUT) | + FMC2_CSQCFGR2_RCMD2EN | + FMC2_CSQCFGR2_RCMD2(NAND_CMD_RNDOUTSTART) | + FMC2_CSQCFGR2_RCMD1T | + FMC2_CSQCFGR2_RCMD2T; + if (!raw) { + csqcfgr2 |= write_data ? 0 : FMC2_CSQCFGR2_DMASEN; + csqcfgr2 |= FMC2_CSQCFGR2_SQSDTEN; + } + + /* + * - Set the number of sectors to be written + * - Set timings + */ + csqcfgr3 = FMC2_CSQCFGR3_SNBR(chip->ecc.steps - 1); + if (write_data) { + csqcfgr3 |= FMC2_CSQCFGR3_RAC2T; + if (chip->options & NAND_ROW_ADDR_3) + csqcfgr3 |= FMC2_CSQCFGR3_AC5T; + else + csqcfgr3 |= FMC2_CSQCFGR3_AC4T; + } + + /* + * Set the fourth first address cycles + * Byte 1 and byte 2 => column, we start at 0x0 + * Byte 3 and byte 4 => page + */ + csqar1 = FMC2_CSQCAR1_ADDC3(page); + csqar1 |= FMC2_CSQCAR1_ADDC4(page >> 8); + + /* + * - Set chip enable number + * - Set ECC byte offset in the spare area + * - Calculate the number of address cycles to be issued + * - Set byte 5 of address cycle if needed + */ + csqar2 = FMC2_CSQCAR2_NANDCEN(fmc2->cs_sel); + if (chip->options & NAND_BUSWIDTH_16) + csqar2 |= FMC2_CSQCAR2_SAO(ecc_offset >> 1); + else + csqar2 |= FMC2_CSQCAR2_SAO(ecc_offset); + if (chip->options & NAND_ROW_ADDR_3) { + csqcfgr1 |= FMC2_CSQCFGR1_ACYNBR(5); + csqar2 |= FMC2_CSQCAR2_ADDC5(page >> 16); + } else { + csqcfgr1 |= FMC2_CSQCFGR1_ACYNBR(4); + } + + writel_relaxed(csqcfgr1, fmc2->io_base + FMC2_CSQCFGR1); + writel_relaxed(csqcfgr2, fmc2->io_base + FMC2_CSQCFGR2); + writel_relaxed(csqcfgr3, fmc2->io_base + FMC2_CSQCFGR3); + writel_relaxed(csqar1, fmc2->io_base + FMC2_CSQAR1); + writel_relaxed(csqar2, fmc2->io_base + FMC2_CSQAR2); +} + +static void stm32_fmc2_dma_callback(void *arg) +{ + complete((struct completion *)arg); +} + +/* Read/write data from/to a page */ +static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf, + int raw, bool write_data) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + struct dma_async_tx_descriptor *desc_data, *desc_ecc; + struct scatterlist *sg; + struct dma_chan *dma_ch = fmc2->dma_rx_ch; + enum dma_data_direction dma_data_dir = DMA_FROM_DEVICE; + enum dma_transfer_direction dma_transfer_dir = DMA_DEV_TO_MEM; + u32 csqcr = readl_relaxed(fmc2->io_base + FMC2_CSQCR); + int eccsteps = chip->ecc.steps; + int eccsize = chip->ecc.size; + const u8 *p = buf; + int s, ret; + + /* Configure DMA data */ + if (write_data) { + dma_data_dir = DMA_TO_DEVICE; + dma_transfer_dir = DMA_MEM_TO_DEV; + dma_ch = fmc2->dma_tx_ch; + } + + for_each_sg(fmc2->dma_data_sg.sgl, sg, eccsteps, s) { + sg_set_buf(sg, p, eccsize); + p += eccsize; + } + + ret = dma_map_sg(fmc2->dev, fmc2->dma_data_sg.sgl, + eccsteps, dma_data_dir); + if (ret < 0) + return ret; + + desc_data = dmaengine_prep_slave_sg(dma_ch, fmc2->dma_data_sg.sgl, + eccsteps, dma_transfer_dir, + DMA_PREP_INTERRUPT); + if (!desc_data) { + ret = -ENOMEM; + goto err_unmap_data; + } + + reinit_completion(&fmc2->dma_data_complete); + reinit_completion(&fmc2->complete); + desc_data->callback = stm32_fmc2_dma_callback; + desc_data->callback_param = &fmc2->dma_data_complete; + ret = dma_submit_error(dmaengine_submit(desc_data)); + if (ret) + goto err_unmap_data; + + dma_async_issue_pending(dma_ch); + + if (!write_data && !raw) { + /* Configure DMA ECC status */ + p = fmc2->ecc_buf; + for_each_sg(fmc2->dma_ecc_sg.sgl, sg, eccsteps, s) { + sg_set_buf(sg, p, fmc2->dma_ecc_len); + p += fmc2->dma_ecc_len; + } + + ret = dma_map_sg(fmc2->dev, fmc2->dma_ecc_sg.sgl, + eccsteps, dma_data_dir); + if (ret < 0) + goto err_unmap_data; + + desc_ecc = dmaengine_prep_slave_sg(fmc2->dma_ecc_ch, + fmc2->dma_ecc_sg.sgl, + eccsteps, dma_transfer_dir, + DMA_PREP_INTERRUPT); + if (!desc_ecc) { + ret = -ENOMEM; + goto err_unmap_ecc; + } + + reinit_completion(&fmc2->dma_ecc_complete); + desc_ecc->callback = stm32_fmc2_dma_callback; + desc_ecc->callback_param = &fmc2->dma_ecc_complete; + ret = dma_submit_error(dmaengine_submit(desc_ecc)); + if (ret) + goto err_unmap_ecc; + + dma_async_issue_pending(fmc2->dma_ecc_ch); + } + + stm32_fmc2_clear_seq_irq(fmc2); + stm32_fmc2_enable_seq_irq(fmc2); + + /* Start the transfer */ + csqcr |= FMC2_CSQCR_CSQSTART; + writel_relaxed(csqcr, fmc2->io_base + FMC2_CSQCR); + + /* Wait end of sequencer transfer */ + if (!wait_for_completion_timeout(&fmc2->complete, + msecs_to_jiffies(1000))) { + dev_err(fmc2->dev, "seq timeout\n"); + stm32_fmc2_disable_seq_irq(fmc2); + dmaengine_terminate_all(dma_ch); + if (!write_data && !raw) + dmaengine_terminate_all(fmc2->dma_ecc_ch); + ret = -ETIMEDOUT; + goto err_unmap_ecc; + } + + /* Wait DMA data transfer completion */ + if (!wait_for_completion_timeout(&fmc2->dma_data_complete, + msecs_to_jiffies(100))) { + dev_err(fmc2->dev, "data DMA timeout\n"); + dmaengine_terminate_all(dma_ch); + ret = -ETIMEDOUT; + } + + /* Wait DMA ECC transfer completion */ + if (!write_data && !raw) { + if (!wait_for_completion_timeout(&fmc2->dma_ecc_complete, + msecs_to_jiffies(100))) { + dev_err(fmc2->dev, "ECC DMA timeout\n"); + dmaengine_terminate_all(fmc2->dma_ecc_ch); + ret = -ETIMEDOUT; + } + } + +err_unmap_ecc: + if (!write_data && !raw) + dma_unmap_sg(fmc2->dev, fmc2->dma_ecc_sg.sgl, + eccsteps, dma_data_dir); + +err_unmap_data: + dma_unmap_sg(fmc2->dev, fmc2->dma_data_sg.sgl, eccsteps, dma_data_dir); + + return ret; +} + +static int stm32_fmc2_sequencer_write(struct nand_chip *chip, + const u8 *buf, int oob_required, + int page, int raw) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + int ret; + + /* Configure the sequencer */ + stm32_fmc2_rw_page_init(chip, page, raw, true); + + /* Write the page */ + ret = stm32_fmc2_xfer(chip, buf, raw, true); + if (ret) + return ret; + + /* Write oob */ + if (oob_required) { + ret = nand_change_write_column_op(chip, mtd->writesize, + chip->oob_poi, mtd->oobsize, + false); + if (ret) + return ret; + } + + return nand_prog_page_end_op(chip); +} + +static int stm32_fmc2_sequencer_write_page(struct nand_chip *chip, + const u8 *buf, + int oob_required, + int page) +{ + int ret; + + /* Select the target */ + ret = stm32_fmc2_select_chip(chip, chip->cur_cs); + if (ret) + return ret; + + return stm32_fmc2_sequencer_write(chip, buf, oob_required, page, false); +} + +static int stm32_fmc2_sequencer_write_page_raw(struct nand_chip *chip, + const u8 *buf, + int oob_required, + int page) +{ + int ret; + + /* Select the target */ + ret = stm32_fmc2_select_chip(chip, chip->cur_cs); + if (ret) + return ret; + + return stm32_fmc2_sequencer_write(chip, buf, oob_required, page, true); +} + +/* Get a status indicating which sectors have errors */ +static inline u16 stm32_fmc2_get_mapping_status(struct stm32_fmc2_nfc *fmc2) +{ + u32 csqemsr = readl_relaxed(fmc2->io_base + FMC2_CSQEMSR); + + return csqemsr & FMC2_CSQEMSR_SEM; +} + +static int stm32_fmc2_sequencer_correct(struct nand_chip *chip, u8 *dat, + u8 *read_ecc, u8 *calc_ecc) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + int eccstrength = chip->ecc.strength; + int i, s, eccsize = chip->ecc.size; + u32 *ecc_sta = (u32 *)fmc2->ecc_buf; + u16 sta_map = stm32_fmc2_get_mapping_status(fmc2); + unsigned int max_bitflips = 0; + + for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, dat += eccsize) { + int stat = 0; + + if (eccstrength == FMC2_ECC_HAM) { + /* Ecc_sta = FMC2_HECCR */ + if (sta_map & BIT(s)) { + stm32_fmc2_ham_set_ecc(*ecc_sta, &calc_ecc[i]); + stat = stm32_fmc2_ham_correct(chip, dat, + &read_ecc[i], + &calc_ecc[i]); + } + ecc_sta++; + } else { + /* + * Ecc_sta[0] = FMC2_BCHDSR0 + * Ecc_sta[1] = FMC2_BCHDSR1 + * Ecc_sta[2] = FMC2_BCHDSR2 + * Ecc_sta[3] = FMC2_BCHDSR3 + * Ecc_sta[4] = FMC2_BCHDSR4 + */ + if (sta_map & BIT(s)) + stat = stm32_fmc2_bch_decode(eccsize, dat, + ecc_sta); + ecc_sta += 5; + } + + if (stat == -EBADMSG) + /* Check for empty pages with bitflips */ + stat = nand_check_erased_ecc_chunk(dat, eccsize, + &read_ecc[i], + eccbytes, + NULL, 0, + eccstrength); + + if (stat < 0) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += stat; + max_bitflips = max_t(unsigned int, max_bitflips, stat); + } + } + + return max_bitflips; +} + +static int stm32_fmc2_sequencer_read_page(struct nand_chip *chip, u8 *buf, + int oob_required, int page) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + u8 *ecc_calc = chip->ecc.calc_buf; + u8 *ecc_code = chip->ecc.code_buf; + u16 sta_map; + int ret; + + /* Select the target */ + ret = stm32_fmc2_select_chip(chip, chip->cur_cs); + if (ret) + return ret; + + /* Configure the sequencer */ + stm32_fmc2_rw_page_init(chip, page, 0, false); + + /* Read the page */ + ret = stm32_fmc2_xfer(chip, buf, 0, false); + if (ret) + return ret; + + sta_map = stm32_fmc2_get_mapping_status(fmc2); + + /* Check if errors happen */ + if (likely(!sta_map)) { + if (oob_required) + return nand_change_read_column_op(chip, mtd->writesize, + chip->oob_poi, + mtd->oobsize, false); + + return 0; + } + + /* Read oob */ + ret = nand_change_read_column_op(chip, mtd->writesize, + chip->oob_poi, mtd->oobsize, false); + if (ret) + return ret; + + ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, + chip->ecc.total); + if (ret) + return ret; + + /* Correct data */ + return chip->ecc.correct(chip, buf, ecc_code, ecc_calc); +} + +static int stm32_fmc2_sequencer_read_page_raw(struct nand_chip *chip, u8 *buf, + int oob_required, int page) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + int ret; + + /* Select the target */ + ret = stm32_fmc2_select_chip(chip, chip->cur_cs); + if (ret) + return ret; + + /* Configure the sequencer */ + stm32_fmc2_rw_page_init(chip, page, 1, false); + + /* Read the page */ + ret = stm32_fmc2_xfer(chip, buf, 1, false); + if (ret) + return ret; + + /* Read oob */ + if (oob_required) + return nand_change_read_column_op(chip, mtd->writesize, + chip->oob_poi, mtd->oobsize, + false); + + return 0; +} + +static irqreturn_t stm32_fmc2_irq(int irq, void *dev_id) +{ + struct stm32_fmc2_nfc *fmc2 = (struct stm32_fmc2_nfc *)dev_id; + + if (fmc2->irq_state == FMC2_IRQ_SEQ) + /* Sequencer is used */ + stm32_fmc2_disable_seq_irq(fmc2); + else if (fmc2->irq_state == FMC2_IRQ_BCH) + /* BCH is used */ + stm32_fmc2_disable_bch_irq(fmc2); + + complete(&fmc2->complete); + + return IRQ_HANDLED; +} + +static void stm32_fmc2_read_data(struct nand_chip *chip, void *buf, + unsigned int len, bool force_8bit) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + void __iomem *io_addr_r = fmc2->data_base[fmc2->cs_sel]; + + if (force_8bit && chip->options & NAND_BUSWIDTH_16) + /* Reconfigure bus width to 8-bit */ + stm32_fmc2_set_buswidth_16(fmc2, false); + + if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32))) { + if (!IS_ALIGNED((uintptr_t)buf, sizeof(u16)) && len) { + *(u8 *)buf = readb_relaxed(io_addr_r); + buf += sizeof(u8); + len -= sizeof(u8); + } + + if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32)) && + len >= sizeof(u16)) { + *(u16 *)buf = readw_relaxed(io_addr_r); + buf += sizeof(u16); + len -= sizeof(u16); + } + } + + /* Buf is aligned */ + while (len >= sizeof(u32)) { + *(u32 *)buf = readl_relaxed(io_addr_r); + buf += sizeof(u32); + len -= sizeof(u32); + } + + /* Read remaining bytes */ + if (len >= sizeof(u16)) { + *(u16 *)buf = readw_relaxed(io_addr_r); + buf += sizeof(u16); + len -= sizeof(u16); + } + + if (len) + *(u8 *)buf = readb_relaxed(io_addr_r); + + if (force_8bit && chip->options & NAND_BUSWIDTH_16) + /* Reconfigure bus width to 16-bit */ + stm32_fmc2_set_buswidth_16(fmc2, true); +} + +static void stm32_fmc2_write_data(struct nand_chip *chip, const void *buf, + unsigned int len, bool force_8bit) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + void __iomem *io_addr_w = fmc2->data_base[fmc2->cs_sel]; + + if (force_8bit && chip->options & NAND_BUSWIDTH_16) + /* Reconfigure bus width to 8-bit */ + stm32_fmc2_set_buswidth_16(fmc2, false); + + if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32))) { + if (!IS_ALIGNED((uintptr_t)buf, sizeof(u16)) && len) { + writeb_relaxed(*(u8 *)buf, io_addr_w); + buf += sizeof(u8); + len -= sizeof(u8); + } + + if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32)) && + len >= sizeof(u16)) { + writew_relaxed(*(u16 *)buf, io_addr_w); + buf += sizeof(u16); + len -= sizeof(u16); + } + } + + /* Buf is aligned */ + while (len >= sizeof(u32)) { + writel_relaxed(*(u32 *)buf, io_addr_w); + buf += sizeof(u32); + len -= sizeof(u32); + } + + /* Write remaining bytes */ + if (len >= sizeof(u16)) { + writew_relaxed(*(u16 *)buf, io_addr_w); + buf += sizeof(u16); + len -= sizeof(u16); + } + + if (len) + writeb_relaxed(*(u8 *)buf, io_addr_w); + + if (force_8bit && chip->options & NAND_BUSWIDTH_16) + /* Reconfigure bus width to 16-bit */ + stm32_fmc2_set_buswidth_16(fmc2, true); +} + +static int stm32_fmc2_exec_op(struct nand_chip *chip, + const struct nand_operation *op, + bool check_only) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + const struct nand_op_instr *instr = NULL; + unsigned int op_id, i; + int ret; + + ret = stm32_fmc2_select_chip(chip, op->cs); + if (ret) + return ret; + + if (check_only) + return ret; + + for (op_id = 0; op_id < op->ninstrs; op_id++) { + instr = &op->instrs[op_id]; + + switch (instr->type) { + case NAND_OP_CMD_INSTR: + writeb_relaxed(instr->ctx.cmd.opcode, + fmc2->cmd_base[fmc2->cs_sel]); + break; + + case NAND_OP_ADDR_INSTR: + for (i = 0; i < instr->ctx.addr.naddrs; i++) + writeb_relaxed(instr->ctx.addr.addrs[i], + fmc2->addr_base[fmc2->cs_sel]); + break; + + case NAND_OP_DATA_IN_INSTR: + stm32_fmc2_read_data(chip, instr->ctx.data.buf.in, + instr->ctx.data.len, + instr->ctx.data.force_8bit); + break; + + case NAND_OP_DATA_OUT_INSTR: + stm32_fmc2_write_data(chip, instr->ctx.data.buf.out, + instr->ctx.data.len, + instr->ctx.data.force_8bit); + break; + + case NAND_OP_WAITRDY_INSTR: + ret = nand_soft_waitrdy(chip, + instr->ctx.waitrdy.timeout_ms); + break; + } + } + + return ret; +} + +/* Controller initialization */ +static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2) +{ + u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR); + u32 bcr1 = readl_relaxed(fmc2->io_base + FMC2_BCR1); + + /* Set CS used to undefined */ + fmc2->cs_sel = -1; + + /* Enable wait feature and nand flash memory bank */ + pcr |= FMC2_PCR_PWAITEN; + pcr |= FMC2_PCR_PBKEN; + + /* Set buswidth to 8 bits mode for identification */ + pcr &= ~FMC2_PCR_PWID_MASK; + + /* ECC logic is disabled */ + pcr &= ~FMC2_PCR_ECCEN; + + /* Default mode */ + pcr &= ~FMC2_PCR_ECCALG; + pcr &= ~FMC2_PCR_BCHECC; + pcr &= ~FMC2_PCR_WEN; + + /* Set default ECC sector size */ + pcr &= ~FMC2_PCR_ECCSS_MASK; + pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048); + + /* Set default tclr/tar timings */ + pcr &= ~FMC2_PCR_TCLR_MASK; + pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT); + pcr &= ~FMC2_PCR_TAR_MASK; + pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT); + + /* Enable FMC2 controller */ + bcr1 |= FMC2_BCR1_FMC2EN; + + writel_relaxed(bcr1, fmc2->io_base + FMC2_BCR1); + writel_relaxed(pcr, fmc2->io_base + FMC2_PCR); + writel_relaxed(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM); + writel_relaxed(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT); +} + +/* Controller timings */ +static void stm32_fmc2_calc_timings(struct nand_chip *chip, + const struct nand_sdr_timings *sdrt) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); + struct stm32_fmc2_timings *tims = &nand->timings; + unsigned long hclk = clk_get_rate(fmc2->clk); + unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000); + int tar, tclr, thiz, twait, tset_mem, tset_att, thold_mem, thold_att; + + tar = hclkp; + if (tar < sdrt->tAR_min) + tar = sdrt->tAR_min; + tims->tar = DIV_ROUND_UP(tar, hclkp) - 1; + if (tims->tar > FMC2_PCR_TIMING_MASK) + tims->tar = FMC2_PCR_TIMING_MASK; + + tclr = hclkp; + if (tclr < sdrt->tCLR_min) + tclr = sdrt->tCLR_min; + tims->tclr = DIV_ROUND_UP(tclr, hclkp) - 1; + if (tims->tclr > FMC2_PCR_TIMING_MASK) + tims->tclr = FMC2_PCR_TIMING_MASK; + + tims->thiz = FMC2_THIZ; + thiz = (tims->thiz + 1) * hclkp; + + /* + * tWAIT > tRP + * tWAIT > tWP + * tWAIT > tREA + tIO + */ + twait = hclkp; + if (twait < sdrt->tRP_min) + twait = sdrt->tRP_min; + if (twait < sdrt->tWP_min) + twait = sdrt->tWP_min; + if (twait < sdrt->tREA_max + FMC2_TIO) + twait = sdrt->tREA_max + FMC2_TIO; + tims->twait = DIV_ROUND_UP(twait, hclkp); + if (tims->twait == 0) + tims->twait = 1; + else if (tims->twait > FMC2_PMEM_PATT_TIMING_MASK) + tims->twait = FMC2_PMEM_PATT_TIMING_MASK; + + /* + * tSETUP_MEM > tCS - tWAIT + * tSETUP_MEM > tALS - tWAIT + * tSETUP_MEM > tDS - (tWAIT - tHIZ) + */ + tset_mem = hclkp; + if (sdrt->tCS_min > twait && (tset_mem < sdrt->tCS_min - twait)) + tset_mem = sdrt->tCS_min - twait; + if (sdrt->tALS_min > twait && (tset_mem < sdrt->tALS_min - twait)) + tset_mem = sdrt->tALS_min - twait; + if (twait > thiz && (sdrt->tDS_min > twait - thiz) && + (tset_mem < sdrt->tDS_min - (twait - thiz))) + tset_mem = sdrt->tDS_min - (twait - thiz); + tims->tset_mem = DIV_ROUND_UP(tset_mem, hclkp); + if (tims->tset_mem == 0) + tims->tset_mem = 1; + else if (tims->tset_mem > FMC2_PMEM_PATT_TIMING_MASK) + tims->tset_mem = FMC2_PMEM_PATT_TIMING_MASK; + + /* + * tHOLD_MEM > tCH + * tHOLD_MEM > tREH - tSETUP_MEM + * tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT) + */ + thold_mem = hclkp; + if (thold_mem < sdrt->tCH_min) + thold_mem = sdrt->tCH_min; + if (sdrt->tREH_min > tset_mem && + (thold_mem < sdrt->tREH_min - tset_mem)) + thold_mem = sdrt->tREH_min - tset_mem; + if ((sdrt->tRC_min > tset_mem + twait) && + (thold_mem < sdrt->tRC_min - (tset_mem + twait))) + thold_mem = sdrt->tRC_min - (tset_mem + twait); + if ((sdrt->tWC_min > tset_mem + twait) && + (thold_mem < sdrt->tWC_min - (tset_mem + twait))) + thold_mem = sdrt->tWC_min - (tset_mem + twait); + tims->thold_mem = DIV_ROUND_UP(thold_mem, hclkp); + if (tims->thold_mem == 0) + tims->thold_mem = 1; + else if (tims->thold_mem > FMC2_PMEM_PATT_TIMING_MASK) + tims->thold_mem = FMC2_PMEM_PATT_TIMING_MASK; + + /* + * tSETUP_ATT > tCS - tWAIT + * tSETUP_ATT > tCLS - tWAIT + * tSETUP_ATT > tALS - tWAIT + * tSETUP_ATT > tRHW - tHOLD_MEM + * tSETUP_ATT > tDS - (tWAIT - tHIZ) + */ + tset_att = hclkp; + if (sdrt->tCS_min > twait && (tset_att < sdrt->tCS_min - twait)) + tset_att = sdrt->tCS_min - twait; + if (sdrt->tCLS_min > twait && (tset_att < sdrt->tCLS_min - twait)) + tset_att = sdrt->tCLS_min - twait; + if (sdrt->tALS_min > twait && (tset_att < sdrt->tALS_min - twait)) + tset_att = sdrt->tALS_min - twait; + if (sdrt->tRHW_min > thold_mem && + (tset_att < sdrt->tRHW_min - thold_mem)) + tset_att = sdrt->tRHW_min - thold_mem; + if (twait > thiz && (sdrt->tDS_min > twait - thiz) && + (tset_att < sdrt->tDS_min - (twait - thiz))) + tset_att = sdrt->tDS_min - (twait - thiz); + tims->tset_att = DIV_ROUND_UP(tset_att, hclkp); + if (tims->tset_att == 0) + tims->tset_att = 1; + else if (tims->tset_att > FMC2_PMEM_PATT_TIMING_MASK) + tims->tset_att = FMC2_PMEM_PATT_TIMING_MASK; + + /* + * tHOLD_ATT > tALH + * tHOLD_ATT > tCH + * tHOLD_ATT > tCLH + * tHOLD_ATT > tCOH + * tHOLD_ATT > tDH + * tHOLD_ATT > tWB + tIO + tSYNC - tSETUP_MEM + * tHOLD_ATT > tADL - tSETUP_MEM + * tHOLD_ATT > tWH - tSETUP_MEM + * tHOLD_ATT > tWHR - tSETUP_MEM + * tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT) + * tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT) + */ + thold_att = hclkp; + if (thold_att < sdrt->tALH_min) + thold_att = sdrt->tALH_min; + if (thold_att < sdrt->tCH_min) + thold_att = sdrt->tCH_min; + if (thold_att < sdrt->tCLH_min) + thold_att = sdrt->tCLH_min; + if (thold_att < sdrt->tCOH_min) + thold_att = sdrt->tCOH_min; + if (thold_att < sdrt->tDH_min) + thold_att = sdrt->tDH_min; + if ((sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC > tset_mem) && + (thold_att < sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem)) + thold_att = sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem; + if (sdrt->tADL_min > tset_mem && + (thold_att < sdrt->tADL_min - tset_mem)) + thold_att = sdrt->tADL_min - tset_mem; + if (sdrt->tWH_min > tset_mem && + (thold_att < sdrt->tWH_min - tset_mem)) + thold_att = sdrt->tWH_min - tset_mem; + if (sdrt->tWHR_min > tset_mem && + (thold_att < sdrt->tWHR_min - tset_mem)) + thold_att = sdrt->tWHR_min - tset_mem; + if ((sdrt->tRC_min > tset_att + twait) && + (thold_att < sdrt->tRC_min - (tset_att + twait))) + thold_att = sdrt->tRC_min - (tset_att + twait); + if ((sdrt->tWC_min > tset_att + twait) && + (thold_att < sdrt->tWC_min - (tset_att + twait))) + thold_att = sdrt->tWC_min - (tset_att + twait); + tims->thold_att = DIV_ROUND_UP(thold_att, hclkp); + if (tims->thold_att == 0) + tims->thold_att = 1; + else if (tims->thold_att > FMC2_PMEM_PATT_TIMING_MASK) + tims->thold_att = FMC2_PMEM_PATT_TIMING_MASK; +} + +static int stm32_fmc2_setup_interface(struct nand_chip *chip, int chipnr, + const struct nand_data_interface *conf) +{ + const struct nand_sdr_timings *sdrt; + + sdrt = nand_get_sdr_timings(conf); + if (IS_ERR(sdrt)) + return PTR_ERR(sdrt); + + if (chipnr == NAND_DATA_IFACE_CHECK_ONLY) + return 0; + + stm32_fmc2_calc_timings(chip, sdrt); + + /* Apply timings */ + stm32_fmc2_timings_init(chip); + + return 0; +} + +/* DMA configuration */ +static int stm32_fmc2_dma_setup(struct stm32_fmc2_nfc *fmc2) +{ + int ret; + + fmc2->dma_tx_ch = dma_request_slave_channel(fmc2->dev, "tx"); + fmc2->dma_rx_ch = dma_request_slave_channel(fmc2->dev, "rx"); + fmc2->dma_ecc_ch = dma_request_slave_channel(fmc2->dev, "ecc"); + + if (!fmc2->dma_tx_ch || !fmc2->dma_rx_ch || !fmc2->dma_ecc_ch) { + dev_warn(fmc2->dev, "DMAs not defined in the device tree, polling mode is used\n"); + return 0; + } + + ret = sg_alloc_table(&fmc2->dma_ecc_sg, FMC2_MAX_SG, GFP_KERNEL); + if (ret) + return ret; + + /* Allocate a buffer to store ECC status registers */ + fmc2->ecc_buf = devm_kzalloc(fmc2->dev, FMC2_MAX_ECC_BUF_LEN, + GFP_KERNEL); + if (!fmc2->ecc_buf) + return -ENOMEM; + + ret = sg_alloc_table(&fmc2->dma_data_sg, FMC2_MAX_SG, GFP_KERNEL); + if (ret) + return ret; + + init_completion(&fmc2->dma_data_complete); + init_completion(&fmc2->dma_ecc_complete); + + return 0; +} + +/* NAND callbacks setup */ +static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + + /* + * Specific callbacks to read/write a page depending on + * the mode (polling/sequencer) and the algo used (Hamming, BCH). + */ + if (fmc2->dma_tx_ch && fmc2->dma_rx_ch && fmc2->dma_ecc_ch) { + /* DMA => use sequencer mode callbacks */ + chip->ecc.correct = stm32_fmc2_sequencer_correct; + chip->ecc.write_page = stm32_fmc2_sequencer_write_page; + chip->ecc.read_page = stm32_fmc2_sequencer_read_page; + chip->ecc.write_page_raw = stm32_fmc2_sequencer_write_page_raw; + chip->ecc.read_page_raw = stm32_fmc2_sequencer_read_page_raw; + } else { + /* No DMA => use polling mode callbacks */ + chip->ecc.hwctl = stm32_fmc2_hwctl; + if (chip->ecc.strength == FMC2_ECC_HAM) { + /* Hamming is used */ + chip->ecc.calculate = stm32_fmc2_ham_calculate; + chip->ecc.correct = stm32_fmc2_ham_correct; + chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK; + } else { + /* BCH is used */ + chip->ecc.calculate = stm32_fmc2_bch_calculate; + chip->ecc.correct = stm32_fmc2_bch_correct; + chip->ecc.read_page = stm32_fmc2_read_page; + } + } + + /* Specific configurations depending on the algo used */ + if (chip->ecc.strength == FMC2_ECC_HAM) + chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3; + else if (chip->ecc.strength == FMC2_ECC_BCH8) + chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13; + else + chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7; +} + +/* FMC2 layout */ +static int stm32_fmc2_nand_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; + + if (section) + return -ERANGE; + + oobregion->length = ecc->total; + oobregion->offset = FMC2_BBM_LEN; + + return 0; +} + +static int stm32_fmc2_nand_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; + + if (section) + return -ERANGE; + + oobregion->length = mtd->oobsize - ecc->total - FMC2_BBM_LEN; + oobregion->offset = ecc->total + FMC2_BBM_LEN; + + return 0; +} + +static const struct mtd_ooblayout_ops stm32_fmc2_nand_ooblayout_ops = { + .ecc = stm32_fmc2_nand_ooblayout_ecc, + .free = stm32_fmc2_nand_ooblayout_free, +}; + +/* FMC2 caps */ +static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength) +{ + /* Hamming */ + if (strength == FMC2_ECC_HAM) + return 4; + + /* BCH8 */ + if (strength == FMC2_ECC_BCH8) + return 14; + + /* BCH4 */ + return 8; +} + +NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes, + FMC2_ECC_STEP_SIZE, + FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8); + +/* FMC2 controller ops */ +static int stm32_fmc2_attach_chip(struct nand_chip *chip) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + struct mtd_info *mtd = nand_to_mtd(chip); + int ret; + + /* + * Only NAND_ECC_HW mode is actually supported + * Hamming => ecc.strength = 1 + * BCH4 => ecc.strength = 4 + * BCH8 => ecc.strength = 8 + * ECC sector size = 512 + */ + if (chip->ecc.mode != NAND_ECC_HW) { + dev_err(fmc2->dev, "nand_ecc_mode is not well defined in the DT\n"); + return -EINVAL; + } + + ret = nand_ecc_choose_conf(chip, &stm32_fmc2_ecc_caps, + mtd->oobsize - FMC2_BBM_LEN); + if (ret) { + dev_err(fmc2->dev, "no valid ECC settings set\n"); + return ret; + } + + if (mtd->writesize / chip->ecc.size > FMC2_MAX_SG) { + dev_err(fmc2->dev, "nand page size is not supported\n"); + return -EINVAL; + } + + if (chip->bbt_options & NAND_BBT_USE_FLASH) + chip->bbt_options |= NAND_BBT_NO_OOB; + + /* NAND callbacks setup */ + stm32_fmc2_nand_callbacks_setup(chip); + + /* Define ECC layout */ + mtd_set_ooblayout(mtd, &stm32_fmc2_nand_ooblayout_ops); + + /* Configure bus width to 16-bit */ + if (chip->options & NAND_BUSWIDTH_16) + stm32_fmc2_set_buswidth_16(fmc2, true); + + return 0; +} + +static const struct nand_controller_ops stm32_fmc2_nand_controller_ops = { + .attach_chip = stm32_fmc2_attach_chip, + .exec_op = stm32_fmc2_exec_op, + .setup_data_interface = stm32_fmc2_setup_interface, +}; + +/* FMC2 probe */ +static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2, + struct device_node *dn) +{ + struct stm32_fmc2_nand *nand = &fmc2->nand; + u32 cs; + int ret, i; + + if (!of_get_property(dn, "reg", &nand->ncs)) + return -EINVAL; + + nand->ncs /= sizeof(u32); + if (!nand->ncs) { + dev_err(fmc2->dev, "invalid reg property size\n"); + return -EINVAL; + } + + for (i = 0; i < nand->ncs; i++) { + ret = of_property_read_u32_index(dn, "reg", i, &cs); + if (ret) { + dev_err(fmc2->dev, "could not retrieve reg property: %d\n", + ret); + return ret; + } + + if (cs > FMC2_MAX_CE) { + dev_err(fmc2->dev, "invalid reg value: %d\n", cs); + return -EINVAL; + } + + if (fmc2->cs_assigned & BIT(cs)) { + dev_err(fmc2->dev, "cs already assigned: %d\n", cs); + return -EINVAL; + } + + fmc2->cs_assigned |= BIT(cs); + nand->cs_used[i] = cs; + } + + nand_set_flash_node(&nand->chip, dn); + + return 0; +} + +static int stm32_fmc2_parse_dt(struct stm32_fmc2_nfc *fmc2) +{ + struct device_node *dn = fmc2->dev->of_node; + struct device_node *child; + int nchips = of_get_child_count(dn); + int ret = 0; + + if (!nchips) { + dev_err(fmc2->dev, "NAND chip not defined\n"); + return -EINVAL; + } + + if (nchips > 1) { + dev_err(fmc2->dev, "too many NAND chips defined\n"); + return -EINVAL; + } + + for_each_child_of_node(dn, child) { + ret = stm32_fmc2_parse_child(fmc2, child); + if (ret < 0) { + of_node_put(child); + return ret; + } + } + + return ret; +} + +static int stm32_fmc2_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct reset_control *rstc; + struct stm32_fmc2_nfc *fmc2; + struct stm32_fmc2_nand *nand; + struct resource *res; + struct mtd_info *mtd; + struct nand_chip *chip; + int chip_cs, mem_region, ret, irq; + + fmc2 = devm_kzalloc(dev, sizeof(*fmc2), GFP_KERNEL); + if (!fmc2) + return -ENOMEM; + + fmc2->dev = dev; + nand_controller_init(&fmc2->base); + fmc2->base.ops = &stm32_fmc2_nand_controller_ops; + + ret = stm32_fmc2_parse_dt(fmc2); + if (ret) + return ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + fmc2->io_base = devm_ioremap_resource(dev, res); + if (IS_ERR(fmc2->io_base)) + return PTR_ERR(fmc2->io_base); + + fmc2->io_phys_addr = res->start; + + for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE; + chip_cs++, mem_region += 3) { + if (!(fmc2->cs_assigned & BIT(chip_cs))) + continue; + + res = platform_get_resource(pdev, IORESOURCE_MEM, mem_region); + fmc2->data_base[chip_cs] = devm_ioremap_resource(dev, res); + if (IS_ERR(fmc2->data_base[chip_cs])) + return PTR_ERR(fmc2->data_base[chip_cs]); + + fmc2->data_phys_addr[chip_cs] = res->start; + + res = platform_get_resource(pdev, IORESOURCE_MEM, + mem_region + 1); + fmc2->cmd_base[chip_cs] = devm_ioremap_resource(dev, res); + if (IS_ERR(fmc2->cmd_base[chip_cs])) + return PTR_ERR(fmc2->cmd_base[chip_cs]); + + res = platform_get_resource(pdev, IORESOURCE_MEM, + mem_region + 2); + fmc2->addr_base[chip_cs] = devm_ioremap_resource(dev, res); + if (IS_ERR(fmc2->addr_base[chip_cs])) + return PTR_ERR(fmc2->addr_base[chip_cs]); + } + + irq = platform_get_irq(pdev, 0); + ret = devm_request_irq(dev, irq, stm32_fmc2_irq, 0, + dev_name(dev), fmc2); + if (ret) { + dev_err(dev, "failed to request irq\n"); + return ret; + } + + init_completion(&fmc2->complete); + + fmc2->clk = devm_clk_get(dev, NULL); + if (IS_ERR(fmc2->clk)) + return PTR_ERR(fmc2->clk); + + ret = clk_prepare_enable(fmc2->clk); + if (ret) { + dev_err(dev, "can not enable the clock\n"); + return ret; + } + + rstc = devm_reset_control_get(dev, NULL); + if (!IS_ERR(rstc)) { + reset_control_assert(rstc); + reset_control_deassert(rstc); + } + + /* DMA setup */ + ret = stm32_fmc2_dma_setup(fmc2); + if (ret) + return ret; + + /* FMC2 init routine */ + stm32_fmc2_init(fmc2); + + nand = &fmc2->nand; + chip = &nand->chip; + mtd = nand_to_mtd(chip); + mtd->dev.parent = dev; + + chip->controller = &fmc2->base; + chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE | + NAND_USE_BOUNCE_BUFFER; + + /* Default ECC settings */ + chip->ecc.mode = NAND_ECC_HW; + chip->ecc.size = FMC2_ECC_STEP_SIZE; + chip->ecc.strength = FMC2_ECC_BCH8; + + /* Scan to find existence of the device */ + ret = nand_scan(chip, nand->ncs); + if (ret) + goto err_scan; + + ret = mtd_device_register(mtd, NULL, 0); + if (ret) + goto err_device_register; + + platform_set_drvdata(pdev, fmc2); + + return 0; + +err_device_register: + nand_cleanup(chip); + +err_scan: + if (fmc2->dma_ecc_ch) + dma_release_channel(fmc2->dma_ecc_ch); + if (fmc2->dma_tx_ch) + dma_release_channel(fmc2->dma_tx_ch); + if (fmc2->dma_rx_ch) + dma_release_channel(fmc2->dma_rx_ch); + + sg_free_table(&fmc2->dma_data_sg); + sg_free_table(&fmc2->dma_ecc_sg); + + clk_disable_unprepare(fmc2->clk); + + return ret; +} + +static int stm32_fmc2_remove(struct platform_device *pdev) +{ + struct stm32_fmc2_nfc *fmc2 = platform_get_drvdata(pdev); + struct stm32_fmc2_nand *nand = &fmc2->nand; + + nand_release(&nand->chip); + + if (fmc2->dma_ecc_ch) + dma_release_channel(fmc2->dma_ecc_ch); + if (fmc2->dma_tx_ch) + dma_release_channel(fmc2->dma_tx_ch); + if (fmc2->dma_rx_ch) + dma_release_channel(fmc2->dma_rx_ch); + + sg_free_table(&fmc2->dma_data_sg); + sg_free_table(&fmc2->dma_ecc_sg); + + clk_disable_unprepare(fmc2->clk); + + return 0; +} + +static int __maybe_unused stm32_fmc2_suspend(struct device *dev) +{ + struct stm32_fmc2_nfc *fmc2 = dev_get_drvdata(dev); + + clk_disable_unprepare(fmc2->clk); + + pinctrl_pm_select_sleep_state(dev); + + return 0; +} + +static int __maybe_unused stm32_fmc2_resume(struct device *dev) +{ + struct stm32_fmc2_nfc *fmc2 = dev_get_drvdata(dev); + struct stm32_fmc2_nand *nand = &fmc2->nand; + int chip_cs, ret; + + pinctrl_pm_select_default_state(dev); + + ret = clk_prepare_enable(fmc2->clk); + if (ret) { + dev_err(dev, "can not enable the clock\n"); + return ret; + } + + stm32_fmc2_init(fmc2); + + for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) { + if (!(fmc2->cs_assigned & BIT(chip_cs))) + continue; + + nand_reset(&nand->chip, chip_cs); + } + + return 0; +} + +static SIMPLE_DEV_PM_OPS(stm32_fmc2_pm_ops, stm32_fmc2_suspend, + stm32_fmc2_resume); + +static const struct of_device_id stm32_fmc2_match[] = { + {.compatible = "st,stm32mp15-fmc2"}, + {} +}; +MODULE_DEVICE_TABLE(of, stm32_fmc2_match); + +static struct platform_driver stm32_fmc2_driver = { + .probe = stm32_fmc2_probe, + .remove = stm32_fmc2_remove, + .driver = { + .name = "stm32_fmc2_nand", + .of_match_table = stm32_fmc2_match, + .pm = &stm32_fmc2_pm_ops, + }, +}; +module_platform_driver(stm32_fmc2_driver); + +MODULE_ALIAS("platform:stm32_fmc2_nand"); +MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>"); +MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 nand driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index e828ee50a201..4282bc477761 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2013 Boris BREZILLON <b.brezillon.dev@gmail.com> * @@ -10,16 +11,6 @@ * * Copyright (C) 2013 Dmitriy B. <rzk333@gmail.com> * Copyright (C) 2013 Sergey Lapin <slapin@ossfans.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/dma-mapping.h> @@ -163,38 +154,36 @@ #define NFC_MAX_CS 7 -/* - * Chip Select structure: stores information related to NAND Chip Select +/** + * struct sunxi_nand_chip_sel - stores information related to NAND Chip Select * - * @cs: the NAND CS id used to communicate with a NAND Chip - * @rb: the Ready/Busy pin ID. -1 means no R/B pin connected to the - * NFC + * @cs: the NAND CS id used to communicate with a NAND Chip + * @rb: the Ready/Busy pin ID. -1 means no R/B pin connected to the NFC */ struct sunxi_nand_chip_sel { u8 cs; s8 rb; }; -/* - * sunxi HW ECC infos: stores information related to HW ECC support +/** + * struct sunxi_nand_hw_ecc - stores information related to HW ECC support * - * @mode: the sunxi ECC mode field deduced from ECC requirements + * @mode: the sunxi ECC mode field deduced from ECC requirements */ struct sunxi_nand_hw_ecc { int mode; }; -/* - * NAND chip structure: stores NAND chip device related information +/** + * struct sunxi_nand_chip - stores NAND chip device related information * - * @node: used to store NAND chips into a list - * @nand: base NAND chip structure - * @mtd: base MTD structure - * @clk_rate: clk_rate required for this NAND chip - * @timing_cfg TIMING_CFG register value for this NAND chip - * @selected: current active CS - * @nsels: number of CS lines required by the NAND chip - * @sels: array of CS lines descriptions + * @node: used to store NAND chips into a list + * @nand: base NAND chip structure + * @clk_rate: clk_rate required for this NAND chip + * @timing_cfg: TIMING_CFG register value for this NAND chip + * @timing_ctl: TIMING_CTL register value for this NAND chip + * @nsels: number of CS lines required by the NAND chip + * @sels: array of CS lines descriptions */ struct sunxi_nand_chip { struct list_head node; @@ -202,11 +191,6 @@ struct sunxi_nand_chip { unsigned long clk_rate; u32 timing_cfg; u32 timing_ctl; - int selected; - int addr_cycles; - u32 addr[2]; - int cmd_cycles; - u8 cmd[2]; int nsels; struct sunxi_nand_chip_sel sels[0]; }; @@ -216,20 +200,21 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand) return container_of(nand, struct sunxi_nand_chip, nand); } -/* - * NAND Controller structure: stores sunxi NAND controller information +/** + * struct sunxi_nfc - stores sunxi NAND controller information * - * @controller: base controller structure - * @dev: parent device (used to print error messages) - * @regs: NAND controller registers - * @ahb_clk: NAND Controller AHB clock - * @mod_clk: NAND Controller mod clock - * @assigned_cs: bitmask describing already assigned CS lines - * @clk_rate: NAND controller current clock rate - * @chips: a list containing all the NAND chips attached to - * this NAND controller - * @complete: a completion object used to wait for NAND - * controller events + * @controller: base controller structure + * @dev: parent device (used to print error messages) + * @regs: NAND controller registers + * @ahb_clk: NAND controller AHB clock + * @mod_clk: NAND controller mod clock + * @reset: NAND controller reset line + * @assigned_cs: bitmask describing already assigned CS lines + * @clk_rate: NAND controller current clock rate + * @chips: a list containing all the NAND chips attached to this NAND + * controller + * @complete: a completion object used to wait for NAND controller events + * @dmac: the DMA channel attached to the NAND controller */ struct sunxi_nfc { struct nand_controller controller; @@ -339,13 +324,11 @@ static int sunxi_nfc_rst(struct sunxi_nfc *nfc) return ret; } -static int sunxi_nfc_dma_op_prepare(struct mtd_info *mtd, const void *buf, +static int sunxi_nfc_dma_op_prepare(struct sunxi_nfc *nfc, const void *buf, int chunksize, int nchunks, enum dma_data_direction ddir, struct scatterlist *sg) { - struct nand_chip *nand = mtd_to_nand(mtd); - struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct dma_async_tx_descriptor *dmad; enum dma_transfer_direction tdir; dma_cookie_t dmat; @@ -388,38 +371,16 @@ err_unmap_buf: return ret; } -static void sunxi_nfc_dma_op_cleanup(struct mtd_info *mtd, +static void sunxi_nfc_dma_op_cleanup(struct sunxi_nfc *nfc, enum dma_data_direction ddir, struct scatterlist *sg) { - struct nand_chip *nand = mtd_to_nand(mtd); - struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); - dma_unmap_sg(nfc->dev, sg, 1, ddir); writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD, nfc->regs + NFC_REG_CTL); } -static int sunxi_nfc_dev_ready(struct nand_chip *nand) -{ - struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); - struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); - u32 mask; - - if (sunxi_nand->selected < 0) - return 0; - - if (sunxi_nand->sels[sunxi_nand->selected].rb < 0) { - dev_err(nfc->dev, "cannot check R/B NAND status!\n"); - return 0; - } - - mask = NFC_RB_STATE(sunxi_nand->sels[sunxi_nand->selected].rb); - - return !!(readl(nfc->regs + NFC_REG_ST) & mask); -} - -static void sunxi_nfc_select_chip(struct nand_chip *nand, int chip) +static void sunxi_nfc_select_chip(struct nand_chip *nand, unsigned int cs) { struct mtd_info *mtd = nand_to_mtd(nand); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); @@ -427,40 +388,27 @@ static void sunxi_nfc_select_chip(struct nand_chip *nand, int chip) struct sunxi_nand_chip_sel *sel; u32 ctl; - if (chip > 0 && chip >= sunxi_nand->nsels) - return; - - if (chip == sunxi_nand->selected) + if (cs > 0 && cs >= sunxi_nand->nsels) return; ctl = readl(nfc->regs + NFC_REG_CTL) & ~(NFC_PAGE_SHIFT_MSK | NFC_CE_SEL_MSK | NFC_RB_SEL_MSK | NFC_EN); - if (chip >= 0) { - sel = &sunxi_nand->sels[chip]; + sel = &sunxi_nand->sels[cs]; + ctl |= NFC_CE_SEL(sel->cs) | NFC_EN | NFC_PAGE_SHIFT(nand->page_shift); + if (sel->rb >= 0) + ctl |= NFC_RB_SEL(sel->rb); - ctl |= NFC_CE_SEL(sel->cs) | NFC_EN | - NFC_PAGE_SHIFT(nand->page_shift); - if (sel->rb < 0) { - nand->legacy.dev_ready = NULL; - } else { - nand->legacy.dev_ready = sunxi_nfc_dev_ready; - ctl |= NFC_RB_SEL(sel->rb); - } - - writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA); + writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA); - if (nfc->clk_rate != sunxi_nand->clk_rate) { - clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate); - nfc->clk_rate = sunxi_nand->clk_rate; - } + if (nfc->clk_rate != sunxi_nand->clk_rate) { + clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate); + nfc->clk_rate = sunxi_nand->clk_rate; } writel(sunxi_nand->timing_ctl, nfc->regs + NFC_REG_TIMING_CTL); writel(sunxi_nand->timing_cfg, nfc->regs + NFC_REG_TIMING_CFG); writel(ctl, nfc->regs + NFC_REG_CTL); - - sunxi_nand->selected = chip; } static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len) @@ -537,71 +485,6 @@ static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf, } } -static uint8_t sunxi_nfc_read_byte(struct nand_chip *nand) -{ - uint8_t ret = 0; - - sunxi_nfc_read_buf(nand, &ret, 1); - - return ret; -} - -static void sunxi_nfc_cmd_ctrl(struct nand_chip *nand, int dat, - unsigned int ctrl) -{ - struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); - struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); - int ret; - - if (dat == NAND_CMD_NONE && (ctrl & NAND_NCE) && - !(ctrl & (NAND_CLE | NAND_ALE))) { - u32 cmd = 0; - - if (!sunxi_nand->addr_cycles && !sunxi_nand->cmd_cycles) - return; - - if (sunxi_nand->cmd_cycles--) - cmd |= NFC_SEND_CMD1 | sunxi_nand->cmd[0]; - - if (sunxi_nand->cmd_cycles--) { - cmd |= NFC_SEND_CMD2; - writel(sunxi_nand->cmd[1], - nfc->regs + NFC_REG_RCMD_SET); - } - - sunxi_nand->cmd_cycles = 0; - - if (sunxi_nand->addr_cycles) { - cmd |= NFC_SEND_ADR | - NFC_ADR_NUM(sunxi_nand->addr_cycles); - writel(sunxi_nand->addr[0], - nfc->regs + NFC_REG_ADDR_LOW); - } - - if (sunxi_nand->addr_cycles > 4) - writel(sunxi_nand->addr[1], - nfc->regs + NFC_REG_ADDR_HIGH); - - ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); - if (ret) - return; - - writel(cmd, nfc->regs + NFC_REG_CMD); - sunxi_nand->addr[0] = 0; - sunxi_nand->addr[1] = 0; - sunxi_nand->addr_cycles = 0; - sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0); - } - - if (ctrl & NAND_CLE) { - sunxi_nand->cmd[sunxi_nand->cmd_cycles++] = dat; - } else if (ctrl & NAND_ALE) { - sunxi_nand->addr[sunxi_nand->addr_cycles / 4] |= - dat << ((sunxi_nand->addr_cycles % 4) * 8); - sunxi_nand->addr_cycles++; - } -} - /* These seed values have been extracted from Allwinner's BSP */ static const u16 sunxi_nfc_randomizer_page_seeds[] = { 0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72, @@ -684,8 +567,10 @@ static u16 sunxi_nfc_randomizer_step(u16 state, int count) return state; } -static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc) +static u16 sunxi_nfc_randomizer_state(struct nand_chip *nand, int page, + bool ecc) { + struct mtd_info *mtd = nand_to_mtd(nand); const u16 *seeds = sunxi_nfc_randomizer_page_seeds; int mod = mtd_div_by_ws(mtd->erasesize, mtd); @@ -702,10 +587,9 @@ static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc) return seeds[page % mod]; } -static void sunxi_nfc_randomizer_config(struct mtd_info *mtd, - int page, bool ecc) +static void sunxi_nfc_randomizer_config(struct nand_chip *nand, int page, + bool ecc) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); u16 state; @@ -714,14 +598,13 @@ static void sunxi_nfc_randomizer_config(struct mtd_info *mtd, return; ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); - state = sunxi_nfc_randomizer_state(mtd, page, ecc); + state = sunxi_nfc_randomizer_state(nand, page, ecc); ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK; writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL); } -static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd) +static void sunxi_nfc_randomizer_enable(struct nand_chip *nand) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); if (!(nand->options & NAND_NEED_SCRAMBLING)) @@ -731,9 +614,8 @@ static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd) nfc->regs + NFC_REG_ECC_CTL); } -static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd) +static void sunxi_nfc_randomizer_disable(struct nand_chip *nand) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); if (!(nand->options & NAND_NEED_SCRAMBLING)) @@ -743,36 +625,35 @@ static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd) nfc->regs + NFC_REG_ECC_CTL); } -static void sunxi_nfc_randomize_bbm(struct mtd_info *mtd, int page, u8 *bbm) +static void sunxi_nfc_randomize_bbm(struct nand_chip *nand, int page, u8 *bbm) { - u16 state = sunxi_nfc_randomizer_state(mtd, page, true); + u16 state = sunxi_nfc_randomizer_state(nand, page, true); bbm[0] ^= state; bbm[1] ^= sunxi_nfc_randomizer_step(state, 8); } -static void sunxi_nfc_randomizer_write_buf(struct mtd_info *mtd, +static void sunxi_nfc_randomizer_write_buf(struct nand_chip *nand, const uint8_t *buf, int len, bool ecc, int page) { - sunxi_nfc_randomizer_config(mtd, page, ecc); - sunxi_nfc_randomizer_enable(mtd); - sunxi_nfc_write_buf(mtd_to_nand(mtd), buf, len); - sunxi_nfc_randomizer_disable(mtd); + sunxi_nfc_randomizer_config(nand, page, ecc); + sunxi_nfc_randomizer_enable(nand); + sunxi_nfc_write_buf(nand, buf, len); + sunxi_nfc_randomizer_disable(nand); } -static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf, +static void sunxi_nfc_randomizer_read_buf(struct nand_chip *nand, uint8_t *buf, int len, bool ecc, int page) { - sunxi_nfc_randomizer_config(mtd, page, ecc); - sunxi_nfc_randomizer_enable(mtd); - sunxi_nfc_read_buf(mtd_to_nand(mtd), buf, len); - sunxi_nfc_randomizer_disable(mtd); + sunxi_nfc_randomizer_config(nand, page, ecc); + sunxi_nfc_randomizer_enable(nand); + sunxi_nfc_read_buf(nand, buf, len); + sunxi_nfc_randomizer_disable(nand); } -static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd) +static void sunxi_nfc_hw_ecc_enable(struct nand_chip *nand) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct sunxi_nand_hw_ecc *data = nand->ecc.priv; u32 ecc_ctl; @@ -789,9 +670,8 @@ static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd) writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL); } -static void sunxi_nfc_hw_ecc_disable(struct mtd_info *mtd) +static void sunxi_nfc_hw_ecc_disable(struct nand_chip *nand) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN, @@ -811,10 +691,9 @@ static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf) return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); } -static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct mtd_info *mtd, u8 *oob, +static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob, int step, bool bbm, int page) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)), @@ -822,21 +701,20 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct mtd_info *mtd, u8 *oob, /* De-randomize the Bad Block Marker. */ if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) - sunxi_nfc_randomize_bbm(mtd, page, oob); + sunxi_nfc_randomize_bbm(nand, page, oob); } -static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct mtd_info *mtd, +static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, const u8 *oob, int step, bool bbm, int page) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); u8 user_data[4]; /* Randomize the Bad Block Marker. */ if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { memcpy(user_data, oob, sizeof(user_data)); - sunxi_nfc_randomize_bbm(mtd, page, user_data); + sunxi_nfc_randomize_bbm(nand, page, user_data); oob = user_data; } @@ -844,9 +722,11 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct mtd_info *mtd, nfc->regs + NFC_REG_USER_DATA(step)); } -static void sunxi_nfc_hw_ecc_update_stats(struct mtd_info *mtd, +static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, unsigned int *max_bitflips, int ret) { + struct mtd_info *mtd = nand_to_mtd(nand); + if (ret < 0) { mtd->ecc_stats.failed++; } else { @@ -855,10 +735,9 @@ static void sunxi_nfc_hw_ecc_update_stats(struct mtd_info *mtd, } } -static int sunxi_nfc_hw_ecc_correct(struct mtd_info *mtd, u8 *data, u8 *oob, +static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob, int step, u32 status, bool *erased) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; u32 tmp; @@ -892,14 +771,13 @@ static int sunxi_nfc_hw_ecc_correct(struct mtd_info *mtd, u8 *data, u8 *oob, return NFC_ECC_ERR_CNT(step, tmp); } -static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, +static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, u8 *data, int data_off, u8 *oob, int oob_off, int *cur_off, unsigned int *max_bitflips, bool bbm, bool oob_required, int page) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; int raw_mode = 0; @@ -909,7 +787,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, if (*cur_off != data_off) nand_change_read_column_op(nand, data_off, NULL, 0, false); - sunxi_nfc_randomizer_read_buf(mtd, NULL, ecc->size, false, page); + sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); if (data_off + ecc->size != oob_off) nand_change_read_column_op(nand, oob_off, NULL, 0, false); @@ -918,18 +796,18 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, if (ret) return ret; - sunxi_nfc_randomizer_enable(mtd); + sunxi_nfc_randomizer_enable(nand); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, nfc->regs + NFC_REG_CMD); ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0); - sunxi_nfc_randomizer_disable(mtd); + sunxi_nfc_randomizer_disable(nand); if (ret) return ret; *cur_off = oob_off + ecc->bytes + 4; - ret = sunxi_nfc_hw_ecc_correct(mtd, data, oob_required ? oob : NULL, 0, + ret = sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, 0, readl(nfc->regs + NFC_REG_ECC_ST), &erased); if (erased) @@ -961,24 +839,24 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, if (oob_required) { nand_change_read_column_op(nand, oob_off, NULL, 0, false); - sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, + sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + 4, true, page); - sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, 0, + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, 0, bbm, page); } } - sunxi_nfc_hw_ecc_update_stats(mtd, max_bitflips, ret); + sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, ret); return raw_mode; } -static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, +static void sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, u8 *oob, int *cur_off, bool randomize, int page) { - struct nand_chip *nand = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; int offset = ((ecc->bytes + 4) * ecc->steps); int len = mtd->oobsize - offset; @@ -993,20 +871,20 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, if (!randomize) sunxi_nfc_read_buf(nand, oob + offset, len); else - sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len, + sunxi_nfc_randomizer_read_buf(nand, oob + offset, len, false, page); if (cur_off) *cur_off = mtd->oobsize + mtd->writesize; } -static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf, +static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf, int oob_required, int page, int nchunks) { - struct nand_chip *nand = mtd_to_nand(mtd); bool randomized = nand->options & NAND_NEED_SCRAMBLING; struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; unsigned int max_bitflips = 0; int ret, i, raw_mode = 0; @@ -1017,14 +895,14 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf, if (ret) return ret; - ret = sunxi_nfc_dma_op_prepare(mtd, buf, ecc->size, nchunks, + ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, nchunks, DMA_FROM_DEVICE, &sg); if (ret) return ret; - sunxi_nfc_hw_ecc_enable(mtd); - sunxi_nfc_randomizer_config(mtd, page, false); - sunxi_nfc_randomizer_enable(mtd); + sunxi_nfc_hw_ecc_enable(nand); + sunxi_nfc_randomizer_config(nand, page, false); + sunxi_nfc_randomizer_enable(nand); writel((NAND_CMD_RNDOUTSTART << 16) | (NAND_CMD_RNDOUT << 8) | NAND_CMD_READSTART, nfc->regs + NFC_REG_RCMD_SET); @@ -1038,10 +916,10 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf, if (ret) dmaengine_terminate_all(nfc->dmac); - sunxi_nfc_randomizer_disable(mtd); - sunxi_nfc_hw_ecc_disable(mtd); + sunxi_nfc_randomizer_disable(nand); + sunxi_nfc_hw_ecc_disable(nand); - sunxi_nfc_dma_op_cleanup(mtd, DMA_FROM_DEVICE, &sg); + sunxi_nfc_dma_op_cleanup(nfc, DMA_FROM_DEVICE, &sg); if (ret) return ret; @@ -1055,7 +933,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf, u8 *oob = nand->oob_poi + oob_off; bool erased; - ret = sunxi_nfc_hw_ecc_correct(mtd, randomized ? data : NULL, + ret = sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, oob_required ? oob : NULL, i, status, &erased); @@ -1069,14 +947,14 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf, mtd->writesize + oob_off, oob, ecc->bytes + 4, false); - sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, i, + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, page); } if (erased) raw_mode = 1; - sunxi_nfc_hw_ecc_update_stats(mtd, &max_bitflips, ret); + sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret); } if (status & NFC_ECC_ERR_MSK) { @@ -1111,25 +989,24 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf, if (ret >= 0) raw_mode = 1; - sunxi_nfc_hw_ecc_update_stats(mtd, &max_bitflips, ret); + sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret); } } if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(mtd, nand->oob_poi, + sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, NULL, !raw_mode, page); return max_bitflips; } -static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, +static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, const u8 *data, int data_off, const u8 *oob, int oob_off, int *cur_off, bool bbm, int page) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; int ret; @@ -1137,7 +1014,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, if (data_off != *cur_off) nand_change_write_column_op(nand, data_off, NULL, 0, false); - sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page); + sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page); if (data_off + ecc->size != oob_off) nand_change_write_column_op(nand, oob_off, NULL, 0, false); @@ -1146,15 +1023,15 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, if (ret) return ret; - sunxi_nfc_randomizer_enable(mtd); - sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, 0, bbm, page); + sunxi_nfc_randomizer_enable(nand); + sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, 0, bbm, page); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR | NFC_ECC_OP, nfc->regs + NFC_REG_CMD); ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0); - sunxi_nfc_randomizer_disable(mtd); + sunxi_nfc_randomizer_disable(nand); if (ret) return ret; @@ -1163,11 +1040,11 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, return 0; } -static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd, +static void sunxi_nfc_hw_ecc_write_extra_oob(struct nand_chip *nand, u8 *oob, int *cur_off, int page) { - struct nand_chip *nand = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; int offset = ((ecc->bytes + 4) * ecc->steps); int len = mtd->oobsize - offset; @@ -1179,32 +1056,34 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd, nand_change_write_column_op(nand, offset + mtd->writesize, NULL, 0, false); - sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page); + sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, page); if (cur_off) *cur_off = mtd->oobsize + mtd->writesize; } -static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *chip, uint8_t *buf, +static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, int oob_required, int page) { - struct mtd_info *mtd = nand_to_mtd(chip); - struct nand_ecc_ctrl *ecc = &chip->ecc; + struct mtd_info *mtd = nand_to_mtd(nand); + struct nand_ecc_ctrl *ecc = &nand->ecc; unsigned int max_bitflips = 0; int ret, i, cur_off = 0; bool raw_mode = false; - nand_read_page_op(chip, page, 0, NULL, 0); + sunxi_nfc_select_chip(nand, nand->cur_cs); + + nand_read_page_op(nand, page, 0, NULL, 0); - sunxi_nfc_hw_ecc_enable(mtd); + sunxi_nfc_hw_ecc_enable(nand); for (i = 0; i < ecc->steps; i++) { int data_off = i * ecc->size; int oob_off = i * (ecc->bytes + 4); u8 *data = buf + data_off; - u8 *oob = chip->oob_poi + oob_off; + u8 *oob = nand->oob_poi + oob_off; - ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, + ret = sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, oob, oob_off + mtd->writesize, &cur_off, &max_bitflips, !i, oob_required, page); @@ -1215,52 +1094,55 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *chip, uint8_t *buf, } if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off, + sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, !raw_mode, page); - sunxi_nfc_hw_ecc_disable(mtd); + sunxi_nfc_hw_ecc_disable(nand); return max_bitflips; } -static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *chip, u8 *buf, +static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *nand, u8 *buf, int oob_required, int page) { - struct mtd_info *mtd = nand_to_mtd(chip); int ret; - nand_read_page_op(chip, page, 0, NULL, 0); + sunxi_nfc_select_chip(nand, nand->cur_cs); + + nand_read_page_op(nand, page, 0, NULL, 0); - ret = sunxi_nfc_hw_ecc_read_chunks_dma(mtd, buf, oob_required, page, - chip->ecc.steps); + ret = sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, oob_required, page, + nand->ecc.steps); if (ret >= 0) return ret; /* Fallback to PIO mode */ - return sunxi_nfc_hw_ecc_read_page(chip, buf, oob_required, page); + return sunxi_nfc_hw_ecc_read_page(nand, buf, oob_required, page); } -static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *chip, +static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand, u32 data_offs, u32 readlen, u8 *bufpoi, int page) { - struct mtd_info *mtd = nand_to_mtd(chip); - struct nand_ecc_ctrl *ecc = &chip->ecc; + struct mtd_info *mtd = nand_to_mtd(nand); + struct nand_ecc_ctrl *ecc = &nand->ecc; int ret, i, cur_off = 0; unsigned int max_bitflips = 0; - nand_read_page_op(chip, page, 0, NULL, 0); + sunxi_nfc_select_chip(nand, nand->cur_cs); + + nand_read_page_op(nand, page, 0, NULL, 0); - sunxi_nfc_hw_ecc_enable(mtd); + sunxi_nfc_hw_ecc_enable(nand); for (i = data_offs / ecc->size; i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { int data_off = i * ecc->size; int oob_off = i * (ecc->bytes + 4); u8 *data = bufpoi + data_off; - u8 *oob = chip->oob_poi + oob_off; + u8 *oob = nand->oob_poi + oob_off; - ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, + ret = sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, oob, oob_off + mtd->writesize, &cur_off, &max_bitflips, !i, @@ -1269,113 +1151,118 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *chip, return ret; } - sunxi_nfc_hw_ecc_disable(mtd); + sunxi_nfc_hw_ecc_disable(nand); return max_bitflips; } -static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *chip, +static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *nand, u32 data_offs, u32 readlen, u8 *buf, int page) { - struct mtd_info *mtd = nand_to_mtd(chip); - int nchunks = DIV_ROUND_UP(data_offs + readlen, chip->ecc.size); + int nchunks = DIV_ROUND_UP(data_offs + readlen, nand->ecc.size); int ret; - nand_read_page_op(chip, page, 0, NULL, 0); + sunxi_nfc_select_chip(nand, nand->cur_cs); + + nand_read_page_op(nand, page, 0, NULL, 0); - ret = sunxi_nfc_hw_ecc_read_chunks_dma(mtd, buf, false, page, nchunks); + ret = sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, false, page, nchunks); if (ret >= 0) return ret; /* Fallback to PIO mode */ - return sunxi_nfc_hw_ecc_read_subpage(chip, data_offs, readlen, + return sunxi_nfc_hw_ecc_read_subpage(nand, data_offs, readlen, buf, page); } -static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *chip, +static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *nand, const uint8_t *buf, int oob_required, int page) { - struct mtd_info *mtd = nand_to_mtd(chip); - struct nand_ecc_ctrl *ecc = &chip->ecc; + struct mtd_info *mtd = nand_to_mtd(nand); + struct nand_ecc_ctrl *ecc = &nand->ecc; int ret, i, cur_off = 0; - nand_prog_page_begin_op(chip, page, 0, NULL, 0); + sunxi_nfc_select_chip(nand, nand->cur_cs); + + nand_prog_page_begin_op(nand, page, 0, NULL, 0); - sunxi_nfc_hw_ecc_enable(mtd); + sunxi_nfc_hw_ecc_enable(nand); for (i = 0; i < ecc->steps; i++) { int data_off = i * ecc->size; int oob_off = i * (ecc->bytes + 4); const u8 *data = buf + data_off; - const u8 *oob = chip->oob_poi + oob_off; + const u8 *oob = nand->oob_poi + oob_off; - ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob, + ret = sunxi_nfc_hw_ecc_write_chunk(nand, data, data_off, oob, oob_off + mtd->writesize, &cur_off, !i, page); if (ret) return ret; } - if (oob_required || (chip->options & NAND_NEED_SCRAMBLING)) - sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, + if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) + sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, &cur_off, page); - sunxi_nfc_hw_ecc_disable(mtd); + sunxi_nfc_hw_ecc_disable(nand); - return nand_prog_page_end_op(chip); + return nand_prog_page_end_op(nand); } -static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *chip, +static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *nand, u32 data_offs, u32 data_len, const u8 *buf, int oob_required, int page) { - struct mtd_info *mtd = nand_to_mtd(chip); - struct nand_ecc_ctrl *ecc = &chip->ecc; + struct mtd_info *mtd = nand_to_mtd(nand); + struct nand_ecc_ctrl *ecc = &nand->ecc; int ret, i, cur_off = 0; - nand_prog_page_begin_op(chip, page, 0, NULL, 0); + sunxi_nfc_select_chip(nand, nand->cur_cs); - sunxi_nfc_hw_ecc_enable(mtd); + nand_prog_page_begin_op(nand, page, 0, NULL, 0); + + sunxi_nfc_hw_ecc_enable(nand); for (i = data_offs / ecc->size; i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) { int data_off = i * ecc->size; int oob_off = i * (ecc->bytes + 4); const u8 *data = buf + data_off; - const u8 *oob = chip->oob_poi + oob_off; + const u8 *oob = nand->oob_poi + oob_off; - ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob, + ret = sunxi_nfc_hw_ecc_write_chunk(nand, data, data_off, oob, oob_off + mtd->writesize, &cur_off, !i, page); if (ret) return ret; } - sunxi_nfc_hw_ecc_disable(mtd); + sunxi_nfc_hw_ecc_disable(nand); - return nand_prog_page_end_op(chip); + return nand_prog_page_end_op(nand); } -static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *chip, +static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, const u8 *buf, int oob_required, int page) { - struct mtd_info *mtd = nand_to_mtd(chip); - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; struct scatterlist sg; int ret, i; + sunxi_nfc_select_chip(nand, nand->cur_cs); + ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) return ret; - ret = sunxi_nfc_dma_op_prepare(mtd, buf, ecc->size, ecc->steps, + ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, ecc->steps, DMA_TO_DEVICE, &sg); if (ret) goto pio_fallback; @@ -1383,14 +1270,14 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *chip, for (i = 0; i < ecc->steps; i++) { const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4)); - sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, i, !i, page); + sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page); } - nand_prog_page_begin_op(chip, page, 0, NULL, 0); + nand_prog_page_begin_op(nand, page, 0, NULL, 0); - sunxi_nfc_hw_ecc_enable(mtd); - sunxi_nfc_randomizer_config(mtd, page, false); - sunxi_nfc_randomizer_enable(mtd); + sunxi_nfc_hw_ecc_enable(nand); + sunxi_nfc_randomizer_config(nand, page, false); + sunxi_nfc_randomizer_enable(nand); writel((NAND_CMD_RNDIN << 8) | NAND_CMD_PAGEPROG, nfc->regs + NFC_REG_WCMD_SET); @@ -1405,46 +1292,46 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *chip, if (ret) dmaengine_terminate_all(nfc->dmac); - sunxi_nfc_randomizer_disable(mtd); - sunxi_nfc_hw_ecc_disable(mtd); + sunxi_nfc_randomizer_disable(nand); + sunxi_nfc_hw_ecc_disable(nand); - sunxi_nfc_dma_op_cleanup(mtd, DMA_TO_DEVICE, &sg); + sunxi_nfc_dma_op_cleanup(nfc, DMA_TO_DEVICE, &sg); if (ret) return ret; - if (oob_required || (chip->options & NAND_NEED_SCRAMBLING)) + if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) /* TODO: use DMA to transfer extra OOB bytes ? */ - sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, + sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, NULL, page); - return nand_prog_page_end_op(chip); + return nand_prog_page_end_op(nand); pio_fallback: - return sunxi_nfc_hw_ecc_write_page(chip, buf, oob_required, page); + return sunxi_nfc_hw_ecc_write_page(nand, buf, oob_required, page); } -static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *chip, int page) +static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *nand, int page) { - chip->pagebuf = -1; + nand->pagebuf = -1; - return chip->ecc.read_page(chip, chip->data_buf, 1, page); + return nand->ecc.read_page(nand, nand->data_buf, 1, page); } -static int sunxi_nfc_hw_ecc_write_oob(struct nand_chip *chip, int page) +static int sunxi_nfc_hw_ecc_write_oob(struct nand_chip *nand, int page) { - struct mtd_info *mtd = nand_to_mtd(chip); + struct mtd_info *mtd = nand_to_mtd(nand); int ret; - chip->pagebuf = -1; + nand->pagebuf = -1; - memset(chip->data_buf, 0xff, mtd->writesize); - ret = chip->ecc.write_page(chip, chip->data_buf, 1, page); + memset(nand->data_buf, 0xff, mtd->writesize); + ret = nand->ecc.write_page(nand, nand->data_buf, 1, page); if (ret) return ret; /* Send command to program the OOB data */ - return nand_prog_page_end_op(chip); + return nand_prog_page_end_op(nand); } static const s32 tWB_lut[] = {6, 12, 16, 20}; @@ -1471,8 +1358,8 @@ static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration, static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline, const struct nand_data_interface *conf) { - struct sunxi_nand_chip *chip = to_sunxi_nand(nand); - struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller); + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); const struct nand_sdr_timings *timings; u32 min_clk_period = 0; s32 tWB, tADL, tWHR, tRHW, tCAD; @@ -1555,6 +1442,20 @@ static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline, if (timings->tRHW_min > (min_clk_period * 20)) min_clk_period = DIV_ROUND_UP(timings->tRHW_min, 20); + /* + * In non-EDO, tREA should be less than tRP to guarantee that the + * controller does not sample the IO lines too early. Unfortunately, + * the sunxi NAND controller does not allow us to have different + * values for tRP and tREH (tRP = tREH = tRW / 2). + * + * We have 2 options to overcome this limitation: + * + * 1/ Extend tRC to fulfil the tREA <= tRC / 2 constraint + * 2/ Use EDO mode (only works if timings->tRLOH > 0) + */ + if (timings->tREA_max > min_clk_period && !timings->tRLOH_min) + min_clk_period = timings->tREA_max; + tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max, min_clk_period); if (tWB < 0) { @@ -1591,7 +1492,7 @@ static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline, tCAD = 0x7; /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */ - chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD); + sunxi_nand->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD); /* Convert min_clk_period from picoseconds to nanoseconds */ min_clk_period = DIV_ROUND_UP(min_clk_period, 1000); @@ -1602,21 +1503,24 @@ static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline, * This new formula was verified with a scope and validated by * Allwinner engineers. */ - chip->clk_rate = NSEC_PER_SEC / min_clk_period; - real_clk_rate = clk_round_rate(nfc->mod_clk, chip->clk_rate); + sunxi_nand->clk_rate = NSEC_PER_SEC / min_clk_period; + real_clk_rate = clk_round_rate(nfc->mod_clk, sunxi_nand->clk_rate); if (real_clk_rate <= 0) { - dev_err(nfc->dev, "Unable to round clk %lu\n", chip->clk_rate); + dev_err(nfc->dev, "Unable to round clk %lu\n", + sunxi_nand->clk_rate); return -EINVAL; } + sunxi_nand->timing_ctl = 0; + /* * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data * output cycle timings shall be used if the host drives tRC less than - * 30 ns. + * 30 ns. We should also use EDO mode if tREA is bigger than tRP. */ min_clk_period = NSEC_PER_SEC / real_clk_rate; - chip->timing_ctl = ((min_clk_period * 2) < 30) ? - NFC_TIMING_CTL_EDO : 0; + if (min_clk_period * 2 < 30 || min_clk_period * 1000 < timings->tREA_max) + sunxi_nand->timing_ctl = NFC_TIMING_CTL_EDO; return 0; } @@ -1677,14 +1581,13 @@ static void sunxi_nand_hw_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc) kfree(ecc->priv); } -static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, +static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, struct nand_ecc_ctrl *ecc, struct device_node *np) { static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 }; - struct nand_chip *nand = mtd_to_nand(mtd); - struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); - struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct mtd_info *mtd = nand_to_mtd(nand); struct sunxi_nand_hw_ecc *data; int nsectors; int ret; @@ -1808,7 +1711,6 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc) static int sunxi_nand_attach_chip(struct nand_chip *nand) { - struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; struct device_node *np = nand_get_flash_node(nand); int ret; @@ -1831,7 +1733,7 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand) switch (ecc->mode) { case NAND_ECC_HW: - ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np); + ret = sunxi_nand_hw_ecc_ctrl_init(nand, ecc, np); if (ret) return ret; break; @@ -1845,15 +1747,165 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand) return 0; } +static int sunxi_nfc_exec_subop(struct nand_chip *nand, + const struct nand_subop *subop) +{ + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + u32 cmd = 0, extcmd = 0, cnt = 0, addrs[2] = { }; + unsigned int i, j, remaining, start; + void *inbuf = NULL; + int ret; + + for (i = 0; i < subop->ninstrs; i++) { + const struct nand_op_instr *instr = &subop->instrs[i]; + + switch (instr->type) { + case NAND_OP_CMD_INSTR: + if (cmd & NFC_SEND_CMD1) { + if (WARN_ON(cmd & NFC_SEND_CMD2)) + return -EINVAL; + + cmd |= NFC_SEND_CMD2; + extcmd |= instr->ctx.cmd.opcode; + } else { + cmd |= NFC_SEND_CMD1 | + NFC_CMD(instr->ctx.cmd.opcode); + } + break; + + case NAND_OP_ADDR_INSTR: + remaining = nand_subop_get_num_addr_cyc(subop, i); + start = nand_subop_get_addr_start_off(subop, i); + for (j = 0; j < 8 && j + start < remaining; j++) { + u32 addr = instr->ctx.addr.addrs[j + start]; + + addrs[j / 4] |= addr << (j % 4) * 8; + } + + if (j) + cmd |= NFC_SEND_ADR | NFC_ADR_NUM(j); + + break; + + case NAND_OP_DATA_IN_INSTR: + case NAND_OP_DATA_OUT_INSTR: + start = nand_subop_get_data_start_off(subop, i); + remaining = nand_subop_get_data_len(subop, i); + cnt = min_t(u32, remaining, NFC_SRAM_SIZE); + cmd |= NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD; + + if (instr->type == NAND_OP_DATA_OUT_INSTR) { + cmd |= NFC_ACCESS_DIR; + memcpy_toio(nfc->regs + NFC_RAM0_BASE, + instr->ctx.data.buf.out + start, + cnt); + } else { + inbuf = instr->ctx.data.buf.in + start; + } + + break; + + case NAND_OP_WAITRDY_INSTR: + cmd |= NFC_WAIT_FLAG; + break; + } + } + + ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); + if (ret) + return ret; + + if (cmd & NFC_SEND_ADR) { + writel(addrs[0], nfc->regs + NFC_REG_ADDR_LOW); + writel(addrs[1], nfc->regs + NFC_REG_ADDR_HIGH); + } + + if (cmd & NFC_SEND_CMD2) + writel(extcmd, + nfc->regs + + (cmd & NFC_ACCESS_DIR ? + NFC_REG_WCMD_SET : NFC_REG_RCMD_SET)); + + if (cmd & NFC_DATA_TRANS) + writel(cnt, nfc->regs + NFC_REG_CNT); + + writel(cmd, nfc->regs + NFC_REG_CMD); + + ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, + !(cmd & NFC_WAIT_FLAG) && cnt < 64, + 0); + if (ret) + return ret; + + if (inbuf) + memcpy_fromio(inbuf, nfc->regs + NFC_RAM0_BASE, cnt); + + return 0; +} + +static int sunxi_nfc_soft_waitrdy(struct nand_chip *nand, + const struct nand_subop *subop) +{ + return nand_soft_waitrdy(nand, + subop->instrs[0].ctx.waitrdy.timeout_ms); +} + +static const struct nand_op_parser sunxi_nfc_op_parser = NAND_OP_PARSER( + NAND_OP_PARSER_PATTERN(sunxi_nfc_exec_subop, + NAND_OP_PARSER_PAT_CMD_ELEM(true), + NAND_OP_PARSER_PAT_ADDR_ELEM(true, 8), + NAND_OP_PARSER_PAT_CMD_ELEM(true), + NAND_OP_PARSER_PAT_WAITRDY_ELEM(true), + NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, 1024)), + NAND_OP_PARSER_PATTERN(sunxi_nfc_exec_subop, + NAND_OP_PARSER_PAT_CMD_ELEM(true), + NAND_OP_PARSER_PAT_ADDR_ELEM(true, 8), + NAND_OP_PARSER_PAT_DATA_OUT_ELEM(true, 1024), + NAND_OP_PARSER_PAT_CMD_ELEM(true), + NAND_OP_PARSER_PAT_WAITRDY_ELEM(true)), +); + +static const struct nand_op_parser sunxi_nfc_norb_op_parser = NAND_OP_PARSER( + NAND_OP_PARSER_PATTERN(sunxi_nfc_exec_subop, + NAND_OP_PARSER_PAT_CMD_ELEM(true), + NAND_OP_PARSER_PAT_ADDR_ELEM(true, 8), + NAND_OP_PARSER_PAT_CMD_ELEM(true), + NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, 1024)), + NAND_OP_PARSER_PATTERN(sunxi_nfc_exec_subop, + NAND_OP_PARSER_PAT_CMD_ELEM(true), + NAND_OP_PARSER_PAT_ADDR_ELEM(true, 8), + NAND_OP_PARSER_PAT_DATA_OUT_ELEM(true, 1024), + NAND_OP_PARSER_PAT_CMD_ELEM(true)), + NAND_OP_PARSER_PATTERN(sunxi_nfc_soft_waitrdy, + NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)), +); + +static int sunxi_nfc_exec_op(struct nand_chip *nand, + const struct nand_operation *op, bool check_only) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + const struct nand_op_parser *parser; + + sunxi_nfc_select_chip(nand, op->cs); + + if (sunxi_nand->sels[op->cs].rb >= 0) + parser = &sunxi_nfc_op_parser; + else + parser = &sunxi_nfc_norb_op_parser; + + return nand_op_parser_exec_op(nand, parser, op, check_only); +} + static const struct nand_controller_ops sunxi_nand_controller_ops = { .attach_chip = sunxi_nand_attach_chip, .setup_data_interface = sunxi_nfc_setup_data_interface, + .exec_op = sunxi_nfc_exec_op, }; static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, struct device_node *np) { - struct sunxi_nand_chip *chip; + struct sunxi_nand_chip *sunxi_nand; struct mtd_info *mtd; struct nand_chip *nand; int nsels; @@ -1870,17 +1922,14 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, return -EINVAL; } - chip = devm_kzalloc(dev, - sizeof(*chip) + - (nsels * sizeof(struct sunxi_nand_chip_sel)), - GFP_KERNEL); - if (!chip) { + sunxi_nand = devm_kzalloc(dev, struct_size(sunxi_nand, sels, nsels), + GFP_KERNEL); + if (!sunxi_nand) { dev_err(dev, "could not allocate chip\n"); return -ENOMEM; } - chip->nsels = nsels; - chip->selected = -1; + sunxi_nand->nsels = nsels; for (i = 0; i < nsels; i++) { ret = of_property_read_u32_index(np, "reg", i, &tmp); @@ -1902,18 +1951,17 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, return -EINVAL; } - chip->sels[i].cs = tmp; + sunxi_nand->sels[i].cs = tmp; if (!of_property_read_u32_index(np, "allwinner,rb", i, &tmp) && tmp < 2) - chip->sels[i].rb = tmp; + sunxi_nand->sels[i].rb = tmp; else - chip->sels[i].rb = -1; + sunxi_nand->sels[i].rb = -1; } - nand = &chip->nand; + nand = &sunxi_nand->nand; /* Default tR value specified in the ONFI spec (chapter 4.15.1) */ - nand->legacy.chip_delay = 200; nand->controller = &nfc->controller; nand->controller->ops = &sunxi_nand_controller_ops; @@ -1923,11 +1971,6 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, */ nand->ecc.mode = NAND_ECC_HW; nand_set_flash_node(nand, np); - nand->legacy.select_chip = sunxi_nfc_select_chip; - nand->legacy.cmd_ctrl = sunxi_nfc_cmd_ctrl; - nand->legacy.read_buf = sunxi_nfc_read_buf; - nand->legacy.write_buf = sunxi_nfc_write_buf; - nand->legacy.read_byte = sunxi_nfc_read_byte; mtd = nand_to_mtd(nand); mtd->dev.parent = dev; @@ -1943,7 +1986,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, return ret; } - list_add_tail(&chip->node, &nfc->chips); + list_add_tail(&sunxi_nand->node, &nfc->chips); return 0; } @@ -1973,14 +2016,15 @@ static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc) static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc) { - struct sunxi_nand_chip *chip; + struct sunxi_nand_chip *sunxi_nand; while (!list_empty(&nfc->chips)) { - chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip, - node); - nand_release(&chip->nand); - sunxi_nand_ecc_cleanup(&chip->nand.ecc); - list_del(&chip->node); + sunxi_nand = list_first_entry(&nfc->chips, + struct sunxi_nand_chip, + node); + nand_release(&sunxi_nand->nand); + sunxi_nand_ecc_cleanup(&sunxi_nand->nand.ecc); + list_del(&sunxi_nand->node); } } @@ -2124,7 +2168,7 @@ static struct platform_driver sunxi_nfc_driver = { }; module_platform_driver(sunxi_nfc_driver); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); MODULE_AUTHOR("Boris BREZILLON"); MODULE_DESCRIPTION("Allwinner NAND Flash Controller driver"); MODULE_ALIAS("platform:sunxi_nand"); diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index f3b59e649b7d..db030f1701ee 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -104,6 +104,7 @@ struct tmio_nand { struct nand_chip chip; + struct completion comp; struct platform_device *dev; @@ -168,15 +169,11 @@ static int tmio_nand_dev_ready(struct nand_chip *chip) static irqreturn_t tmio_irq(int irq, void *__tmio) { struct tmio_nand *tmio = __tmio; - struct nand_chip *nand_chip = &tmio->chip; /* disable RDYREQ interrupt */ tmio_iowrite8(0x00, tmio->fcr + FCR_IMR); + complete(&tmio->comp); - if (unlikely(!waitqueue_active(&nand_chip->controller->wq))) - dev_warn(&tmio->dev->dev, "spurious interrupt\n"); - - wake_up(&nand_chip->controller->wq); return IRQ_HANDLED; } @@ -193,18 +190,18 @@ static int tmio_nand_wait(struct nand_chip *nand_chip) u8 status; /* enable RDYREQ interrupt */ + tmio_iowrite8(0x0f, tmio->fcr + FCR_ISR); + reinit_completion(&tmio->comp); tmio_iowrite8(0x81, tmio->fcr + FCR_IMR); - timeout = wait_event_timeout(nand_chip->controller->wq, - tmio_nand_dev_ready(nand_chip), - msecs_to_jiffies(nand_chip->state == FL_ERASING ? 400 : 20)); + timeout = 400; + timeout = wait_for_completion_timeout(&tmio->comp, + msecs_to_jiffies(timeout)); if (unlikely(!tmio_nand_dev_ready(nand_chip))) { tmio_iowrite8(0x00, tmio->fcr + FCR_IMR); - dev_warn(&tmio->dev->dev, "still busy with %s after %d ms\n", - nand_chip->state == FL_ERASING ? "erase" : "program", - nand_chip->state == FL_ERASING ? 400 : 20); + dev_warn(&tmio->dev->dev, "still busy after 400 ms\n"); } else if (unlikely(!timeout)) { tmio_iowrite8(0x00, tmio->fcr + FCR_IMR); @@ -378,6 +375,8 @@ static int tmio_probe(struct platform_device *dev) if (!tmio) return -ENOMEM; + init_completion(&tmio->comp); + tmio->dev = dev; platform_set_drvdata(dev, tmio); diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 479c2f2cf17f..fa87ae28cdfe 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -304,24 +304,30 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand, struct nand_device *nand = spinand_to_nand(spinand); struct mtd_info *mtd = nanddev_to_mtd(nand); struct nand_page_io_req adjreq = *req; - unsigned int nbytes = 0; - void *buf = NULL; + void *buf = spinand->databuf; + unsigned int nbytes; u16 column = 0; int ret; - memset(spinand->databuf, 0xff, - nanddev_page_size(nand) + - nanddev_per_page_oobsize(nand)); + /* + * Looks like PROGRAM LOAD (AKA write cache) does not necessarily reset + * the cache content to 0xFF (depends on vendor implementation), so we + * must fill the page cache entirely even if we only want to program + * the data portion of the page, otherwise we might corrupt the BBM or + * user data previously programmed in OOB area. + */ + nbytes = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); + memset(spinand->databuf, 0xff, nbytes); + adjreq.dataoffs = 0; + adjreq.datalen = nanddev_page_size(nand); + adjreq.databuf.out = spinand->databuf; + adjreq.ooblen = nanddev_per_page_oobsize(nand); + adjreq.ooboffs = 0; + adjreq.oobbuf.out = spinand->oobbuf; - if (req->datalen) { + if (req->datalen) memcpy(spinand->databuf + req->dataoffs, req->databuf.out, req->datalen); - adjreq.dataoffs = 0; - adjreq.datalen = nanddev_page_size(nand); - adjreq.databuf.out = spinand->databuf; - nbytes = adjreq.datalen; - buf = spinand->databuf; - } if (req->ooblen) { if (req->mode == MTD_OPS_AUTO_OOB) @@ -332,14 +338,6 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand, else memcpy(spinand->oobbuf + req->ooboffs, req->oobbuf.out, req->ooblen); - - adjreq.ooblen = nanddev_per_page_oobsize(nand); - adjreq.ooboffs = 0; - nbytes += nanddev_per_page_oobsize(nand); - if (!buf) { - buf = spinand->oobbuf; - column = nanddev_page_size(nand); - } } spinand_cache_op_adjust_colum(spinand, &adjreq, &column); @@ -370,8 +368,8 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand, /* * We need to use the RANDOM LOAD CACHE operation if there's - * more than one iteration, because the LOAD operation resets - * the cache to 0xff. + * more than one iteration, because the LOAD operation might + * reset the cache to 0xff. */ if (nbytes) { column = op.addr.val; @@ -1018,11 +1016,11 @@ static int spinand_init(struct spinand_device *spinand) for (i = 0; i < nand->memorg.ntargets; i++) { ret = spinand_select_target(spinand, i); if (ret) - goto err_free_bufs; + goto err_manuf_cleanup; ret = spinand_lock_block(spinand, BL_ALL_UNLOCKED); if (ret) - goto err_free_bufs; + goto err_manuf_cleanup; } ret = nanddev_init(nand, &spinand_ops, THIS_MODULE); diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c index e4141c20947a..0b49d8264bef 100644 --- a/drivers/mtd/nand/spi/gigadevice.c +++ b/drivers/mtd/nand/spi/gigadevice.c @@ -12,6 +12,8 @@ #define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS (1 << 4) #define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS (3 << 4) +#define GD5FXGQ4UEXXG_REG_STATUS2 0xf0 + static SPINAND_OP_VARIANTS(read_cache_variants, SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), @@ -81,11 +83,83 @@ static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand, return -EINVAL; } +static int gd5fxgq4uexxg_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section) + return -ERANGE; + + region->offset = 64; + region->length = 64; + + return 0; +} + +static int gd5fxgq4uexxg_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section) + return -ERANGE; + + /* Reserve 1 bytes for the BBM. */ + region->offset = 1; + region->length = 63; + + return 0; +} + +static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand, + u8 status) +{ + u8 status2; + struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQ4UEXXG_REG_STATUS2, + &status2); + int ret; + + switch (status & STATUS_ECC_MASK) { + case STATUS_ECC_NO_BITFLIPS: + return 0; + + case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS: + /* + * Read status2 register to determine a more fine grained + * bit error status + */ + ret = spi_mem_exec_op(spinand->spimem, &op); + if (ret) + return ret; + + /* + * 4 ... 7 bits are flipped (1..4 can't be detected, so + * report the maximum of 4 in this case + */ + /* bits sorted this way (3...0): ECCS1,ECCS0,ECCSE1,ECCSE0 */ + return ((status & STATUS_ECC_MASK) >> 2) | + ((status2 & STATUS_ECC_MASK) >> 4); + + case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS: + return 8; + + case STATUS_ECC_UNCOR_ERROR: + return -EBADMSG; + + default: + break; + } + + return -EINVAL; +} + static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = { .ecc = gd5fxgq4xa_ooblayout_ecc, .free = gd5fxgq4xa_ooblayout_free, }; +static const struct mtd_ooblayout_ops gd5fxgq4uexxg_ooblayout = { + .ecc = gd5fxgq4uexxg_ooblayout_ecc, + .free = gd5fxgq4uexxg_ooblayout_free, +}; + static const struct spinand_info gigadevice_spinand_table[] = { SPINAND_INFO("GD5F1GQ4xA", 0xF1, NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), @@ -114,6 +188,15 @@ static const struct spinand_info gigadevice_spinand_table[] = { 0, SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, gd5fxgq4xa_ecc_get_status)), + SPINAND_INFO("GD5F1GQ4UExxG", 0xd1, + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&gd5fxgq4uexxg_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), }; static int gigadevice_spinand_detect(struct spinand_device *spinand) diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c index 98f6b9c4b684..d16b57081c95 100644 --- a/drivers/mtd/nand/spi/macronix.c +++ b/drivers/mtd/nand/spi/macronix.c @@ -10,6 +10,7 @@ #include <linux/mtd/spinand.h> #define SPINAND_MFR_MACRONIX 0xC2 +#define MACRONIX_ECCSR_MASK 0x0F static SPINAND_OP_VARIANTS(read_cache_variants, SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), @@ -55,7 +56,12 @@ static int mx35lf1ge4ab_get_eccsr(struct spinand_device *spinand, u8 *eccsr) SPI_MEM_OP_DUMMY(1, 1), SPI_MEM_OP_DATA_IN(1, eccsr, 1)); - return spi_mem_exec_op(spinand->spimem, &op); + int ret = spi_mem_exec_op(spinand->spimem, &op); + if (ret) + return ret; + + *eccsr &= MACRONIX_ECCSR_MASK; + return 0; } static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand, diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c index 081265557e70..db8021da45b5 100644 --- a/drivers/mtd/nand/spi/toshiba.c +++ b/drivers/mtd/nand/spi/toshiba.c @@ -25,19 +25,19 @@ static SPINAND_OP_VARIANTS(write_cache_variants, static SPINAND_OP_VARIANTS(update_cache_variants, SPINAND_PROG_LOAD(false, 0, NULL, 0)); -static int tc58cvg2s0h_ooblayout_ecc(struct mtd_info *mtd, int section, +static int tc58cxgxsx_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *region) { - if (section > 7) + if (section > 0) return -ERANGE; - region->offset = 128 + 16 * section; - region->length = 16; + region->offset = mtd->oobsize / 2; + region->length = mtd->oobsize / 2; return 0; } -static int tc58cvg2s0h_ooblayout_free(struct mtd_info *mtd, int section, +static int tc58cxgxsx_ooblayout_free(struct mtd_info *mtd, int section, struct mtd_oob_region *region) { if (section > 0) @@ -45,17 +45,17 @@ static int tc58cvg2s0h_ooblayout_free(struct mtd_info *mtd, int section, /* 2 bytes reserved for BBM */ region->offset = 2; - region->length = 126; + region->length = (mtd->oobsize / 2) - 2; return 0; } -static const struct mtd_ooblayout_ops tc58cvg2s0h_ooblayout = { - .ecc = tc58cvg2s0h_ooblayout_ecc, - .free = tc58cvg2s0h_ooblayout_free, +static const struct mtd_ooblayout_ops tc58cxgxsx_ooblayout = { + .ecc = tc58cxgxsx_ooblayout_ecc, + .free = tc58cxgxsx_ooblayout_free, }; -static int tc58cvg2s0h_ecc_get_status(struct spinand_device *spinand, +static int tc58cxgxsx_ecc_get_status(struct spinand_device *spinand, u8 status) { struct nand_device *nand = spinand_to_nand(spinand); @@ -94,15 +94,66 @@ static int tc58cvg2s0h_ecc_get_status(struct spinand_device *spinand, } static const struct spinand_info toshiba_spinand_table[] = { - SPINAND_INFO("TC58CVG2S0H", 0xCD, + /* 3.3V 1Gb */ + SPINAND_INFO("TC58CVG0S3", 0xC2, + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, + tc58cxgxsx_ecc_get_status)), + /* 3.3V 2Gb */ + SPINAND_INFO("TC58CVG1S3", 0xCB, + NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, + tc58cxgxsx_ecc_get_status)), + /* 3.3V 4Gb */ + SPINAND_INFO("TC58CVG2S0", 0xCD, + NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, + tc58cxgxsx_ecc_get_status)), + /* 1.8V 1Gb */ + SPINAND_INFO("TC58CYG0S3", 0xB2, + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, + tc58cxgxsx_ecc_get_status)), + /* 1.8V 2Gb */ + SPINAND_INFO("TC58CYG1S3", 0xBB, + NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, + tc58cxgxsx_ecc_get_status)), + /* 1.8V 4Gb */ + SPINAND_INFO("TC58CYG2S0", 0xBD, NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - SPINAND_HAS_QE_BIT, - SPINAND_ECCINFO(&tc58cvg2s0h_ooblayout, - tc58cvg2s0h_ecc_get_status)), + 0, + SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, + tc58cxgxsx_ecc_get_status)), }; static int toshiba_spinand_detect(struct spinand_device *spinand) diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig index 44fe8018733c..dab986691267 100644 --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig @@ -7,14 +7,6 @@ menuconfig MTD_SPI_NOR if MTD_SPI_NOR -config MTD_MT81xx_NOR - tristate "Mediatek MT81xx SPI NOR flash controller" - depends on HAS_IOMEM - help - This enables access to SPI NOR flash, using MT81xx SPI NOR flash - controller. This controller does not support generic SPI BUS, it only - supports SPI NOR Flash. - config MTD_SPI_NOR_USE_4K_SECTORS bool "Use small 4096 B erase sectors" default y @@ -50,15 +42,6 @@ config SPI_CADENCE_QUADSPI device with a Cadence QSPI controller and want to access the Flash as an MTD device. -config SPI_FSL_QUADSPI - tristate "Freescale Quad SPI controller" - depends on ARCH_MXC || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST - depends on HAS_IOMEM - help - This enables support for the Quad SPI controller in master mode. - This controller does not support generic SPI. It only supports - SPI NOR. - config SPI_HISI_SFC tristate "Hisilicon SPI-NOR Flash Controller(SFC)" depends on ARCH_HISI || COMPILE_TEST @@ -66,6 +49,14 @@ config SPI_HISI_SFC help This enables support for hisilicon SPI-NOR flash controller. +config SPI_MTK_QUADSPI + tristate "MediaTek Quad SPI controller" + depends on HAS_IOMEM + help + This enables support for the Quad SPI controller in master mode. + This controller does not support generic SPI. It only supports + SPI NOR. + config SPI_NXP_SPIFI tristate "NXP SPI Flash Interface (SPIFI)" depends on OF && (ARCH_LPC18XX || COMPILE_TEST) diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile index a552efd22958..189a15cca3ec 100644 --- a/drivers/mtd/spi-nor/Makefile +++ b/drivers/mtd/spi-nor/Makefile @@ -2,9 +2,8 @@ obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o obj-$(CONFIG_SPI_ASPEED_SMC) += aspeed-smc.o obj-$(CONFIG_SPI_CADENCE_QUADSPI) += cadence-quadspi.o -obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o -obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o +obj-$(CONFIG_SPI_MTK_QUADSPI) += mtk-quadspi.o obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o obj-$(CONFIG_SPI_INTEL_SPI_PCI) += intel-spi-pci.o diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index 04cedd3a2bf6..792628750eec 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c @@ -44,6 +44,12 @@ /* Quirks */ #define CQSPI_NEEDS_WR_DELAY BIT(0) +/* Capabilities mask */ +#define CQSPI_BASE_HWCAPS_MASK \ + (SNOR_HWCAPS_READ | SNOR_HWCAPS_READ_FAST | \ + SNOR_HWCAPS_READ_1_1_2 | SNOR_HWCAPS_READ_1_1_4 | \ + SNOR_HWCAPS_PP) + struct cqspi_st; struct cqspi_flash_pdata { @@ -93,6 +99,11 @@ struct cqspi_st { struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT]; }; +struct cqspi_driver_platdata { + u32 hwcaps_mask; + u8 quirks; +}; + /* Operation timeout value */ #define CQSPI_TIMEOUT_MS 500 #define CQSPI_READ_TIMEOUT_MS 10 @@ -101,6 +112,7 @@ struct cqspi_st { #define CQSPI_INST_TYPE_SINGLE 0 #define CQSPI_INST_TYPE_DUAL 1 #define CQSPI_INST_TYPE_QUAD 2 +#define CQSPI_INST_TYPE_OCTAL 3 #define CQSPI_DUMMY_CLKS_PER_BYTE 8 #define CQSPI_DUMMY_BYTES_MAX 4 @@ -418,9 +430,10 @@ static int cqspi_command_write(struct spi_nor *nor, const u8 opcode, void __iomem *reg_base = cqspi->iobase; unsigned int reg; unsigned int data; + u32 write_len; int ret; - if (n_tx > 4 || (n_tx && !txbuf)) { + if (n_tx > CQSPI_STIG_DATA_LEN_MAX || (n_tx && !txbuf)) { dev_err(nor->dev, "Invalid input argument, cmdlen %d txbuf 0x%p\n", n_tx, txbuf); @@ -433,10 +446,18 @@ static int cqspi_command_write(struct spi_nor *nor, const u8 opcode, reg |= ((n_tx - 1) & CQSPI_REG_CMDCTRL_WR_BYTES_MASK) << CQSPI_REG_CMDCTRL_WR_BYTES_LSB; data = 0; - memcpy(&data, txbuf, n_tx); + write_len = (n_tx > 4) ? 4 : n_tx; + memcpy(&data, txbuf, write_len); + txbuf += write_len; writel(data, reg_base + CQSPI_REG_CMDWRITEDATALOWER); - } + if (n_tx > 4) { + data = 0; + write_len = n_tx - 4; + memcpy(&data, txbuf, write_len); + writel(data, reg_base + CQSPI_REG_CMDWRITEDATAUPPER); + } + } ret = cqspi_exec_flash_cmd(cqspi, reg); return ret; } @@ -911,6 +932,9 @@ static int cqspi_set_protocol(struct spi_nor *nor, const int read) case SNOR_PROTO_1_1_4: f_pdata->data_width = CQSPI_INST_TYPE_QUAD; break; + case SNOR_PROTO_1_1_8: + f_pdata->data_width = CQSPI_INST_TYPE_OCTAL; + break; default: return -EINVAL; } @@ -1213,21 +1237,23 @@ static void cqspi_request_mmap_dma(struct cqspi_st *cqspi) static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np) { - const struct spi_nor_hwcaps hwcaps = { - .mask = SNOR_HWCAPS_READ | - SNOR_HWCAPS_READ_FAST | - SNOR_HWCAPS_READ_1_1_2 | - SNOR_HWCAPS_READ_1_1_4 | - SNOR_HWCAPS_PP, - }; struct platform_device *pdev = cqspi->pdev; struct device *dev = &pdev->dev; + const struct cqspi_driver_platdata *ddata; + struct spi_nor_hwcaps hwcaps; struct cqspi_flash_pdata *f_pdata; struct spi_nor *nor; struct mtd_info *mtd; unsigned int cs; int i, ret; + ddata = of_device_get_match_data(dev); + if (!ddata) { + dev_err(dev, "Couldn't find driver data\n"); + return -EINVAL; + } + hwcaps.mask = ddata->hwcaps_mask; + /* Get flash device data */ for_each_available_child_of_node(dev->of_node, np) { ret = of_property_read_u32(np, "reg", &cs); @@ -1310,7 +1336,7 @@ static int cqspi_probe(struct platform_device *pdev) struct cqspi_st *cqspi; struct resource *res; struct resource *res_ahb; - unsigned long data; + const struct cqspi_driver_platdata *ddata; int ret; int irq; @@ -1377,8 +1403,8 @@ static int cqspi_probe(struct platform_device *pdev) } cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk); - data = (unsigned long)of_device_get_match_data(dev); - if (data & CQSPI_NEEDS_WR_DELAY) + ddata = of_device_get_match_data(dev); + if (ddata && (ddata->quirks & CQSPI_NEEDS_WR_DELAY)) cqspi->wr_delay = 5 * DIV_ROUND_UP(NSEC_PER_SEC, cqspi->master_ref_clk_hz); @@ -1460,14 +1486,32 @@ static const struct dev_pm_ops cqspi__dev_pm_ops = { #define CQSPI_DEV_PM_OPS NULL #endif +static const struct cqspi_driver_platdata cdns_qspi = { + .hwcaps_mask = CQSPI_BASE_HWCAPS_MASK, +}; + +static const struct cqspi_driver_platdata k2g_qspi = { + .hwcaps_mask = CQSPI_BASE_HWCAPS_MASK, + .quirks = CQSPI_NEEDS_WR_DELAY, +}; + +static const struct cqspi_driver_platdata am654_ospi = { + .hwcaps_mask = CQSPI_BASE_HWCAPS_MASK | SNOR_HWCAPS_READ_1_1_8, + .quirks = CQSPI_NEEDS_WR_DELAY, +}; + static const struct of_device_id cqspi_dt_ids[] = { { .compatible = "cdns,qspi-nor", - .data = (void *)0, + .data = &cdns_qspi, }, { .compatible = "ti,k2g-qspi", - .data = (void *)CQSPI_NEEDS_WR_DELAY, + .data = &k2g_qspi, + }, + { + .compatible = "ti,am654-ospi", + .data = &am654_ospi, }, { /* end of table */ } }; diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c deleted file mode 100644 index 1ff3430f82c8..000000000000 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ /dev/null @@ -1,1224 +0,0 @@ -/* - * Freescale QuadSPI driver. - * - * Copyright (C) 2013 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/errno.h> -#include <linux/platform_device.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/timer.h> -#include <linux/jiffies.h> -#include <linux/completion.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/spi-nor.h> -#include <linux/mutex.h> -#include <linux/pm_qos.h> -#include <linux/sizes.h> - -/* Controller needs driver to swap endian */ -#define QUADSPI_QUIRK_SWAP_ENDIAN (1 << 0) -/* Controller needs 4x internal clock */ -#define QUADSPI_QUIRK_4X_INT_CLK (1 << 1) -/* - * TKT253890, Controller needs driver to fill txfifo till 16 byte to - * trigger data transfer even though extern data will not transferred. - */ -#define QUADSPI_QUIRK_TKT253890 (1 << 2) -/* Controller cannot wake up from wait mode, TKT245618 */ -#define QUADSPI_QUIRK_TKT245618 (1 << 3) - -/* The registers */ -#define QUADSPI_MCR 0x00 -#define QUADSPI_MCR_RESERVED_SHIFT 16 -#define QUADSPI_MCR_RESERVED_MASK (0xF << QUADSPI_MCR_RESERVED_SHIFT) -#define QUADSPI_MCR_MDIS_SHIFT 14 -#define QUADSPI_MCR_MDIS_MASK (1 << QUADSPI_MCR_MDIS_SHIFT) -#define QUADSPI_MCR_CLR_TXF_SHIFT 11 -#define QUADSPI_MCR_CLR_TXF_MASK (1 << QUADSPI_MCR_CLR_TXF_SHIFT) -#define QUADSPI_MCR_CLR_RXF_SHIFT 10 -#define QUADSPI_MCR_CLR_RXF_MASK (1 << QUADSPI_MCR_CLR_RXF_SHIFT) -#define QUADSPI_MCR_DDR_EN_SHIFT 7 -#define QUADSPI_MCR_DDR_EN_MASK (1 << QUADSPI_MCR_DDR_EN_SHIFT) -#define QUADSPI_MCR_END_CFG_SHIFT 2 -#define QUADSPI_MCR_END_CFG_MASK (3 << QUADSPI_MCR_END_CFG_SHIFT) -#define QUADSPI_MCR_SWRSTHD_SHIFT 1 -#define QUADSPI_MCR_SWRSTHD_MASK (1 << QUADSPI_MCR_SWRSTHD_SHIFT) -#define QUADSPI_MCR_SWRSTSD_SHIFT 0 -#define QUADSPI_MCR_SWRSTSD_MASK (1 << QUADSPI_MCR_SWRSTSD_SHIFT) - -#define QUADSPI_IPCR 0x08 -#define QUADSPI_IPCR_SEQID_SHIFT 24 -#define QUADSPI_IPCR_SEQID_MASK (0xF << QUADSPI_IPCR_SEQID_SHIFT) - -#define QUADSPI_BUF0CR 0x10 -#define QUADSPI_BUF1CR 0x14 -#define QUADSPI_BUF2CR 0x18 -#define QUADSPI_BUFXCR_INVALID_MSTRID 0xe - -#define QUADSPI_BUF3CR 0x1c -#define QUADSPI_BUF3CR_ALLMST_SHIFT 31 -#define QUADSPI_BUF3CR_ALLMST_MASK (1 << QUADSPI_BUF3CR_ALLMST_SHIFT) -#define QUADSPI_BUF3CR_ADATSZ_SHIFT 8 -#define QUADSPI_BUF3CR_ADATSZ_MASK (0xFF << QUADSPI_BUF3CR_ADATSZ_SHIFT) - -#define QUADSPI_BFGENCR 0x20 -#define QUADSPI_BFGENCR_PAR_EN_SHIFT 16 -#define QUADSPI_BFGENCR_PAR_EN_MASK (1 << (QUADSPI_BFGENCR_PAR_EN_SHIFT)) -#define QUADSPI_BFGENCR_SEQID_SHIFT 12 -#define QUADSPI_BFGENCR_SEQID_MASK (0xF << QUADSPI_BFGENCR_SEQID_SHIFT) - -#define QUADSPI_BUF0IND 0x30 -#define QUADSPI_BUF1IND 0x34 -#define QUADSPI_BUF2IND 0x38 -#define QUADSPI_SFAR 0x100 - -#define QUADSPI_SMPR 0x108 -#define QUADSPI_SMPR_DDRSMP_SHIFT 16 -#define QUADSPI_SMPR_DDRSMP_MASK (7 << QUADSPI_SMPR_DDRSMP_SHIFT) -#define QUADSPI_SMPR_FSDLY_SHIFT 6 -#define QUADSPI_SMPR_FSDLY_MASK (1 << QUADSPI_SMPR_FSDLY_SHIFT) -#define QUADSPI_SMPR_FSPHS_SHIFT 5 -#define QUADSPI_SMPR_FSPHS_MASK (1 << QUADSPI_SMPR_FSPHS_SHIFT) -#define QUADSPI_SMPR_HSENA_SHIFT 0 -#define QUADSPI_SMPR_HSENA_MASK (1 << QUADSPI_SMPR_HSENA_SHIFT) - -#define QUADSPI_RBSR 0x10c -#define QUADSPI_RBSR_RDBFL_SHIFT 8 -#define QUADSPI_RBSR_RDBFL_MASK (0x3F << QUADSPI_RBSR_RDBFL_SHIFT) - -#define QUADSPI_RBCT 0x110 -#define QUADSPI_RBCT_WMRK_MASK 0x1F -#define QUADSPI_RBCT_RXBRD_SHIFT 8 -#define QUADSPI_RBCT_RXBRD_USEIPS (0x1 << QUADSPI_RBCT_RXBRD_SHIFT) - -#define QUADSPI_TBSR 0x150 -#define QUADSPI_TBDR 0x154 -#define QUADSPI_SR 0x15c -#define QUADSPI_SR_IP_ACC_SHIFT 1 -#define QUADSPI_SR_IP_ACC_MASK (0x1 << QUADSPI_SR_IP_ACC_SHIFT) -#define QUADSPI_SR_AHB_ACC_SHIFT 2 -#define QUADSPI_SR_AHB_ACC_MASK (0x1 << QUADSPI_SR_AHB_ACC_SHIFT) - -#define QUADSPI_FR 0x160 -#define QUADSPI_FR_TFF_MASK 0x1 - -#define QUADSPI_SFA1AD 0x180 -#define QUADSPI_SFA2AD 0x184 -#define QUADSPI_SFB1AD 0x188 -#define QUADSPI_SFB2AD 0x18c -#define QUADSPI_RBDR 0x200 - -#define QUADSPI_LUTKEY 0x300 -#define QUADSPI_LUTKEY_VALUE 0x5AF05AF0 - -#define QUADSPI_LCKCR 0x304 -#define QUADSPI_LCKER_LOCK 0x1 -#define QUADSPI_LCKER_UNLOCK 0x2 - -#define QUADSPI_RSER 0x164 -#define QUADSPI_RSER_TFIE (0x1 << 0) - -#define QUADSPI_LUT_BASE 0x310 - -/* - * The definition of the LUT register shows below: - * - * --------------------------------------------------- - * | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 | - * --------------------------------------------------- - */ -#define OPRND0_SHIFT 0 -#define PAD0_SHIFT 8 -#define INSTR0_SHIFT 10 -#define OPRND1_SHIFT 16 - -/* Instruction set for the LUT register. */ -#define LUT_STOP 0 -#define LUT_CMD 1 -#define LUT_ADDR 2 -#define LUT_DUMMY 3 -#define LUT_MODE 4 -#define LUT_MODE2 5 -#define LUT_MODE4 6 -#define LUT_FSL_READ 7 -#define LUT_FSL_WRITE 8 -#define LUT_JMP_ON_CS 9 -#define LUT_ADDR_DDR 10 -#define LUT_MODE_DDR 11 -#define LUT_MODE2_DDR 12 -#define LUT_MODE4_DDR 13 -#define LUT_FSL_READ_DDR 14 -#define LUT_FSL_WRITE_DDR 15 -#define LUT_DATA_LEARN 16 - -/* - * The PAD definitions for LUT register. - * - * The pad stands for the lines number of IO[0:3]. - * For example, the Quad read need four IO lines, so you should - * set LUT_PAD4 which means we use four IO lines. - */ -#define LUT_PAD1 0 -#define LUT_PAD2 1 -#define LUT_PAD4 2 - -/* Oprands for the LUT register. */ -#define ADDR24BIT 0x18 -#define ADDR32BIT 0x20 - -/* Macros for constructing the LUT register. */ -#define LUT0(ins, pad, opr) \ - (((opr) << OPRND0_SHIFT) | ((LUT_##pad) << PAD0_SHIFT) | \ - ((LUT_##ins) << INSTR0_SHIFT)) - -#define LUT1(ins, pad, opr) (LUT0(ins, pad, opr) << OPRND1_SHIFT) - -/* other macros for LUT register. */ -#define QUADSPI_LUT(x) (QUADSPI_LUT_BASE + (x) * 4) -#define QUADSPI_LUT_NUM 64 - -/* SEQID -- we can have 16 seqids at most. */ -#define SEQID_READ 0 -#define SEQID_WREN 1 -#define SEQID_WRDI 2 -#define SEQID_RDSR 3 -#define SEQID_SE 4 -#define SEQID_CHIP_ERASE 5 -#define SEQID_PP 6 -#define SEQID_RDID 7 -#define SEQID_WRSR 8 -#define SEQID_RDCR 9 -#define SEQID_EN4B 10 -#define SEQID_BRWR 11 - -#define QUADSPI_MIN_IOMAP SZ_4M - -enum fsl_qspi_devtype { - FSL_QUADSPI_VYBRID, - FSL_QUADSPI_IMX6SX, - FSL_QUADSPI_IMX7D, - FSL_QUADSPI_IMX6UL, - FSL_QUADSPI_LS1021A, - FSL_QUADSPI_LS2080A, -}; - -struct fsl_qspi_devtype_data { - enum fsl_qspi_devtype devtype; - int rxfifo; - int txfifo; - int ahb_buf_size; - int driver_data; -}; - -static const struct fsl_qspi_devtype_data vybrid_data = { - .devtype = FSL_QUADSPI_VYBRID, - .rxfifo = 128, - .txfifo = 64, - .ahb_buf_size = 1024, - .driver_data = QUADSPI_QUIRK_SWAP_ENDIAN, -}; - -static const struct fsl_qspi_devtype_data imx6sx_data = { - .devtype = FSL_QUADSPI_IMX6SX, - .rxfifo = 128, - .txfifo = 512, - .ahb_buf_size = 1024, - .driver_data = QUADSPI_QUIRK_4X_INT_CLK - | QUADSPI_QUIRK_TKT245618, -}; - -static const struct fsl_qspi_devtype_data imx7d_data = { - .devtype = FSL_QUADSPI_IMX7D, - .rxfifo = 512, - .txfifo = 512, - .ahb_buf_size = 1024, - .driver_data = QUADSPI_QUIRK_TKT253890 - | QUADSPI_QUIRK_4X_INT_CLK, -}; - -static const struct fsl_qspi_devtype_data imx6ul_data = { - .devtype = FSL_QUADSPI_IMX6UL, - .rxfifo = 128, - .txfifo = 512, - .ahb_buf_size = 1024, - .driver_data = QUADSPI_QUIRK_TKT253890 - | QUADSPI_QUIRK_4X_INT_CLK, -}; - -static struct fsl_qspi_devtype_data ls1021a_data = { - .devtype = FSL_QUADSPI_LS1021A, - .rxfifo = 128, - .txfifo = 64, - .ahb_buf_size = 1024, - .driver_data = 0, -}; - -static const struct fsl_qspi_devtype_data ls2080a_data = { - .devtype = FSL_QUADSPI_LS2080A, - .rxfifo = 128, - .txfifo = 64, - .ahb_buf_size = 1024, - .driver_data = QUADSPI_QUIRK_TKT253890, -}; - - -#define FSL_QSPI_MAX_CHIP 4 -struct fsl_qspi { - struct spi_nor nor[FSL_QSPI_MAX_CHIP]; - void __iomem *iobase; - void __iomem *ahb_addr; - u32 memmap_phy; - u32 memmap_offs; - u32 memmap_len; - struct clk *clk, *clk_en; - struct device *dev; - struct completion c; - const struct fsl_qspi_devtype_data *devtype_data; - u32 nor_size; - u32 nor_num; - u32 clk_rate; - unsigned int chip_base_addr; /* We may support two chips. */ - bool has_second_chip; - bool big_endian; - struct mutex lock; - struct pm_qos_request pm_qos_req; -}; - -static inline int needs_swap_endian(struct fsl_qspi *q) -{ - return q->devtype_data->driver_data & QUADSPI_QUIRK_SWAP_ENDIAN; -} - -static inline int needs_4x_clock(struct fsl_qspi *q) -{ - return q->devtype_data->driver_data & QUADSPI_QUIRK_4X_INT_CLK; -} - -static inline int needs_fill_txfifo(struct fsl_qspi *q) -{ - return q->devtype_data->driver_data & QUADSPI_QUIRK_TKT253890; -} - -static inline int needs_wakeup_wait_mode(struct fsl_qspi *q) -{ - return q->devtype_data->driver_data & QUADSPI_QUIRK_TKT245618; -} - -/* - * R/W functions for big- or little-endian registers: - * The qSPI controller's endian is independent of the CPU core's endian. - * So far, although the CPU core is little-endian but the qSPI have two - * versions for big-endian and little-endian. - */ -static void qspi_writel(struct fsl_qspi *q, u32 val, void __iomem *addr) -{ - if (q->big_endian) - iowrite32be(val, addr); - else - iowrite32(val, addr); -} - -static u32 qspi_readl(struct fsl_qspi *q, void __iomem *addr) -{ - if (q->big_endian) - return ioread32be(addr); - else - return ioread32(addr); -} - -/* - * An IC bug makes us to re-arrange the 32-bit data. - * The following chips, such as IMX6SLX, have fixed this bug. - */ -static inline u32 fsl_qspi_endian_xchg(struct fsl_qspi *q, u32 a) -{ - return needs_swap_endian(q) ? __swab32(a) : a; -} - -static inline void fsl_qspi_unlock_lut(struct fsl_qspi *q) -{ - qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); - qspi_writel(q, QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR); -} - -static inline void fsl_qspi_lock_lut(struct fsl_qspi *q) -{ - qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); - qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR); -} - -static irqreturn_t fsl_qspi_irq_handler(int irq, void *dev_id) -{ - struct fsl_qspi *q = dev_id; - u32 reg; - - /* clear interrupt */ - reg = qspi_readl(q, q->iobase + QUADSPI_FR); - qspi_writel(q, reg, q->iobase + QUADSPI_FR); - - if (reg & QUADSPI_FR_TFF_MASK) - complete(&q->c); - - dev_dbg(q->dev, "QUADSPI_FR : 0x%.8x:0x%.8x\n", q->chip_base_addr, reg); - return IRQ_HANDLED; -} - -static void fsl_qspi_init_lut(struct fsl_qspi *q) -{ - void __iomem *base = q->iobase; - int rxfifo = q->devtype_data->rxfifo; - u32 lut_base; - int i; - - struct spi_nor *nor = &q->nor[0]; - u8 addrlen = (nor->addr_width == 3) ? ADDR24BIT : ADDR32BIT; - u8 read_op = nor->read_opcode; - u8 read_dm = nor->read_dummy; - - fsl_qspi_unlock_lut(q); - - /* Clear all the LUT table */ - for (i = 0; i < QUADSPI_LUT_NUM; i++) - qspi_writel(q, 0, base + QUADSPI_LUT_BASE + i * 4); - - /* Read */ - lut_base = SEQID_READ * 4; - - qspi_writel(q, LUT0(CMD, PAD1, read_op) | LUT1(ADDR, PAD1, addrlen), - base + QUADSPI_LUT(lut_base)); - qspi_writel(q, LUT0(DUMMY, PAD1, read_dm) | - LUT1(FSL_READ, PAD4, rxfifo), - base + QUADSPI_LUT(lut_base + 1)); - - /* Write enable */ - lut_base = SEQID_WREN * 4; - qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WREN), - base + QUADSPI_LUT(lut_base)); - - /* Page Program */ - lut_base = SEQID_PP * 4; - - qspi_writel(q, LUT0(CMD, PAD1, nor->program_opcode) | - LUT1(ADDR, PAD1, addrlen), - base + QUADSPI_LUT(lut_base)); - qspi_writel(q, LUT0(FSL_WRITE, PAD1, 0), - base + QUADSPI_LUT(lut_base + 1)); - - /* Read Status */ - lut_base = SEQID_RDSR * 4; - qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDSR) | - LUT1(FSL_READ, PAD1, 0x1), - base + QUADSPI_LUT(lut_base)); - - /* Erase a sector */ - lut_base = SEQID_SE * 4; - - qspi_writel(q, LUT0(CMD, PAD1, nor->erase_opcode) | - LUT1(ADDR, PAD1, addrlen), - base + QUADSPI_LUT(lut_base)); - - /* Erase the whole chip */ - lut_base = SEQID_CHIP_ERASE * 4; - qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_CHIP_ERASE), - base + QUADSPI_LUT(lut_base)); - - /* READ ID */ - lut_base = SEQID_RDID * 4; - qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDID) | - LUT1(FSL_READ, PAD1, 0x8), - base + QUADSPI_LUT(lut_base)); - - /* Write Register */ - lut_base = SEQID_WRSR * 4; - qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WRSR) | - LUT1(FSL_WRITE, PAD1, 0x2), - base + QUADSPI_LUT(lut_base)); - - /* Read Configuration Register */ - lut_base = SEQID_RDCR * 4; - qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDCR) | - LUT1(FSL_READ, PAD1, 0x1), - base + QUADSPI_LUT(lut_base)); - - /* Write disable */ - lut_base = SEQID_WRDI * 4; - qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WRDI), - base + QUADSPI_LUT(lut_base)); - - /* Enter 4 Byte Mode (Micron) */ - lut_base = SEQID_EN4B * 4; - qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_EN4B), - base + QUADSPI_LUT(lut_base)); - - /* Enter 4 Byte Mode (Spansion) */ - lut_base = SEQID_BRWR * 4; - qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_BRWR), - base + QUADSPI_LUT(lut_base)); - - fsl_qspi_lock_lut(q); -} - -/* Get the SEQID for the command */ -static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd) -{ - switch (cmd) { - case SPINOR_OP_READ_1_1_4: - case SPINOR_OP_READ_1_1_4_4B: - return SEQID_READ; - case SPINOR_OP_WREN: - return SEQID_WREN; - case SPINOR_OP_WRDI: - return SEQID_WRDI; - case SPINOR_OP_RDSR: - return SEQID_RDSR; - case SPINOR_OP_SE: - return SEQID_SE; - case SPINOR_OP_CHIP_ERASE: - return SEQID_CHIP_ERASE; - case SPINOR_OP_PP: - return SEQID_PP; - case SPINOR_OP_RDID: - return SEQID_RDID; - case SPINOR_OP_WRSR: - return SEQID_WRSR; - case SPINOR_OP_RDCR: - return SEQID_RDCR; - case SPINOR_OP_EN4B: - return SEQID_EN4B; - case SPINOR_OP_BRWR: - return SEQID_BRWR; - default: - if (cmd == q->nor[0].erase_opcode) - return SEQID_SE; - dev_err(q->dev, "Unsupported cmd 0x%.2x\n", cmd); - break; - } - return -EINVAL; -} - -static int -fsl_qspi_runcmd(struct fsl_qspi *q, u8 cmd, unsigned int addr, int len) -{ - void __iomem *base = q->iobase; - int seqid; - u32 reg, reg2; - int err; - - init_completion(&q->c); - dev_dbg(q->dev, "to 0x%.8x:0x%.8x, len:%d, cmd:%.2x\n", - q->chip_base_addr, addr, len, cmd); - - /* save the reg */ - reg = qspi_readl(q, base + QUADSPI_MCR); - - qspi_writel(q, q->memmap_phy + q->chip_base_addr + addr, - base + QUADSPI_SFAR); - qspi_writel(q, QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS, - base + QUADSPI_RBCT); - qspi_writel(q, reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR); - - do { - reg2 = qspi_readl(q, base + QUADSPI_SR); - if (reg2 & (QUADSPI_SR_IP_ACC_MASK | QUADSPI_SR_AHB_ACC_MASK)) { - udelay(1); - dev_dbg(q->dev, "The controller is busy, 0x%x\n", reg2); - continue; - } - break; - } while (1); - - /* trigger the LUT now */ - seqid = fsl_qspi_get_seqid(q, cmd); - if (seqid < 0) - return seqid; - - qspi_writel(q, (seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, - base + QUADSPI_IPCR); - - /* Wait for the interrupt. */ - if (!wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000))) { - dev_err(q->dev, - "cmd 0x%.2x timeout, addr@%.8x, FR:0x%.8x, SR:0x%.8x\n", - cmd, addr, qspi_readl(q, base + QUADSPI_FR), - qspi_readl(q, base + QUADSPI_SR)); - err = -ETIMEDOUT; - } else { - err = 0; - } - - /* restore the MCR */ - qspi_writel(q, reg, base + QUADSPI_MCR); - - return err; -} - -/* Read out the data from the QUADSPI_RBDR buffer registers. */ -static void fsl_qspi_read_data(struct fsl_qspi *q, int len, u8 *rxbuf) -{ - u32 tmp; - int i = 0; - - while (len > 0) { - tmp = qspi_readl(q, q->iobase + QUADSPI_RBDR + i * 4); - tmp = fsl_qspi_endian_xchg(q, tmp); - dev_dbg(q->dev, "chip addr:0x%.8x, rcv:0x%.8x\n", - q->chip_base_addr, tmp); - - if (len >= 4) { - *((u32 *)rxbuf) = tmp; - rxbuf += 4; - } else { - memcpy(rxbuf, &tmp, len); - break; - } - - len -= 4; - i++; - } -} - -/* - * If we have changed the content of the flash by writing or erasing, - * we need to invalidate the AHB buffer. If we do not do so, we may read out - * the wrong data. The spec tells us reset the AHB domain and Serial Flash - * domain at the same time. - */ -static inline void fsl_qspi_invalid(struct fsl_qspi *q) -{ - u32 reg; - - reg = qspi_readl(q, q->iobase + QUADSPI_MCR); - reg |= QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK; - qspi_writel(q, reg, q->iobase + QUADSPI_MCR); - - /* - * The minimum delay : 1 AHB + 2 SFCK clocks. - * Delay 1 us is enough. - */ - udelay(1); - - reg &= ~(QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK); - qspi_writel(q, reg, q->iobase + QUADSPI_MCR); -} - -static ssize_t fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor, - u8 opcode, unsigned int to, u32 *txbuf, - unsigned count) -{ - int ret, i, j; - u32 tmp; - - dev_dbg(q->dev, "to 0x%.8x:0x%.8x, len : %d\n", - q->chip_base_addr, to, count); - - /* clear the TX FIFO. */ - tmp = qspi_readl(q, q->iobase + QUADSPI_MCR); - qspi_writel(q, tmp | QUADSPI_MCR_CLR_TXF_MASK, q->iobase + QUADSPI_MCR); - - /* fill the TX data to the FIFO */ - for (j = 0, i = ((count + 3) / 4); j < i; j++) { - tmp = fsl_qspi_endian_xchg(q, *txbuf); - qspi_writel(q, tmp, q->iobase + QUADSPI_TBDR); - txbuf++; - } - - /* fill the TXFIFO upto 16 bytes for i.MX7d */ - if (needs_fill_txfifo(q)) - for (; i < 4; i++) - qspi_writel(q, tmp, q->iobase + QUADSPI_TBDR); - - /* Trigger it */ - ret = fsl_qspi_runcmd(q, opcode, to, count); - - if (ret == 0) - return count; - - return ret; -} - -static void fsl_qspi_set_map_addr(struct fsl_qspi *q) -{ - int nor_size = q->nor_size; - void __iomem *base = q->iobase; - - qspi_writel(q, nor_size + q->memmap_phy, base + QUADSPI_SFA1AD); - qspi_writel(q, nor_size * 2 + q->memmap_phy, base + QUADSPI_SFA2AD); - qspi_writel(q, nor_size * 3 + q->memmap_phy, base + QUADSPI_SFB1AD); - qspi_writel(q, nor_size * 4 + q->memmap_phy, base + QUADSPI_SFB2AD); -} - -/* - * There are two different ways to read out the data from the flash: - * the "IP Command Read" and the "AHB Command Read". - * - * The IC guy suggests we use the "AHB Command Read" which is faster - * then the "IP Command Read". (What's more is that there is a bug in - * the "IP Command Read" in the Vybrid.) - * - * After we set up the registers for the "AHB Command Read", we can use - * the memcpy to read the data directly. A "missed" access to the buffer - * causes the controller to clear the buffer, and use the sequence pointed - * by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash. - */ -static int fsl_qspi_init_ahb_read(struct fsl_qspi *q) -{ - void __iomem *base = q->iobase; - int seqid; - - /* AHB configuration for access buffer 0/1/2 .*/ - qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR); - qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR); - qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR); - /* - * Set ADATSZ with the maximum AHB buffer size to improve the - * read performance. - */ - qspi_writel(q, QUADSPI_BUF3CR_ALLMST_MASK | - ((q->devtype_data->ahb_buf_size / 8) - << QUADSPI_BUF3CR_ADATSZ_SHIFT), - base + QUADSPI_BUF3CR); - - /* We only use the buffer3 */ - qspi_writel(q, 0, base + QUADSPI_BUF0IND); - qspi_writel(q, 0, base + QUADSPI_BUF1IND); - qspi_writel(q, 0, base + QUADSPI_BUF2IND); - - /* Set the default lut sequence for AHB Read. */ - seqid = fsl_qspi_get_seqid(q, q->nor[0].read_opcode); - if (seqid < 0) - return seqid; - - qspi_writel(q, seqid << QUADSPI_BFGENCR_SEQID_SHIFT, - q->iobase + QUADSPI_BFGENCR); - - return 0; -} - -/* This function was used to prepare and enable QSPI clock */ -static int fsl_qspi_clk_prep_enable(struct fsl_qspi *q) -{ - int ret; - - ret = clk_prepare_enable(q->clk_en); - if (ret) - return ret; - - ret = clk_prepare_enable(q->clk); - if (ret) { - clk_disable_unprepare(q->clk_en); - return ret; - } - - if (needs_wakeup_wait_mode(q)) - pm_qos_add_request(&q->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, 0); - - return 0; -} - -/* This function was used to disable and unprepare QSPI clock */ -static void fsl_qspi_clk_disable_unprep(struct fsl_qspi *q) -{ - if (needs_wakeup_wait_mode(q)) - pm_qos_remove_request(&q->pm_qos_req); - - clk_disable_unprepare(q->clk); - clk_disable_unprepare(q->clk_en); - -} - -/* We use this function to do some basic init for spi_nor_scan(). */ -static int fsl_qspi_nor_setup(struct fsl_qspi *q) -{ - void __iomem *base = q->iobase; - u32 reg; - int ret; - - /* disable and unprepare clock to avoid glitch pass to controller */ - fsl_qspi_clk_disable_unprep(q); - - /* the default frequency, we will change it in the future. */ - ret = clk_set_rate(q->clk, 66000000); - if (ret) - return ret; - - ret = fsl_qspi_clk_prep_enable(q); - if (ret) - return ret; - - /* Reset the module */ - qspi_writel(q, QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK, - base + QUADSPI_MCR); - udelay(1); - - /* Init the LUT table. */ - fsl_qspi_init_lut(q); - - /* Disable the module */ - qspi_writel(q, QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK, - base + QUADSPI_MCR); - - reg = qspi_readl(q, base + QUADSPI_SMPR); - qspi_writel(q, reg & ~(QUADSPI_SMPR_FSDLY_MASK - | QUADSPI_SMPR_FSPHS_MASK - | QUADSPI_SMPR_HSENA_MASK - | QUADSPI_SMPR_DDRSMP_MASK), base + QUADSPI_SMPR); - - /* Enable the module */ - qspi_writel(q, QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK, - base + QUADSPI_MCR); - - /* clear all interrupt status */ - qspi_writel(q, 0xffffffff, q->iobase + QUADSPI_FR); - - /* enable the interrupt */ - qspi_writel(q, QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER); - - return 0; -} - -static int fsl_qspi_nor_setup_last(struct fsl_qspi *q) -{ - unsigned long rate = q->clk_rate; - int ret; - - if (needs_4x_clock(q)) - rate *= 4; - - /* disable and unprepare clock to avoid glitch pass to controller */ - fsl_qspi_clk_disable_unprep(q); - - ret = clk_set_rate(q->clk, rate); - if (ret) - return ret; - - ret = fsl_qspi_clk_prep_enable(q); - if (ret) - return ret; - - /* Init the LUT table again. */ - fsl_qspi_init_lut(q); - - /* Init for AHB read */ - return fsl_qspi_init_ahb_read(q); -} - -static const struct of_device_id fsl_qspi_dt_ids[] = { - { .compatible = "fsl,vf610-qspi", .data = &vybrid_data, }, - { .compatible = "fsl,imx6sx-qspi", .data = &imx6sx_data, }, - { .compatible = "fsl,imx7d-qspi", .data = &imx7d_data, }, - { .compatible = "fsl,imx6ul-qspi", .data = &imx6ul_data, }, - { .compatible = "fsl,ls1021a-qspi", .data = (void *)&ls1021a_data, }, - { .compatible = "fsl,ls2080a-qspi", .data = &ls2080a_data, }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids); - -static void fsl_qspi_set_base_addr(struct fsl_qspi *q, struct spi_nor *nor) -{ - q->chip_base_addr = q->nor_size * (nor - q->nor); -} - -static int fsl_qspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) -{ - int ret; - struct fsl_qspi *q = nor->priv; - - ret = fsl_qspi_runcmd(q, opcode, 0, len); - if (ret) - return ret; - - fsl_qspi_read_data(q, len, buf); - return 0; -} - -static int fsl_qspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) -{ - struct fsl_qspi *q = nor->priv; - int ret; - - if (!buf) { - ret = fsl_qspi_runcmd(q, opcode, 0, 1); - if (ret) - return ret; - - if (opcode == SPINOR_OP_CHIP_ERASE) - fsl_qspi_invalid(q); - - } else if (len > 0) { - ret = fsl_qspi_nor_write(q, nor, opcode, 0, - (u32 *)buf, len); - if (ret > 0) - return 0; - } else { - dev_err(q->dev, "invalid cmd %d\n", opcode); - ret = -EINVAL; - } - - return ret; -} - -static ssize_t fsl_qspi_write(struct spi_nor *nor, loff_t to, - size_t len, const u_char *buf) -{ - struct fsl_qspi *q = nor->priv; - ssize_t ret = fsl_qspi_nor_write(q, nor, nor->program_opcode, to, - (u32 *)buf, len); - - /* invalid the data in the AHB buffer. */ - fsl_qspi_invalid(q); - return ret; -} - -static ssize_t fsl_qspi_read(struct spi_nor *nor, loff_t from, - size_t len, u_char *buf) -{ - struct fsl_qspi *q = nor->priv; - u8 cmd = nor->read_opcode; - - /* if necessary,ioremap buffer before AHB read, */ - if (!q->ahb_addr) { - q->memmap_offs = q->chip_base_addr + from; - q->memmap_len = len > QUADSPI_MIN_IOMAP ? len : QUADSPI_MIN_IOMAP; - - q->ahb_addr = ioremap_nocache( - q->memmap_phy + q->memmap_offs, - q->memmap_len); - if (!q->ahb_addr) { - dev_err(q->dev, "ioremap failed\n"); - return -ENOMEM; - } - /* ioremap if the data requested is out of range */ - } else if (q->chip_base_addr + from < q->memmap_offs - || q->chip_base_addr + from + len > - q->memmap_offs + q->memmap_len) { - iounmap(q->ahb_addr); - - q->memmap_offs = q->chip_base_addr + from; - q->memmap_len = len > QUADSPI_MIN_IOMAP ? len : QUADSPI_MIN_IOMAP; - q->ahb_addr = ioremap_nocache( - q->memmap_phy + q->memmap_offs, - q->memmap_len); - if (!q->ahb_addr) { - dev_err(q->dev, "ioremap failed\n"); - return -ENOMEM; - } - } - - dev_dbg(q->dev, "cmd [%x],read from %p, len:%zd\n", - cmd, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs, - len); - - /* Read out the data directly from the AHB buffer.*/ - memcpy(buf, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs, - len); - - return len; -} - -static int fsl_qspi_erase(struct spi_nor *nor, loff_t offs) -{ - struct fsl_qspi *q = nor->priv; - int ret; - - dev_dbg(nor->dev, "%dKiB at 0x%08x:0x%08x\n", - nor->mtd.erasesize / 1024, q->chip_base_addr, (u32)offs); - - ret = fsl_qspi_runcmd(q, nor->erase_opcode, offs, 0); - if (ret) - return ret; - - fsl_qspi_invalid(q); - return 0; -} - -static int fsl_qspi_prep(struct spi_nor *nor, enum spi_nor_ops ops) -{ - struct fsl_qspi *q = nor->priv; - int ret; - - mutex_lock(&q->lock); - - ret = fsl_qspi_clk_prep_enable(q); - if (ret) - goto err_mutex; - - fsl_qspi_set_base_addr(q, nor); - return 0; - -err_mutex: - mutex_unlock(&q->lock); - return ret; -} - -static void fsl_qspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops) -{ - struct fsl_qspi *q = nor->priv; - - fsl_qspi_clk_disable_unprep(q); - mutex_unlock(&q->lock); -} - -static int fsl_qspi_probe(struct platform_device *pdev) -{ - const struct spi_nor_hwcaps hwcaps = { - .mask = SNOR_HWCAPS_READ_1_1_4 | - SNOR_HWCAPS_PP, - }; - struct device_node *np = pdev->dev.of_node; - struct device *dev = &pdev->dev; - struct fsl_qspi *q; - struct resource *res; - struct spi_nor *nor; - struct mtd_info *mtd; - int ret, i = 0; - - q = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL); - if (!q) - return -ENOMEM; - - q->nor_num = of_get_child_count(dev->of_node); - if (!q->nor_num || q->nor_num > FSL_QSPI_MAX_CHIP) - return -ENODEV; - - q->dev = dev; - q->devtype_data = of_device_get_match_data(dev); - if (!q->devtype_data) - return -ENODEV; - platform_set_drvdata(pdev, q); - - /* find the resources */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI"); - q->iobase = devm_ioremap_resource(dev, res); - if (IS_ERR(q->iobase)) - return PTR_ERR(q->iobase); - - q->big_endian = of_property_read_bool(np, "big-endian"); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "QuadSPI-memory"); - if (!devm_request_mem_region(dev, res->start, resource_size(res), - res->name)) { - dev_err(dev, "can't request region for resource %pR\n", res); - return -EBUSY; - } - - q->memmap_phy = res->start; - - /* find the clocks */ - q->clk_en = devm_clk_get(dev, "qspi_en"); - if (IS_ERR(q->clk_en)) - return PTR_ERR(q->clk_en); - - q->clk = devm_clk_get(dev, "qspi"); - if (IS_ERR(q->clk)) - return PTR_ERR(q->clk); - - ret = fsl_qspi_clk_prep_enable(q); - if (ret) { - dev_err(dev, "can not enable the clock\n"); - goto clk_failed; - } - - /* find the irq */ - ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "failed to get the irq: %d\n", ret); - goto irq_failed; - } - - ret = devm_request_irq(dev, ret, - fsl_qspi_irq_handler, 0, pdev->name, q); - if (ret) { - dev_err(dev, "failed to request irq: %d\n", ret); - goto irq_failed; - } - - ret = fsl_qspi_nor_setup(q); - if (ret) - goto irq_failed; - - if (of_get_property(np, "fsl,qspi-has-second-chip", NULL)) - q->has_second_chip = true; - - mutex_init(&q->lock); - - /* iterate the subnodes. */ - for_each_available_child_of_node(dev->of_node, np) { - /* skip the holes */ - if (!q->has_second_chip) - i *= 2; - - nor = &q->nor[i]; - mtd = &nor->mtd; - - nor->dev = dev; - spi_nor_set_flash_node(nor, np); - nor->priv = q; - - if (q->nor_num > 1 && !mtd->name) { - int spiflash_idx; - - ret = of_property_read_u32(np, "reg", &spiflash_idx); - if (!ret) { - mtd->name = devm_kasprintf(dev, GFP_KERNEL, - "%s-%d", - dev_name(dev), - spiflash_idx); - if (!mtd->name) { - ret = -ENOMEM; - goto mutex_failed; - } - } else { - dev_warn(dev, "reg property is missing\n"); - } - } - - /* fill the hooks */ - nor->read_reg = fsl_qspi_read_reg; - nor->write_reg = fsl_qspi_write_reg; - nor->read = fsl_qspi_read; - nor->write = fsl_qspi_write; - nor->erase = fsl_qspi_erase; - - nor->prepare = fsl_qspi_prep; - nor->unprepare = fsl_qspi_unprep; - - ret = of_property_read_u32(np, "spi-max-frequency", - &q->clk_rate); - if (ret < 0) - goto mutex_failed; - - /* set the chip address for READID */ - fsl_qspi_set_base_addr(q, nor); - - ret = spi_nor_scan(nor, NULL, &hwcaps); - if (ret) - goto mutex_failed; - - ret = mtd_device_register(mtd, NULL, 0); - if (ret) - goto mutex_failed; - - /* Set the correct NOR size now. */ - if (q->nor_size == 0) { - q->nor_size = mtd->size; - - /* Map the SPI NOR to accessiable address */ - fsl_qspi_set_map_addr(q); - } - - /* - * The TX FIFO is 64 bytes in the Vybrid, but the Page Program - * may writes 265 bytes per time. The write is working in the - * unit of the TX FIFO, not in the unit of the SPI NOR's page - * size. - * - * So shrink the spi_nor->page_size if it is larger then the - * TX FIFO. - */ - if (nor->page_size > q->devtype_data->txfifo) - nor->page_size = q->devtype_data->txfifo; - - i++; - } - - /* finish the rest init. */ - ret = fsl_qspi_nor_setup_last(q); - if (ret) - goto last_init_failed; - - fsl_qspi_clk_disable_unprep(q); - return 0; - -last_init_failed: - for (i = 0; i < q->nor_num; i++) { - /* skip the holes */ - if (!q->has_second_chip) - i *= 2; - mtd_device_unregister(&q->nor[i].mtd); - } -mutex_failed: - mutex_destroy(&q->lock); -irq_failed: - fsl_qspi_clk_disable_unprep(q); -clk_failed: - dev_err(dev, "Freescale QuadSPI probe failed\n"); - return ret; -} - -static int fsl_qspi_remove(struct platform_device *pdev) -{ - struct fsl_qspi *q = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < q->nor_num; i++) { - /* skip the holes */ - if (!q->has_second_chip) - i *= 2; - mtd_device_unregister(&q->nor[i].mtd); - } - - /* disable the hardware */ - qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); - qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER); - - mutex_destroy(&q->lock); - - if (q->ahb_addr) - iounmap(q->ahb_addr); - - return 0; -} - -static int fsl_qspi_suspend(struct platform_device *pdev, pm_message_t state) -{ - return 0; -} - -static int fsl_qspi_resume(struct platform_device *pdev) -{ - int ret; - struct fsl_qspi *q = platform_get_drvdata(pdev); - - ret = fsl_qspi_clk_prep_enable(q); - if (ret) - return ret; - - fsl_qspi_nor_setup(q); - fsl_qspi_set_map_addr(q); - fsl_qspi_nor_setup_last(q); - - fsl_qspi_clk_disable_unprep(q); - - return 0; -} - -static struct platform_driver fsl_qspi_driver = { - .driver = { - .name = "fsl-quadspi", - .of_match_table = fsl_qspi_dt_ids, - }, - .probe = fsl_qspi_probe, - .remove = fsl_qspi_remove, - .suspend = fsl_qspi_suspend, - .resume = fsl_qspi_resume, -}; -module_platform_driver(fsl_qspi_driver); - -MODULE_DESCRIPTION("Freescale QuadSPI Controller Driver"); -MODULE_AUTHOR("Freescale Semiconductor Inc."); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c index 5442993b71ff..d9eed6844ba1 100644 --- a/drivers/mtd/spi-nor/mtk-quadspi.c +++ b/drivers/mtd/spi-nor/mtk-quadspi.c @@ -431,7 +431,8 @@ static int mtk_nor_init(struct mtk_nor *mtk_nor, struct device_node *flash_node) { const struct spi_nor_hwcaps hwcaps = { - .mask = SNOR_HWCAPS_READ_FAST | + .mask = SNOR_HWCAPS_READ | + SNOR_HWCAPS_READ_FAST | SNOR_HWCAPS_READ_1_1_2 | SNOR_HWCAPS_PP, }; diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 6e13bbd1aaa5..fae147452aff 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -68,7 +68,7 @@ enum spi_nor_read_command_index { SNOR_CMD_READ_4_4_4, SNOR_CMD_READ_1_4_4_DTR, - /* Octo SPI */ + /* Octal SPI */ SNOR_CMD_READ_1_1_8, SNOR_CMD_READ_1_8_8, SNOR_CMD_READ_8_8_8, @@ -85,7 +85,7 @@ enum spi_nor_pp_command_index { SNOR_CMD_PP_1_4_4, SNOR_CMD_PP_4_4_4, - /* Octo SPI */ + /* Octal SPI */ SNOR_CMD_PP_1_1_8, SNOR_CMD_PP_1_8_8, SNOR_CMD_PP_8_8_8, @@ -278,6 +278,7 @@ struct flash_info { #define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ #define USE_CLSR BIT(14) /* use CLSR command */ +#define SPI_NOR_OCTAL_READ BIT(15) /* Flash supports Octal Read */ /* Part specific fixup hooks. */ const struct spi_nor_fixups *fixups; @@ -398,6 +399,8 @@ static u8 spi_nor_convert_3to4_read(u8 opcode) { SPINOR_OP_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B }, { SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B }, { SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B }, + { SPINOR_OP_READ_1_1_8, SPINOR_OP_READ_1_1_8_4B }, + { SPINOR_OP_READ_1_8_8, SPINOR_OP_READ_1_8_8_4B }, { SPINOR_OP_READ_1_1_1_DTR, SPINOR_OP_READ_1_1_1_DTR_4B }, { SPINOR_OP_READ_1_2_2_DTR, SPINOR_OP_READ_1_2_2_DTR_4B }, @@ -414,6 +417,8 @@ static u8 spi_nor_convert_3to4_program(u8 opcode) { SPINOR_OP_PP, SPINOR_OP_PP_4B }, { SPINOR_OP_PP_1_1_4, SPINOR_OP_PP_1_1_4_4B }, { SPINOR_OP_PP_1_4_4, SPINOR_OP_PP_1_4_4_4B }, + { SPINOR_OP_PP_1_1_8, SPINOR_OP_PP_1_1_8_4B }, + { SPINOR_OP_PP_1_8_8, SPINOR_OP_PP_1_8_8_4B }, }; return spi_nor_convert_opcode(opcode, spi_nor_3to4_program, @@ -1740,7 +1745,11 @@ static const struct flash_info spi_nor_ids[] = { { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, + { "en25q80a", INFO(0x1c3014, 0, 64 * 1024, 16, + SECT_4K | SPI_NOR_DUAL_READ) }, { "en25qh32", INFO(0x1c7016, 0, 64 * 1024, 64, 0) }, + { "en25qh64", INFO(0x1c7017, 0, 64 * 1024, 128, + SECT_4K | SPI_NOR_DUAL_READ) }, { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, @@ -1836,6 +1845,8 @@ static const struct flash_info spi_nor_ids[] = { { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) }, { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) }, + { "mx25u3235f", INFO(0xc22536, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mx25u4035", INFO(0xc22533, 0, 64 * 1024, 8, SECT_4K) }, { "mx25u8035", INFO(0xc22534, 0, 64 * 1024, 16, SECT_4K) }, { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, @@ -1847,6 +1858,8 @@ static const struct flash_info spi_nor_ids[] = { SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) .fixups = &mx25l25635_fixups }, { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, + { "mx25v8035f", INFO(0xc22314, 0, 64 * 1024, 16, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, @@ -1872,7 +1885,8 @@ static const struct flash_info spi_nor_ids[] = { /* Micron */ { "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512, - SECT_4K | USE_FSR | SPI_NOR_4B_OPCODES) + SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ | + SPI_NOR_4B_OPCODES) }, /* PMC */ @@ -1885,13 +1899,17 @@ static const struct flash_info spi_nor_ids[] = { */ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "s25fl128s0", INFO6(0x012018, 0x4d0080, 256 * 1024, 64, + SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { "s25fl128s1", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, + SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) }, { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, - { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { "s25fl512s", INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, - { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, @@ -3591,6 +3609,13 @@ static int spi_nor_init_params(struct spi_nor *nor, SNOR_PROTO_1_1_4); } + if (info->flags & SPI_NOR_OCTAL_READ) { + params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8; + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_8], + 0, 8, SPINOR_OP_READ_1_1_8, + SNOR_PROTO_1_1_8); + } + /* Page Program settings. */ params->hwcaps.mask |= SNOR_HWCAPS_PP; spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP], diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 6371958dd170..21bf8ac78380 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -197,9 +197,9 @@ config VXLAN config GENEVE tristate "Generic Network Virtualization Encapsulation" - depends on INET && NET_UDP_TUNNEL + depends on INET depends on IPV6 || !IPV6 - select NET_IP_TUNNEL + select NET_UDP_TUNNEL select GRO_CELLS ---help--- This allows one to create geneve virtual interfaces that provide @@ -519,7 +519,7 @@ config NET_FAILOVER and destroy a failover master netdev and manages a primary and standby slave netdevs that get registered via the generic failover infrastructure. This can be used by paravirtual drivers to enable - an alternate low latency datapath. It alsoenables live migration of + an alternate low latency datapath. It also enables live migration of a VM with direct attached VF by failing over to the paravirtual datapath when the VF is unplugged. diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index a9d597f28023..537c90c8eb0a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1183,29 +1183,22 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) } } - /* Link-local multicast packets should be passed to the - * stack on the link they arrive as well as pass them to the - * bond-master device. These packets are mostly usable when - * stack receives it with the link on which they arrive - * (e.g. LLDP) they also must be available on master. Some of - * the use cases include (but are not limited to): LLDP agents - * that must be able to operate both on enslaved interfaces as - * well as on bonds themselves; linux bridges that must be able - * to process/pass BPDUs from attached bonds when any kind of - * STP version is enabled on the network. + /* + * For packets determined by bond_should_deliver_exact_match() call to + * be suppressed we want to make an exception for link-local packets. + * This is necessary for e.g. LLDP daemons to be able to monitor + * inactive slave links without being forced to bind to them + * explicitly. + * + * At the same time, packets that are passed to the bonding master + * (including link-local ones) can have their originating interface + * determined via PACKET_ORIGDEV socket option. */ - if (is_link_local_ether_addr(eth_hdr(skb)->h_dest)) { - struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); - - if (nskb) { - nskb->dev = bond->dev; - nskb->queue_mapping = 0; - netif_rx(nskb); - } - return RX_HANDLER_PASS; - } - if (bond_should_deliver_exact_match(skb, slave, bond)) + if (bond_should_deliver_exact_match(skb, slave, bond)) { + if (is_link_local_ether_addr(eth_hdr(skb)->h_dest)) + return RX_HANDLER_PASS; return RX_HANDLER_EXACT; + } skb->dev = bond->dev; @@ -1963,6 +1956,9 @@ static int __bond_release_one(struct net_device *bond_dev, if (!bond_has_slaves(bond)) { bond_set_carrier(bond); eth_hw_addr_random(bond_dev); + bond->nest_level = SINGLE_DEPTH_NESTING; + } else { + bond->nest_level = dev_get_nest_level(bond_dev) + 1; } unblock_netpoll_tx(); diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index a0f954f36c09..44e6c7b1b222 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -257,10 +257,7 @@ static int handle_tx(struct ser_device *ser) if (skb->len == 0) { struct sk_buff *tmp = skb_dequeue(&ser->head); WARN_ON(tmp != skb); - if (in_interrupt()) - dev_kfree_skb_irq(skb); - else - kfree_skb(skb); + dev_consume_skb_any(skb); } } /* Send flow off if queue is empty */ diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 3b3f88ffab53..c05e4d50d43d 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -480,8 +480,6 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb); struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr) { struct can_priv *priv = netdev_priv(dev); - struct sk_buff *skb = priv->echo_skb[idx]; - struct canfd_frame *cf; if (idx >= priv->echo_skb_max) { netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n", @@ -489,20 +487,21 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 return NULL; } - if (!skb) { - netdev_err(dev, "%s: BUG! Trying to echo non existing skb: can_priv::echo_skb[%u]\n", - __func__, idx); - return NULL; - } + if (priv->echo_skb[idx]) { + /* Using "struct canfd_frame::len" for the frame + * length is supported on both CAN and CANFD frames. + */ + struct sk_buff *skb = priv->echo_skb[idx]; + struct canfd_frame *cf = (struct canfd_frame *)skb->data; + u8 len = cf->len; - /* Using "struct canfd_frame::len" for the frame - * length is supported on both CAN and CANFD frames. - */ - cf = (struct canfd_frame *)skb->data; - *len_ptr = cf->len; - priv->echo_skb[idx] = NULL; + *len_ptr = len; + priv->echo_skb[idx] = NULL; - return skb; + return skb; + } + + return NULL; } /* diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 0f36eafe3ac1..1c66fb2ad76b 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -1106,7 +1106,7 @@ static int flexcan_chip_start(struct net_device *dev) } } else { /* clear and invalidate unused mailboxes first */ - for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i <= priv->mb_count; i++) { + for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i < priv->mb_count; i++) { mb = flexcan_get_mb(priv, i); priv->write(FLEXCAN_MB_CODE_RX_INACTIVE, &mb->can_ctrl); @@ -1432,7 +1432,7 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev) gpr_np = of_find_node_by_phandle(phandle); if (!gpr_np) { dev_dbg(&pdev->dev, "could not find gpr node by phandle\n"); - return PTR_ERR(gpr_np); + return -ENODEV; } priv = netdev_priv(dev); diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 0e4bbdcc614f..c76892ac4e69 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -344,7 +344,8 @@ static void b53_set_forwarding(struct b53_device *dev, int enable) b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt); } -static void b53_enable_vlan(struct b53_device *dev, bool enable) +static void b53_enable_vlan(struct b53_device *dev, bool enable, + bool enable_filtering) { u8 mgmt, vc0, vc1, vc4 = 0, vc5; @@ -369,8 +370,13 @@ static void b53_enable_vlan(struct b53_device *dev, bool enable) vc0 |= VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID; vc1 |= VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN; vc4 &= ~VC4_ING_VID_CHECK_MASK; - vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S; - vc5 |= VC5_DROP_VTABLE_MISS; + if (enable_filtering) { + vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S; + vc5 |= VC5_DROP_VTABLE_MISS; + } else { + vc4 |= VC4_ING_VID_VIO_FWD << VC4_ING_VID_CHECK_S; + vc5 &= ~VC5_DROP_VTABLE_MISS; + } if (is5325(dev)) vc0 &= ~VC0_RESERVED_1; @@ -420,6 +426,9 @@ static void b53_enable_vlan(struct b53_device *dev, bool enable) } b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); + + dev->vlan_enabled = enable; + dev->vlan_filtering_enabled = enable_filtering; } static int b53_set_jumbo(struct b53_device *dev, bool enable, bool allow_10_100) @@ -632,25 +641,35 @@ static void b53_enable_mib(struct b53_device *dev) b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, gc); } +static u16 b53_default_pvid(struct b53_device *dev) +{ + if (is5325(dev) || is5365(dev)) + return 1; + else + return 0; +} + int b53_configure_vlan(struct dsa_switch *ds) { struct b53_device *dev = ds->priv; struct b53_vlan vl = { 0 }; - int i; + int i, def_vid; + + def_vid = b53_default_pvid(dev); /* clear all vlan entries */ if (is5325(dev) || is5365(dev)) { - for (i = 1; i < dev->num_vlans; i++) + for (i = def_vid; i < dev->num_vlans; i++) b53_set_vlan_entry(dev, i, &vl); } else { b53_do_vlan_op(dev, VTA_CMD_CLEAR); } - b53_enable_vlan(dev, false); + b53_enable_vlan(dev, false, dev->vlan_filtering_enabled); b53_for_each_port(dev, i) b53_write16(dev, B53_VLAN_PAGE, - B53_VLAN_PORT_DEF_TAG(i), 1); + B53_VLAN_PORT_DEF_TAG(i), def_vid); if (!is5325(dev) && !is5365(dev)) b53_set_jumbo(dev, dev->enable_jumbo, false); @@ -1255,6 +1274,46 @@ EXPORT_SYMBOL(b53_phylink_mac_link_up); int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) { + struct b53_device *dev = ds->priv; + struct net_device *bridge_dev; + unsigned int i; + u16 pvid, new_pvid; + + /* Handle the case were multiple bridges span the same switch device + * and one of them has a different setting than what is being requested + * which would be breaking filtering semantics for any of the other + * bridge devices. + */ + b53_for_each_port(dev, i) { + bridge_dev = dsa_to_port(ds, i)->bridge_dev; + if (bridge_dev && + bridge_dev != dsa_to_port(ds, port)->bridge_dev && + br_vlan_enabled(bridge_dev) != vlan_filtering) { + netdev_err(bridge_dev, + "VLAN filtering is global to the switch!\n"); + return -EINVAL; + } + } + + b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), &pvid); + new_pvid = pvid; + if (dev->vlan_filtering_enabled && !vlan_filtering) { + /* Filtering is currently enabled, use the default PVID since + * the bridge does not expect tagging anymore + */ + dev->ports[port].pvid = pvid; + new_pvid = b53_default_pvid(dev); + } else if (!dev->vlan_filtering_enabled && vlan_filtering) { + /* Filtering is currently disabled, restore the previous PVID */ + new_pvid = dev->ports[port].pvid; + } + + if (pvid != new_pvid) + b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), + new_pvid); + + b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering); + return 0; } EXPORT_SYMBOL(b53_vlan_filtering); @@ -1270,7 +1329,7 @@ int b53_vlan_prepare(struct dsa_switch *ds, int port, if (vlan->vid_end > dev->num_vlans) return -ERANGE; - b53_enable_vlan(dev, true); + b53_enable_vlan(dev, true, dev->vlan_filtering_enabled); return 0; } @@ -1300,7 +1359,7 @@ void b53_vlan_add(struct dsa_switch *ds, int port, b53_fast_age_vlan(dev, vid); } - if (pvid) { + if (pvid && !dsa_is_cpu_port(ds, port)) { b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), vlan->vid_end); b53_fast_age_vlan(dev, vid); @@ -1326,12 +1385,8 @@ int b53_vlan_del(struct dsa_switch *ds, int port, vl->members &= ~BIT(port); - if (pvid == vid) { - if (is5325(dev) || is5365(dev)) - pvid = 1; - else - pvid = 0; - } + if (pvid == vid) + pvid = b53_default_pvid(dev); if (untagged && !dsa_is_cpu_port(ds, port)) vl->untag &= ~(BIT(port)); @@ -1644,10 +1699,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *br) b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan); dev->ports[port].vlan_ctl_mask = pvlan; - if (is5325(dev) || is5365(dev)) - pvid = 1; - else - pvid = 0; + pvid = b53_default_pvid(dev); /* Make this port join all VLANs without VLAN entries */ if (is58xx(dev)) { diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index ec796482792d..4dc7ee38b258 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h @@ -91,6 +91,7 @@ enum { struct b53_port { u16 vlan_ctl_mask; struct ethtool_eee eee; + u16 pvid; }; struct b53_vlan { @@ -137,6 +138,8 @@ struct b53_device { unsigned int num_vlans; struct b53_vlan *vlans; + bool vlan_enabled; + bool vlan_filtering_enabled; unsigned int num_ports; struct b53_port *ports; }; diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c index 90f514252987..d9c56a779c08 100644 --- a/drivers/net/dsa/b53/b53_srab.c +++ b/drivers/net/dsa/b53/b53_srab.c @@ -511,9 +511,6 @@ static void b53_srab_prepare_irq(struct platform_device *pdev) /* Clear all pending interrupts */ writel(0xffffffff, priv->regs + B53_SRAB_INTR); - if (dev->pdata && dev->pdata->chip_id != BCM58XX_DEVICE_ID) - return; - for (i = 0; i < B53_N_PORTS; i++) { port = &priv->port_intrs[i]; diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 361fbde76654..14138d423cf1 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -690,7 +690,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds) * port, the other ones have already been disabled during * bcm_sf2_sw_setup */ - for (port = 0; port < DSA_MAX_PORTS; port++) { + for (port = 0; port < ds->num_ports; port++) { if (dsa_is_user_port(ds, port) || dsa_is_cpu_port(ds, port)) bcm_sf2_port_disable(ds, port, NULL); } @@ -726,10 +726,11 @@ static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port, { struct net_device *p = ds->ports[port].cpu_dp->master; struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); - struct ethtool_wolinfo pwol; + struct ethtool_wolinfo pwol = { }; /* Get the parent device WoL settings */ - p->ethtool_ops->get_wol(p, &pwol); + if (p->ethtool_ops->get_wol) + p->ethtool_ops->get_wol(p, &pwol); /* Advertise the parent device supported settings */ wol->supported = pwol.supported; @@ -750,9 +751,10 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port, struct net_device *p = ds->ports[port].cpu_dp->master; struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); s8 cpu_port = ds->ports[port].cpu_dp->index; - struct ethtool_wolinfo pwol; + struct ethtool_wolinfo pwol = { }; - p->ethtool_ops->get_wol(p, &pwol); + if (p->ethtool_ops->get_wol) + p->ethtool_ops->get_wol(p, &pwol); if (wol->wolopts & ~pwol.supported) return -EINVAL; diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index 693a67f45bef..ddc1f9ca8ebc 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -1162,6 +1162,12 @@ static struct platform_driver gswip_driver = { module_platform_driver(gswip_driver); +MODULE_FIRMWARE("lantiq/xrx300_phy11g_a21.bin"); +MODULE_FIRMWARE("lantiq/xrx300_phy22f_a21.bin"); +MODULE_FIRMWARE("lantiq/xrx200_phy11g_a14.bin"); +MODULE_FIRMWARE("lantiq/xrx200_phy11g_a22.bin"); +MODULE_FIRMWARE("lantiq/xrx200_phy22f_a14.bin"); +MODULE_FIRMWARE("lantiq/xrx200_phy22f_a22.bin"); MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>"); MODULE_DESCRIPTION("Lantiq / Intel GSWIP driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 3b12e2dcff31..8a5111f9414c 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -7,7 +7,6 @@ #include <linux/delay.h> #include <linux/export.h> -#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/kernel.h> #include <linux/module.h> @@ -15,7 +14,6 @@ #include <linux/phy.h> #include <linux/etherdevice.h> #include <linux/if_bridge.h> -#include <linux/of_gpio.h> #include <linux/of_net.h> #include <net/dsa.h> #include <net/switchdev.h> diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 74547f43b938..a8a2c728afba 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -18,7 +18,6 @@ #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/netdevice.h> -#include <linux/of_gpio.h> #include <linux/of_mdio.h> #include <linux/of_net.h> #include <linux/of_platform.h> diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 8a517d8fb9d1..7e3c00bd9532 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -261,6 +261,7 @@ static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip) unsigned int sub_irq; unsigned int n; u16 reg; + u16 ctl1; int err; mutex_lock(&chip->reg_lock); @@ -270,13 +271,28 @@ static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip) if (err) goto out; - for (n = 0; n < chip->g1_irq.nirqs; ++n) { - if (reg & (1 << n)) { - sub_irq = irq_find_mapping(chip->g1_irq.domain, n); - handle_nested_irq(sub_irq); - ++nhandled; + do { + for (n = 0; n < chip->g1_irq.nirqs; ++n) { + if (reg & (1 << n)) { + sub_irq = irq_find_mapping(chip->g1_irq.domain, + n); + handle_nested_irq(sub_irq); + ++nhandled; + } } - } + + mutex_lock(&chip->reg_lock); + err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &ctl1); + if (err) + goto unlock; + err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, ®); +unlock: + mutex_unlock(&chip->reg_lock); + if (err) + goto out; + ctl1 &= GENMASK(chip->g1_irq.nirqs, 0); + } while (reg & ctl1); + out: return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); } @@ -880,7 +896,7 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip, default: return U64_MAX; } - value = (((u64)high) << 16) | low; + value = (((u64)high) << 32) | low; return value; } @@ -2403,6 +2419,107 @@ static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip) return mv88e6xxx_g1_stats_clear(chip); } +/* The mv88e6390 has some hidden registers used for debug and + * development. The errata also makes use of them. + */ +static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port, + int reg, u16 val) +{ + u16 ctrl; + int err; + + err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_DATA_PORT, + PORT_RESERVED_1A, val); + if (err) + return err; + + ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_WRITE | + PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT | + reg; + + return mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT, + PORT_RESERVED_1A, ctrl); +} + +static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip) +{ + return mv88e6xxx_wait(chip, PORT_RESERVED_1A_CTRL_PORT, + PORT_RESERVED_1A, PORT_RESERVED_1A_BUSY); +} + + +static int mv88e6390_hidden_read(struct mv88e6xxx_chip *chip, int port, + int reg, u16 *val) +{ + u16 ctrl; + int err; + + ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_READ | + PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT | + reg; + + err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT, + PORT_RESERVED_1A, ctrl); + if (err) + return err; + + err = mv88e6390_hidden_wait(chip); + if (err) + return err; + + return mv88e6xxx_port_read(chip, PORT_RESERVED_1A_DATA_PORT, + PORT_RESERVED_1A, val); +} + +/* Check if the errata has already been applied. */ +static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip) +{ + int port; + int err; + u16 val; + + for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { + err = mv88e6390_hidden_read(chip, port, 0, &val); + if (err) { + dev_err(chip->dev, + "Error reading hidden register: %d\n", err); + return false; + } + if (val != 0x01c0) + return false; + } + + return true; +} + +/* The 6390 copper ports have an errata which require poking magic + * values into undocumented hidden registers and then performing a + * software reset. + */ +static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip) +{ + int port; + int err; + + if (mv88e6390_setup_errata_applied(chip)) + return 0; + + /* Set the ports into blocking mode */ + for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { + err = mv88e6xxx_port_set_state(chip, port, BR_STATE_DISABLED); + if (err) + return err; + } + + for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { + err = mv88e6390_hidden_write(chip, port, 0, 0x01c0); + if (err) + return err; + } + + return mv88e6xxx_software_reset(chip); +} + static int mv88e6xxx_setup(struct dsa_switch *ds) { struct mv88e6xxx_chip *chip = ds->priv; @@ -2415,6 +2532,12 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) mutex_lock(&chip->reg_lock); + if (chip->info->ops->setup_errata) { + err = chip->info->ops->setup_errata(chip); + if (err) + goto unlock; + } + /* Cache the cmode of each port. */ for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { if (chip->info->ops->port_get_cmode) { @@ -2970,7 +3093,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6185_port_get_cmode, - .stats_snapshot = mv88e6320_g1_stats_snapshot, + .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3226,6 +3349,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { static const struct mv88e6xxx_ops mv88e6190_ops = { /* MV88E6XXX_FAMILY_6390 */ + .setup_errata = mv88e6390_setup_errata, .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, @@ -3269,6 +3393,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { static const struct mv88e6xxx_ops mv88e6190x_ops = { /* MV88E6XXX_FAMILY_6390 */ + .setup_errata = mv88e6390_setup_errata, .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, @@ -3312,6 +3437,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { static const struct mv88e6xxx_ops mv88e6191_ops = { /* MV88E6XXX_FAMILY_6390 */ + .setup_errata = mv88e6390_setup_errata, .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, @@ -3404,6 +3530,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { static const struct mv88e6xxx_ops mv88e6290_ops = { /* MV88E6XXX_FAMILY_6390 */ + .setup_errata = mv88e6390_setup_errata, .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, @@ -3709,6 +3836,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { static const struct mv88e6xxx_ops mv88e6390_ops = { /* MV88E6XXX_FAMILY_6390 */ + .setup_errata = mv88e6390_setup_errata, .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, @@ -3756,6 +3884,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { static const struct mv88e6xxx_ops mv88e6390x_ops = { /* MV88E6XXX_FAMILY_6390 */ + .setup_errata = mv88e6390_setup_errata, .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, @@ -4466,6 +4595,14 @@ static int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip, return 0; } +static void mv88e6xxx_ports_cmode_init(struct mv88e6xxx_chip *chip) +{ + int i; + + for (i = 0; i < mv88e6xxx_num_ports(chip); i++) + chip->ports[i].cmode = MV88E6XXX_PORT_STS_CMODE_INVALID; +} + static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds, int port) { @@ -4502,6 +4639,8 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev, if (err) goto free; + mv88e6xxx_ports_cmode_init(chip); + mutex_lock(&chip->reg_lock); err = mv88e6xxx_switch_reset(chip); mutex_unlock(&chip->reg_lock); diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index f9ecb7872d32..546651d8c3e1 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -300,6 +300,11 @@ struct mv88e6xxx_mdio_bus { }; struct mv88e6xxx_ops { + /* Switch Setup Errata, called early in the switch setup to + * allow any errata actions to be performed + */ + int (*setup_errata)(struct mv88e6xxx_chip *chip); + int (*ieee_pri_map)(struct mv88e6xxx_chip *chip); int (*ip_pri_map)(struct mv88e6xxx_chip *chip); diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c b/drivers/net/dsa/mv88e6xxx/global1_atu.c index 5200e4bdce93..ea243840ee0f 100644 --- a/drivers/net/dsa/mv88e6xxx/global1_atu.c +++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c @@ -314,6 +314,7 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) { struct mv88e6xxx_chip *chip = dev_id; struct mv88e6xxx_atu_entry entry; + int spid; int err; u16 val; @@ -336,6 +337,8 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) if (err) goto out; + spid = entry.state; + if (val & MV88E6XXX_G1_ATU_OP_AGE_OUT_VIOLATION) { dev_err_ratelimited(chip->dev, "ATU age out violation for %pM\n", @@ -344,23 +347,23 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) { dev_err_ratelimited(chip->dev, - "ATU member violation for %pM portvec %x\n", - entry.mac, entry.portvec); - chip->ports[entry.portvec].atu_member_violation++; + "ATU member violation for %pM portvec %x spid %d\n", + entry.mac, entry.portvec, spid); + chip->ports[spid].atu_member_violation++; } if (val & MV88E6XXX_G1_ATU_OP_MISS_VIOLATION) { dev_err_ratelimited(chip->dev, - "ATU miss violation for %pM portvec %x\n", - entry.mac, entry.portvec); - chip->ports[entry.portvec].atu_miss_violation++; + "ATU miss violation for %pM portvec %x spid %d\n", + entry.mac, entry.portvec, spid); + chip->ports[spid].atu_miss_violation++; } if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) { dev_err_ratelimited(chip->dev, - "ATU full violation for %pM portvec %x\n", - entry.mac, entry.portvec); - chip->ports[entry.portvec].atu_full_violation++; + "ATU full violation for %pM portvec %x spid %d\n", + entry.mac, entry.portvec, spid); + chip->ports[spid].atu_full_violation++; } mutex_unlock(&chip->reg_lock); diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index ebd26b6a93e6..79ab51e69aee 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -398,6 +398,10 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, cmode = 0; } + /* cmode doesn't change, nothing to do for us */ + if (cmode == chip->ports[port].cmode) + return 0; + lane = mv88e6390x_serdes_get_lane(chip, port); if (lane < 0) return lane; @@ -408,7 +412,7 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, return err; } - err = mv88e6390_serdes_power(chip, port, false); + err = mv88e6390x_serdes_power(chip, port, false); if (err) return err; @@ -424,7 +428,7 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, if (err) return err; - err = mv88e6390_serdes_power(chip, port, true); + err = mv88e6390x_serdes_power(chip, port, true); if (err) return err; diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 0d81866d0e4a..4aadf321edb7 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -52,6 +52,7 @@ #define MV88E6185_PORT_STS_CMODE_1000BASE_X 0x0005 #define MV88E6185_PORT_STS_CMODE_PHY 0x0006 #define MV88E6185_PORT_STS_CMODE_DISABLED 0x0007 +#define MV88E6XXX_PORT_STS_CMODE_INVALID 0xff /* Offset 0x01: MAC (or PCS or Physical) Control Register */ #define MV88E6XXX_PORT_MAC_CTL 0x01 @@ -251,6 +252,16 @@ /* Offset 0x19: Port IEEE Priority Remapping Registers (4-7) */ #define MV88E6095_PORT_IEEE_PRIO_REMAP_4567 0x19 +/* Offset 0x1a: Magic undocumented errata register */ +#define PORT_RESERVED_1A 0x1a +#define PORT_RESERVED_1A_BUSY BIT(15) +#define PORT_RESERVED_1A_WRITE BIT(14) +#define PORT_RESERVED_1A_READ 0 +#define PORT_RESERVED_1A_PORT_SHIFT 5 +#define PORT_RESERVED_1A_BLOCK (0xf << 10) +#define PORT_RESERVED_1A_CTRL_PORT 4 +#define PORT_RESERVED_1A_DATA_PORT 5 + int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, u16 *val); int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 2caa8c8b4b55..1bfc5ff8d81d 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -664,7 +664,7 @@ int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) if (port < 9) return 0; - return mv88e6390_serdes_irq_setup(chip, port); + return mv88e6390x_serdes_irq_setup(chip, port); } void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) diff --git a/drivers/net/dsa/realtek-smi.c b/drivers/net/dsa/realtek-smi.c index b4b839a1d095..ad41ec63cc9f 100644 --- a/drivers/net/dsa/realtek-smi.c +++ b/drivers/net/dsa/realtek-smi.c @@ -347,16 +347,17 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi) struct device_node *mdio_np; int ret; - mdio_np = of_find_compatible_node(smi->dev->of_node, NULL, - "realtek,smi-mdio"); + mdio_np = of_get_compatible_child(smi->dev->of_node, "realtek,smi-mdio"); if (!mdio_np) { dev_err(smi->dev, "no MDIO bus node\n"); return -ENODEV; } smi->slave_mii_bus = devm_mdiobus_alloc(smi->dev); - if (!smi->slave_mii_bus) - return -ENOMEM; + if (!smi->slave_mii_bus) { + ret = -ENOMEM; + goto err_put_node; + } smi->slave_mii_bus->priv = smi; smi->slave_mii_bus->name = "SMI slave MII"; smi->slave_mii_bus->read = realtek_smi_mdio_read; @@ -371,10 +372,15 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi) if (ret) { dev_err(smi->dev, "unable to register MDIO bus %s\n", smi->slave_mii_bus->id); - of_node_put(mdio_np); + goto err_put_node; } return 0; + +err_put_node: + of_node_put(mdio_np); + + return ret; } static int realtek_smi_probe(struct platform_device *pdev) @@ -457,6 +463,8 @@ static int realtek_smi_remove(struct platform_device *pdev) struct realtek_smi *smi = dev_get_drvdata(&pdev->dev); dsa_unregister_switch(smi->ds); + if (smi->slave_mii_bus) + of_node_put(smi->slave_mii_bus->dev.of_node); gpiod_set_value(smi->reset, 1); return 0; diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c index 91fc64c1145e..47e5984f16fb 100644 --- a/drivers/net/ethernet/aeroflex/greth.c +++ b/drivers/net/ethernet/aeroflex/greth.c @@ -1433,18 +1433,18 @@ static int greth_of_probe(struct platform_device *ofdev) } /* Allocate TX descriptor ring in coherent memory */ - greth->tx_bd_base = dma_zalloc_coherent(greth->dev, 1024, - &greth->tx_bd_base_phys, - GFP_KERNEL); + greth->tx_bd_base = dma_alloc_coherent(greth->dev, 1024, + &greth->tx_bd_base_phys, + GFP_KERNEL); if (!greth->tx_bd_base) { err = -ENOMEM; goto error3; } /* Allocate RX descriptor ring in coherent memory */ - greth->rx_bd_base = dma_zalloc_coherent(greth->dev, 1024, - &greth->rx_bd_base_phys, - GFP_KERNEL); + greth->rx_bd_base = dma_alloc_coherent(greth->dev, 1024, + &greth->rx_bd_base_phys, + GFP_KERNEL); if (!greth->rx_bd_base) { err = -ENOMEM; goto error4; diff --git a/drivers/net/ethernet/alacritech/slicoss.c b/drivers/net/ethernet/alacritech/slicoss.c index 0b60921c392f..16477aa6d61f 100644 --- a/drivers/net/ethernet/alacritech/slicoss.c +++ b/drivers/net/ethernet/alacritech/slicoss.c @@ -795,8 +795,8 @@ static int slic_init_stat_queue(struct slic_device *sdev) size = stq->len * sizeof(*descs) + DESC_ALIGN_MASK; for (i = 0; i < SLIC_NUM_STAT_DESC_ARRAYS; i++) { - descs = dma_zalloc_coherent(&sdev->pdev->dev, size, &paddr, - GFP_KERNEL); + descs = dma_alloc_coherent(&sdev->pdev->dev, size, &paddr, + GFP_KERNEL); if (!descs) { netdev_err(sdev->netdev, "failed to allocate status descriptors\n"); @@ -1240,8 +1240,8 @@ static int slic_init_shmem(struct slic_device *sdev) struct slic_shmem_data *sm_data; dma_addr_t paddr; - sm_data = dma_zalloc_coherent(&sdev->pdev->dev, sizeof(*sm_data), - &paddr, GFP_KERNEL); + sm_data = dma_alloc_coherent(&sdev->pdev->dev, sizeof(*sm_data), + &paddr, GFP_KERNEL); if (!sm_data) { dev_err(&sdev->pdev->dev, "failed to allocate shared memory\n"); return -ENOMEM; @@ -1621,8 +1621,8 @@ static int slic_read_eeprom(struct slic_device *sdev) int err = 0; u8 *mac[2]; - eeprom = dma_zalloc_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE, - &paddr, GFP_KERNEL); + eeprom = dma_alloc_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE, + &paddr, GFP_KERNEL); if (!eeprom) return -ENOMEM; diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c index 4f11f98347ed..1827ef1f6d55 100644 --- a/drivers/net/ethernet/alteon/acenic.c +++ b/drivers/net/ethernet/alteon/acenic.c @@ -2059,7 +2059,7 @@ static inline void ace_tx_int(struct net_device *dev, if (skb) { dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); info->skb = NULL; } diff --git a/drivers/net/ethernet/altera/altera_msgdma.c b/drivers/net/ethernet/altera/altera_msgdma.c index 0fb986ba3290..0ae723f75341 100644 --- a/drivers/net/ethernet/altera/altera_msgdma.c +++ b/drivers/net/ethernet/altera/altera_msgdma.c @@ -145,7 +145,8 @@ u32 msgdma_tx_completions(struct altera_tse_private *priv) & 0xffff; if (inuse) { /* Tx FIFO is not empty */ - ready = priv->tx_prod - priv->tx_cons - inuse - 1; + ready = max_t(int, + priv->tx_prod - priv->tx_cons - inuse - 1, 0); } else { /* Check for buffered last packet */ status = csrrd32(priv->tx_dma_csr, msgdma_csroffs(status)); diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index 02921d877c08..aa1d1f5339d2 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -714,8 +714,10 @@ static struct phy_device *connect_local_phy(struct net_device *dev) phydev = phy_connect(dev, phy_id_fmt, &altera_tse_adjust_link, priv->phy_iface); - if (IS_ERR(phydev)) + if (IS_ERR(phydev)) { netdev_err(dev, "Could not attach to PHY\n"); + phydev = NULL; + } } else { int ret; diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index 420cede41ca4..b17d435de09f 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -111,8 +111,8 @@ static int ena_com_admin_init_sq(struct ena_com_admin_queue *queue) struct ena_com_admin_sq *sq = &queue->sq; u16 size = ADMIN_SQ_SIZE(queue->q_depth); - sq->entries = dma_zalloc_coherent(queue->q_dmadev, size, &sq->dma_addr, - GFP_KERNEL); + sq->entries = dma_alloc_coherent(queue->q_dmadev, size, &sq->dma_addr, + GFP_KERNEL); if (!sq->entries) { pr_err("memory allocation failed"); @@ -133,8 +133,8 @@ static int ena_com_admin_init_cq(struct ena_com_admin_queue *queue) struct ena_com_admin_cq *cq = &queue->cq; u16 size = ADMIN_CQ_SIZE(queue->q_depth); - cq->entries = dma_zalloc_coherent(queue->q_dmadev, size, &cq->dma_addr, - GFP_KERNEL); + cq->entries = dma_alloc_coherent(queue->q_dmadev, size, &cq->dma_addr, + GFP_KERNEL); if (!cq->entries) { pr_err("memory allocation failed"); @@ -156,8 +156,8 @@ static int ena_com_admin_init_aenq(struct ena_com_dev *dev, dev->aenq.q_depth = ENA_ASYNC_QUEUE_DEPTH; size = ADMIN_AENQ_SIZE(ENA_ASYNC_QUEUE_DEPTH); - aenq->entries = dma_zalloc_coherent(dev->dmadev, size, &aenq->dma_addr, - GFP_KERNEL); + aenq->entries = dma_alloc_coherent(dev->dmadev, size, &aenq->dma_addr, + GFP_KERNEL); if (!aenq->entries) { pr_err("memory allocation failed"); @@ -344,15 +344,15 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev, dev_node = dev_to_node(ena_dev->dmadev); set_dev_node(ena_dev->dmadev, ctx->numa_node); io_sq->desc_addr.virt_addr = - dma_zalloc_coherent(ena_dev->dmadev, size, - &io_sq->desc_addr.phys_addr, - GFP_KERNEL); + dma_alloc_coherent(ena_dev->dmadev, size, + &io_sq->desc_addr.phys_addr, + GFP_KERNEL); set_dev_node(ena_dev->dmadev, dev_node); if (!io_sq->desc_addr.virt_addr) { io_sq->desc_addr.virt_addr = - dma_zalloc_coherent(ena_dev->dmadev, size, - &io_sq->desc_addr.phys_addr, - GFP_KERNEL); + dma_alloc_coherent(ena_dev->dmadev, size, + &io_sq->desc_addr.phys_addr, + GFP_KERNEL); } if (!io_sq->desc_addr.virt_addr) { @@ -425,14 +425,14 @@ static int ena_com_init_io_cq(struct ena_com_dev *ena_dev, prev_node = dev_to_node(ena_dev->dmadev); set_dev_node(ena_dev->dmadev, ctx->numa_node); io_cq->cdesc_addr.virt_addr = - dma_zalloc_coherent(ena_dev->dmadev, size, - &io_cq->cdesc_addr.phys_addr, GFP_KERNEL); + dma_alloc_coherent(ena_dev->dmadev, size, + &io_cq->cdesc_addr.phys_addr, GFP_KERNEL); set_dev_node(ena_dev->dmadev, prev_node); if (!io_cq->cdesc_addr.virt_addr) { io_cq->cdesc_addr.virt_addr = - dma_zalloc_coherent(ena_dev->dmadev, size, - &io_cq->cdesc_addr.phys_addr, - GFP_KERNEL); + dma_alloc_coherent(ena_dev->dmadev, size, + &io_cq->cdesc_addr.phys_addr, + GFP_KERNEL); } if (!io_cq->cdesc_addr.virt_addr) { @@ -1026,8 +1026,8 @@ static int ena_com_hash_key_allocate(struct ena_com_dev *ena_dev) struct ena_rss *rss = &ena_dev->rss; rss->hash_key = - dma_zalloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_key), - &rss->hash_key_dma_addr, GFP_KERNEL); + dma_alloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_key), + &rss->hash_key_dma_addr, GFP_KERNEL); if (unlikely(!rss->hash_key)) return -ENOMEM; @@ -1050,8 +1050,8 @@ static int ena_com_hash_ctrl_init(struct ena_com_dev *ena_dev) struct ena_rss *rss = &ena_dev->rss; rss->hash_ctrl = - dma_zalloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_ctrl), - &rss->hash_ctrl_dma_addr, GFP_KERNEL); + dma_alloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_ctrl), + &rss->hash_ctrl_dma_addr, GFP_KERNEL); if (unlikely(!rss->hash_ctrl)) return -ENOMEM; @@ -1094,8 +1094,8 @@ static int ena_com_indirect_table_allocate(struct ena_com_dev *ena_dev, sizeof(struct ena_admin_rss_ind_table_entry); rss->rss_ind_tbl = - dma_zalloc_coherent(ena_dev->dmadev, tbl_size, - &rss->rss_ind_tbl_dma_addr, GFP_KERNEL); + dma_alloc_coherent(ena_dev->dmadev, tbl_size, + &rss->rss_ind_tbl_dma_addr, GFP_KERNEL); if (unlikely(!rss->rss_ind_tbl)) goto mem_err1; @@ -1649,9 +1649,9 @@ int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev) spin_lock_init(&mmio_read->lock); mmio_read->read_resp = - dma_zalloc_coherent(ena_dev->dmadev, - sizeof(*mmio_read->read_resp), - &mmio_read->read_resp_dma_addr, GFP_KERNEL); + dma_alloc_coherent(ena_dev->dmadev, + sizeof(*mmio_read->read_resp), + &mmio_read->read_resp_dma_addr, GFP_KERNEL); if (unlikely(!mmio_read->read_resp)) goto err; @@ -2623,8 +2623,8 @@ int ena_com_allocate_host_info(struct ena_com_dev *ena_dev) struct ena_host_attribute *host_attr = &ena_dev->host_attr; host_attr->host_info = - dma_zalloc_coherent(ena_dev->dmadev, SZ_4K, - &host_attr->host_info_dma_addr, GFP_KERNEL); + dma_alloc_coherent(ena_dev->dmadev, SZ_4K, + &host_attr->host_info_dma_addr, GFP_KERNEL); if (unlikely(!host_attr->host_info)) return -ENOMEM; @@ -2641,8 +2641,9 @@ int ena_com_allocate_debug_area(struct ena_com_dev *ena_dev, struct ena_host_attribute *host_attr = &ena_dev->host_attr; host_attr->debug_area_virt_addr = - dma_zalloc_coherent(ena_dev->dmadev, debug_area_size, - &host_attr->debug_area_dma_addr, GFP_KERNEL); + dma_alloc_coherent(ena_dev->dmadev, debug_area_size, + &host_attr->debug_area_dma_addr, + GFP_KERNEL); if (unlikely(!host_attr->debug_area_virt_addr)) { host_attr->debug_area_size = 0; return -ENOMEM; diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index a70bb1bb90e7..a6eacf2099c3 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -2663,11 +2663,6 @@ static int ena_restore_device(struct ena_adapter *adapter) goto err_device_destroy; } - clear_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags); - /* Make sure we don't have a race with AENQ Links state handler */ - if (test_bit(ENA_FLAG_LINK_UP, &adapter->flags)) - netif_carrier_on(adapter->netdev); - rc = ena_enable_msix_and_set_admin_interrupts(adapter, adapter->num_queues); if (rc) { @@ -2684,6 +2679,11 @@ static int ena_restore_device(struct ena_adapter *adapter) } set_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags); + + clear_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags); + if (test_bit(ENA_FLAG_LINK_UP, &adapter->flags)) + netif_carrier_on(adapter->netdev); + mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ)); dev_err(&pdev->dev, "Device reset completed successfully, Driver info: %s\n", diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index dc8b6173d8d8..63870072cbbd 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -45,7 +45,7 @@ #define DRV_MODULE_VER_MAJOR 2 #define DRV_MODULE_VER_MINOR 0 -#define DRV_MODULE_VER_SUBMINOR 2 +#define DRV_MODULE_VER_SUBMINOR 3 #define DRV_MODULE_NAME "ena" #ifndef DRV_MODULE_VERSION diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index a90080f12e67..e548c0ae2e00 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c @@ -666,7 +666,7 @@ static int amd8111e_tx(struct net_device *dev) pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[tx_index], lp->tx_skbuff[tx_index]->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq (lp->tx_skbuff[tx_index]); + dev_consume_skb_irq(lp->tx_skbuff[tx_index]); lp->tx_skbuff[tx_index] = NULL; lp->tx_dma_addr[tx_index] = 0; } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index d272dc6984ac..b40d4377cc71 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -431,8 +431,6 @@ #define MAC_MDIOSCAR_PA_WIDTH 5 #define MAC_MDIOSCAR_RA_INDEX 0 #define MAC_MDIOSCAR_RA_WIDTH 16 -#define MAC_MDIOSCAR_REG_INDEX 0 -#define MAC_MDIOSCAR_REG_WIDTH 21 #define MAC_MDIOSCCDR_BUSY_INDEX 22 #define MAC_MDIOSCCDR_BUSY_WIDTH 1 #define MAC_MDIOSCCDR_CMD_INDEX 16 diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 1e929a1e4ca7..4666084eda16 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -1284,6 +1284,20 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad, } } +static unsigned int xgbe_create_mdio_sca(int port, int reg) +{ + unsigned int mdio_sca, da; + + da = (reg & MII_ADDR_C45) ? reg >> 16 : 0; + + mdio_sca = 0; + XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, RA, reg); + XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, PA, port); + XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, da); + + return mdio_sca; +} + static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr, int reg, u16 val) { @@ -1291,9 +1305,7 @@ static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr, reinit_completion(&pdata->mdio_complete); - mdio_sca = 0; - XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg); - XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr); + mdio_sca = xgbe_create_mdio_sca(addr, reg); XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca); mdio_sccd = 0; @@ -1317,9 +1329,7 @@ static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr, reinit_completion(&pdata->mdio_complete); - mdio_sca = 0; - XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg); - XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr); + mdio_sca = xgbe_create_mdio_sca(addr, reg); XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca); mdio_sccd = 0; diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c b/drivers/net/ethernet/apm/xgene-v2/main.c index 0f2ad50f3bd7..87b142a312e0 100644 --- a/drivers/net/ethernet/apm/xgene-v2/main.c +++ b/drivers/net/ethernet/apm/xgene-v2/main.c @@ -206,8 +206,8 @@ static netdev_tx_t xge_start_xmit(struct sk_buff *skb, struct net_device *ndev) } /* Packet buffers should be 64B aligned */ - pkt_buf = dma_zalloc_coherent(dev, XGENE_ENET_STD_MTU, &dma_addr, - GFP_ATOMIC); + pkt_buf = dma_alloc_coherent(dev, XGENE_ENET_STD_MTU, &dma_addr, + GFP_ATOMIC); if (unlikely(!pkt_buf)) { dev_kfree_skb_any(skb); return NETDEV_TX_OK; @@ -428,8 +428,8 @@ static struct xge_desc_ring *xge_create_desc_ring(struct net_device *ndev) ring->ndev = ndev; size = XGENE_ENET_DESC_SIZE * XGENE_ENET_NUM_DESC; - ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma_addr, - GFP_KERNEL); + ring->desc_addr = dma_alloc_coherent(dev, size, &ring->dma_addr, + GFP_KERNEL); if (!ring->desc_addr) goto err; diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c index 6a8e2567f2bd..4d3855ceb500 100644 --- a/drivers/net/ethernet/apple/bmac.c +++ b/drivers/net/ethernet/apple/bmac.c @@ -777,7 +777,7 @@ static irqreturn_t bmac_txdma_intr(int irq, void *dev_id) if (bp->tx_bufs[bp->tx_empty]) { ++dev->stats.tx_packets; - dev_kfree_skb_irq(bp->tx_bufs[bp->tx_empty]); + dev_consume_skb_irq(bp->tx_bufs[bp->tx_empty]); } bp->tx_bufs[bp->tx_empty] = NULL; bp->tx_fullup = 0; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index b58ca7cb8e9d..fbba300c1d01 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -275,6 +275,9 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self) { + /* Tx TC/Queue number config */ + hw_atl_rpb_tps_tx_tc_mode_set(self, 1U); + hw_atl_thm_lso_tcp_flag_of_first_pkt_set(self, 0x0FF6U); hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(self, 0x0FF6U); hw_atl_thm_lso_tcp_flag_of_last_pkt_set(self, 0x0F7FU); diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c index 939f77e2e117..8ac7a67b15c1 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c @@ -1274,6 +1274,15 @@ void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en) HW_ATL_TPB_TX_BUF_EN_SHIFT, tx_buff_en); } +void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw, + u32 tx_traf_class_mode) +{ + aq_hw_write_reg_bit(aq_hw, HW_ATL_TPB_TX_TC_MODE_ADDR, + HW_ATL_TPB_TX_TC_MODE_MSK, + HW_ATL_TPB_TX_TC_MODE_SHIFT, + tx_traf_class_mode); +} + void hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(struct aq_hw_s *aq_hw, u32 tx_buff_hi_threshold_per_tc, u32 buffer) diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h index 03c570d115fe..f529540bfd7e 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h @@ -605,6 +605,10 @@ void hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(struct aq_hw_s *aq_hw, /* tpb */ +/* set TX Traffic Class Mode */ +void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw, + u32 tx_traf_class_mode); + /* set tx buffer enable */ void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en); diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h index 8470d92db812..e91ffce005f1 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h @@ -1948,6 +1948,19 @@ /* default value of bitfield tx_buf_en */ #define HW_ATL_TPB_TX_BUF_EN_DEFAULT 0x0 +/* register address for bitfield tx_tc_mode */ +#define HW_ATL_TPB_TX_TC_MODE_ADDR 0x00007900 +/* bitmask for bitfield tx_tc_mode */ +#define HW_ATL_TPB_TX_TC_MODE_MSK 0x00000100 +/* inverted bitmask for bitfield tx_tc_mode */ +#define HW_ATL_TPB_TX_TC_MODE_MSKN 0xFFFFFEFF +/* lower bit position of bitfield tx_tc_mode */ +#define HW_ATL_TPB_TX_TC_MODE_SHIFT 8 +/* width of bitfield tx_tc_mode */ +#define HW_ATL_TPB_TX_TC_MODE_WIDTH 1 +/* default value of bitfield tx_tc_mode */ +#define HW_ATL_TPB_TX_TC_MODE_DEFAULT 0x0 + /* tx tx{b}_hi_thresh[c:0] bitfield definitions * preprocessor definitions for the bitfield "tx{b}_hi_thresh[c:0]". * parameter: buffer {b} | stride size 0x10 | range [0, 7] diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index c131cfc1b79d..e3538ba7d0e7 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -660,10 +660,9 @@ static int alx_alloc_rings(struct alx_priv *alx) alx->num_txq + sizeof(struct alx_rrd) * alx->rx_ringsz + sizeof(struct alx_rfd) * alx->rx_ringsz; - alx->descmem.virt = dma_zalloc_coherent(&alx->hw.pdev->dev, - alx->descmem.size, - &alx->descmem.dma, - GFP_KERNEL); + alx->descmem.virt = dma_alloc_coherent(&alx->hw.pdev->dev, + alx->descmem.size, + &alx->descmem.dma, GFP_KERNEL); if (!alx->descmem.virt) return -ENOMEM; diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 7087b88550db..3a3b35b5df67 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -1019,8 +1019,8 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) sizeof(struct atl1c_recv_ret_status) * rx_desc_count + 8 * 4; - ring_header->desc = dma_zalloc_coherent(&pdev->dev, ring_header->size, - &ring_header->dma, GFP_KERNEL); + ring_header->desc = dma_alloc_coherent(&pdev->dev, ring_header->size, + &ring_header->dma, GFP_KERNEL); if (unlikely(!ring_header->desc)) { dev_err(&pdev->dev, "could not get memory for DMA buffer\n"); goto err_nomem; diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index bb41becb6609..31ff1e0d1baa 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c @@ -1335,13 +1335,11 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct atl2_adapter *adapter; - static int cards_found; + static int cards_found = 0; unsigned long mmio_start; int mmio_len; int err; - cards_found = 0; - err = pci_enable_device(pdev); if (err) return err; diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index f44808959ff3..97ab0dd25552 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -638,7 +638,7 @@ static void b44_tx(struct b44 *bp) bytes_compl += skb->len; pkts_compl++; - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); } netdev_completed_queue(bp->dev, pkts_compl, bytes_compl); @@ -1012,7 +1012,7 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev) } skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len); - dev_kfree_skb_any(skb); + dev_consume_skb_any(skb); skb = bounce_skb; } diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index 6bae973d4dce..09cd188826b1 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -936,7 +936,7 @@ static int bcm_enet_open(struct net_device *dev) /* allocate rx dma ring */ size = priv->rx_ring_size * sizeof(struct bcm_enet_desc); - p = dma_zalloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL); + p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL); if (!p) { ret = -ENOMEM; goto out_freeirq_tx; @@ -947,7 +947,7 @@ static int bcm_enet_open(struct net_device *dev) /* allocate tx dma ring */ size = priv->tx_ring_size * sizeof(struct bcm_enet_desc); - p = dma_zalloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL); + p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL); if (!p) { ret = -ENOMEM; goto out_free_rx_ring; @@ -2120,7 +2120,7 @@ static int bcm_enetsw_open(struct net_device *dev) /* allocate rx dma ring */ size = priv->rx_ring_size * sizeof(struct bcm_enet_desc); - p = dma_zalloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL); + p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL); if (!p) { dev_err(kdev, "cannot allocate rx ring %u\n", size); ret = -ENOMEM; @@ -2132,7 +2132,7 @@ static int bcm_enetsw_open(struct net_device *dev) /* allocate tx dma ring */ size = priv->tx_ring_size * sizeof(struct bcm_enet_desc); - p = dma_zalloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL); + p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL); if (!p) { dev_err(kdev, "cannot allocate tx ring\n"); ret = -ENOMEM; diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 4574275ef445..bc3ac369cbe3 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -134,6 +134,10 @@ static void bcm_sysport_set_rx_csum(struct net_device *dev, priv->rx_chk_en = !!(wanted & NETIF_F_RXCSUM); reg = rxchk_readl(priv, RXCHK_CONTROL); + /* Clear L2 header checks, which would prevent BPDUs + * from being received. + */ + reg &= ~RXCHK_L2_HDR_DIS; if (priv->rx_chk_en) reg |= RXCHK_EN; else @@ -520,7 +524,6 @@ static void bcm_sysport_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct bcm_sysport_priv *priv = netdev_priv(dev); - u32 reg; wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER; wol->wolopts = priv->wolopts; @@ -528,11 +531,7 @@ static void bcm_sysport_get_wol(struct net_device *dev, if (!(priv->wolopts & WAKE_MAGICSECURE)) return; - /* Return the programmed SecureOn password */ - reg = umac_readl(priv, UMAC_PSW_MS); - put_unaligned_be16(reg, &wol->sopass[0]); - reg = umac_readl(priv, UMAC_PSW_LS); - put_unaligned_be32(reg, &wol->sopass[2]); + memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass)); } static int bcm_sysport_set_wol(struct net_device *dev, @@ -548,13 +547,8 @@ static int bcm_sysport_set_wol(struct net_device *dev, if (wol->wolopts & ~supported) return -EINVAL; - /* Program the SecureOn password */ - if (wol->wolopts & WAKE_MAGICSECURE) { - umac_writel(priv, get_unaligned_be16(&wol->sopass[0]), - UMAC_PSW_MS); - umac_writel(priv, get_unaligned_be32(&wol->sopass[2]), - UMAC_PSW_LS); - } + if (wol->wolopts & WAKE_MAGICSECURE) + memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass)); /* Flag the device and relevant IRQ as wakeup capable */ if (wol->wolopts) { @@ -1506,8 +1500,8 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv, /* We just need one DMA descriptor which is DMA-able, since writing to * the port will allocate a new descriptor in its internal linked-list */ - p = dma_zalloc_coherent(kdev, sizeof(struct dma_desc), &ring->desc_dma, - GFP_KERNEL); + p = dma_alloc_coherent(kdev, sizeof(struct dma_desc), &ring->desc_dma, + GFP_KERNEL); if (!p) { netif_err(priv, hw, priv->netdev, "DMA alloc failed\n"); return -ENOMEM; @@ -2649,13 +2643,18 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv) unsigned int index, i = 0; u32 reg; - /* Password has already been programmed */ reg = umac_readl(priv, UMAC_MPD_CTRL); if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) reg |= MPD_EN; reg &= ~PSW_EN; - if (priv->wolopts & WAKE_MAGICSECURE) + if (priv->wolopts & WAKE_MAGICSECURE) { + /* Program the SecureOn password */ + umac_writel(priv, get_unaligned_be16(&priv->sopass[0]), + UMAC_PSW_MS); + umac_writel(priv, get_unaligned_be32(&priv->sopass[2]), + UMAC_PSW_LS); reg |= PSW_EN; + } umac_writel(priv, reg, UMAC_MPD_CTRL); if (priv->wolopts & WAKE_FILTER) { diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h index 0887e6356649..0b192fea9c5d 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.h +++ b/drivers/net/ethernet/broadcom/bcmsysport.h @@ -12,6 +12,7 @@ #define __BCM_SYSPORT_H #include <linux/bitmap.h> +#include <linux/ethtool.h> #include <linux/if_vlan.h> #include <linux/net_dim.h> @@ -778,6 +779,7 @@ struct bcm_sysport_priv { unsigned int crc_fwd:1; u16 rev; u32 wolopts; + u8 sopass[SOPASS_MAX]; unsigned int wol_irq_disabled:1; /* MIB related fields */ diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index cabc8e49ad24..2d3a44c40221 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -634,9 +634,9 @@ static int bgmac_dma_alloc(struct bgmac *bgmac) /* Alloc ring of descriptors */ size = BGMAC_TX_RING_SLOTS * sizeof(struct bgmac_dma_desc); - ring->cpu_base = dma_zalloc_coherent(dma_dev, size, - &ring->dma_base, - GFP_KERNEL); + ring->cpu_base = dma_alloc_coherent(dma_dev, size, + &ring->dma_base, + GFP_KERNEL); if (!ring->cpu_base) { dev_err(bgmac->dev, "Allocation of TX ring 0x%X failed\n", ring->mmio_base); @@ -659,9 +659,9 @@ static int bgmac_dma_alloc(struct bgmac *bgmac) /* Alloc ring of descriptors */ size = BGMAC_RX_RING_SLOTS * sizeof(struct bgmac_dma_desc); - ring->cpu_base = dma_zalloc_coherent(dma_dev, size, - &ring->dma_base, - GFP_KERNEL); + ring->cpu_base = dma_alloc_coherent(dma_dev, size, + &ring->dma_base, + GFP_KERNEL); if (!ring->cpu_base) { dev_err(bgmac->dev, "Allocation of RX ring 0x%X failed\n", ring->mmio_base); diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index bbb247116045..d63371d70bce 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -844,8 +844,8 @@ bnx2_alloc_stats_blk(struct net_device *dev) BNX2_SBLK_MSIX_ALIGN_SIZE); bp->status_stats_size = status_blk_size + sizeof(struct statistics_block); - status_blk = dma_zalloc_coherent(&bp->pdev->dev, bp->status_stats_size, - &bp->status_blk_mapping, GFP_KERNEL); + status_blk = dma_alloc_coherent(&bp->pdev->dev, bp->status_stats_size, + &bp->status_blk_mapping, GFP_KERNEL); if (!status_blk) return -ENOMEM; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 5cd3135dfe30..03d131f777bc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -2081,7 +2081,7 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id, bool is_pf); #define BNX2X_ILT_ZALLOC(x, y, size) \ - x = dma_zalloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL) + x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL) #define BNX2X_ILT_FREE(x, y, size) \ do { \ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 142bc11b9fbb..2462e7aa0c5d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -52,7 +52,7 @@ extern int bnx2x_num_queues; #define BNX2X_PCI_ALLOC(y, size) \ ({ \ - void *x = dma_zalloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \ + void *x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \ if (x) \ DP(NETIF_MSG_HW, \ "BNX2X_PCI_ALLOC: Physical %Lx Virtual %p\n", \ diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 3aa80da973d7..803f7990d32b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -500,6 +500,12 @@ normal_tx: } length >>= 9; + if (unlikely(length >= ARRAY_SIZE(bnxt_lhint_arr))) { + dev_warn_ratelimited(&pdev->dev, "Dropped oversize %d bytes TX packet.\n", + skb->len); + i = 0; + goto tx_dma_error; + } flags |= bnxt_lhint_arr[length]; txbd->tx_bd_len_flags_type = cpu_to_le32(flags); @@ -3449,10 +3455,10 @@ alloc_ext_stats: goto alloc_tx_ext_stats; bp->hw_rx_port_stats_ext = - dma_zalloc_coherent(&pdev->dev, - sizeof(struct rx_port_stats_ext), - &bp->hw_rx_port_stats_ext_map, - GFP_KERNEL); + dma_alloc_coherent(&pdev->dev, + sizeof(struct rx_port_stats_ext), + &bp->hw_rx_port_stats_ext_map, + GFP_KERNEL); if (!bp->hw_rx_port_stats_ext) return 0; @@ -3462,10 +3468,10 @@ alloc_tx_ext_stats: if (bp->hwrm_spec_code >= 0x10902) { bp->hw_tx_port_stats_ext = - dma_zalloc_coherent(&pdev->dev, - sizeof(struct tx_port_stats_ext), - &bp->hw_tx_port_stats_ext_map, - GFP_KERNEL); + dma_alloc_coherent(&pdev->dev, + sizeof(struct tx_port_stats_ext), + &bp->hw_tx_port_stats_ext_map, + GFP_KERNEL); } bp->flags |= BNXT_FLAG_PORT_STATS_EXT; } @@ -3903,7 +3909,7 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, if (len) break; /* on first few passes, just barely sleep */ - if (i < DFLT_HWRM_CMD_TIMEOUT) + if (i < HWRM_SHORT_TIMEOUT_COUNTER) usleep_range(HWRM_SHORT_MIN_TIMEOUT, HWRM_SHORT_MAX_TIMEOUT); else @@ -3926,7 +3932,7 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, dma_rmb(); if (*valid) break; - udelay(1); + usleep_range(1, 5); } if (j >= HWRM_VALID_BIT_DELAY_USEC) { @@ -4973,12 +4979,18 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp) struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; struct bnxt_ring_struct *ring = &cpr->cp_ring_struct; u32 map_idx = ring->map_idx; + unsigned int vector; + vector = bp->irq_tbl[map_idx].vector; + disable_irq_nosync(vector); rc = hwrm_ring_alloc_send_msg(bp, ring, type, map_idx); - if (rc) + if (rc) { + enable_irq(vector); goto err_out; + } bnxt_set_db(bp, &cpr->cp_db, type, map_idx, ring->fw_ring_id); bnxt_db_nq(bp, &cpr->cp_db, cpr->cp_raw_cons); + enable_irq(vector); bp->grp_info[i].cp_fw_ring_id = ring->fw_ring_id; if (!i) { @@ -5601,7 +5613,8 @@ static int bnxt_hwrm_check_pf_rings(struct bnxt *bp, int tx_rings, int rx_rings, FUNC_CFG_REQ_FLAGS_STAT_CTX_ASSETS_TEST | FUNC_CFG_REQ_FLAGS_VNIC_ASSETS_TEST; if (bp->flags & BNXT_FLAG_CHIP_P5) - flags |= FUNC_CFG_REQ_FLAGS_RSSCOS_CTX_ASSETS_TEST; + flags |= FUNC_CFG_REQ_FLAGS_RSSCOS_CTX_ASSETS_TEST | + FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST; else flags |= FUNC_CFG_REQ_FLAGS_RING_GRP_ASSETS_TEST; } @@ -6221,9 +6234,12 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt *bp, rmem->pg_tbl_map = ctx_pg->ctx_dma_arr[i]; rmem->depth = 1; rmem->nr_pages = MAX_CTX_PAGES; - if (i == (nr_tbls - 1)) - rmem->nr_pages = ctx_pg->nr_pages % - MAX_CTX_PAGES; + if (i == (nr_tbls - 1)) { + int rem = ctx_pg->nr_pages % MAX_CTX_PAGES; + + if (rem) + rmem->nr_pages = rem; + } rc = bnxt_alloc_ctx_mem_blk(bp, pg_tbl); if (rc) break; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index a451796deefe..2fb653e0048d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -582,7 +582,7 @@ struct nqe_cn { (HWRM_SHORT_TIMEOUT_COUNTER * HWRM_SHORT_MIN_TIMEOUT + \ ((n) - HWRM_SHORT_TIMEOUT_COUNTER) * HWRM_MIN_TIMEOUT)) -#define HWRM_VALID_BIT_DELAY_USEC 20 +#define HWRM_VALID_BIT_DELAY_USEC 150 #define BNXT_HWRM_CHNL_CHIMP 0 #define BNXT_HWRM_CHNL_KONG 1 diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c index 15c7041e937b..70775158c8c4 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c @@ -316,8 +316,8 @@ static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app, n = IEEE_8021QAZ_MAX_TCS; data_len = sizeof(*data) + sizeof(*fw_app) * n; - data = dma_zalloc_coherent(&bp->pdev->dev, data_len, &mapping, - GFP_KERNEL); + data = dma_alloc_coherent(&bp->pdev->dev, data_len, &mapping, + GFP_KERNEL); if (!data) return -ENOMEM; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c index 140dbd62106d..7f56032e44ac 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c @@ -85,8 +85,8 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg, return -EFAULT; } - data_addr = dma_zalloc_coherent(&bp->pdev->dev, bytesize, - &data_dma_addr, GFP_KERNEL); + data_addr = dma_alloc_coherent(&bp->pdev->dev, bytesize, + &data_dma_addr, GFP_KERNEL); if (!data_addr) return -ENOMEM; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h index f1aaac8e6268..0a0995894ddb 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h @@ -386,8 +386,8 @@ struct hwrm_err_output { #define HWRM_VERSION_MAJOR 1 #define HWRM_VERSION_MINOR 10 #define HWRM_VERSION_UPDATE 0 -#define HWRM_VERSION_RSVD 33 -#define HWRM_VERSION_STR "1.10.0.33" +#define HWRM_VERSION_RSVD 35 +#define HWRM_VERSION_STR "1.10.0.35" /* hwrm_ver_get_input (size:192b/24B) */ struct hwrm_ver_get_input { @@ -1184,6 +1184,7 @@ struct hwrm_func_cfg_input { #define FUNC_CFG_REQ_FLAGS_L2_CTX_ASSETS_TEST 0x100000UL #define FUNC_CFG_REQ_FLAGS_TRUSTED_VF_ENABLE 0x200000UL #define FUNC_CFG_REQ_FLAGS_DYNAMIC_TX_RING_ALLOC 0x400000UL + #define FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST 0x800000UL __le32 enables; #define FUNC_CFG_REQ_ENABLES_MTU 0x1UL #define FUNC_CFG_REQ_ENABLES_MRU 0x2UL diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c index 5db9f4158e62..134ae2862efa 100644 --- a/drivers/net/ethernet/broadcom/sb1250-mac.c +++ b/drivers/net/ethernet/broadcom/sb1250-mac.c @@ -1288,7 +1288,7 @@ static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d, * for transmits, we just free buffers. */ - dev_kfree_skb_irq(sb); + dev_consume_skb_irq(sb); /* * .. and advance to the next buffer. diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 3b1397af81f7..b1627dd5f2fd 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -8712,10 +8712,10 @@ static int tg3_mem_rx_acquire(struct tg3 *tp) if (!i && tg3_flag(tp, ENABLE_RSS)) continue; - tnapi->rx_rcb = dma_zalloc_coherent(&tp->pdev->dev, - TG3_RX_RCB_RING_BYTES(tp), - &tnapi->rx_rcb_mapping, - GFP_KERNEL); + tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev, + TG3_RX_RCB_RING_BYTES(tp), + &tnapi->rx_rcb_mapping, + GFP_KERNEL); if (!tnapi->rx_rcb) goto err_out; } @@ -8768,9 +8768,9 @@ static int tg3_alloc_consistent(struct tg3 *tp) { int i; - tp->hw_stats = dma_zalloc_coherent(&tp->pdev->dev, - sizeof(struct tg3_hw_stats), - &tp->stats_mapping, GFP_KERNEL); + tp->hw_stats = dma_alloc_coherent(&tp->pdev->dev, + sizeof(struct tg3_hw_stats), + &tp->stats_mapping, GFP_KERNEL); if (!tp->hw_stats) goto err_out; @@ -8778,10 +8778,10 @@ static int tg3_alloc_consistent(struct tg3 *tp) struct tg3_napi *tnapi = &tp->napi[i]; struct tg3_hw_status *sblk; - tnapi->hw_status = dma_zalloc_coherent(&tp->pdev->dev, - TG3_HW_STATUS_SIZE, - &tnapi->status_mapping, - GFP_KERNEL); + tnapi->hw_status = dma_alloc_coherent(&tp->pdev->dev, + TG3_HW_STATUS_SIZE, + &tnapi->status_mapping, + GFP_KERNEL); if (!tnapi->hw_status) goto err_out; diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 3d45f4c92cf6..9bbaad9f3d63 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -643,6 +643,7 @@ #define MACB_CAPS_JUMBO 0x00000020 #define MACB_CAPS_GEM_HAS_PTP 0x00000040 #define MACB_CAPS_BD_RD_PREFETCH 0x00000080 +#define MACB_CAPS_NEEDS_RSTONUBR 0x00000100 #define MACB_CAPS_FIFO_MODE 0x10000000 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000 #define MACB_CAPS_SG_DISABLED 0x40000000 @@ -1214,6 +1215,8 @@ struct macb { int rx_bd_rd_prefetch; int tx_bd_rd_prefetch; + + u32 rx_intr_mask; }; #ifdef CONFIG_MACB_USE_HWSTAMP diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index b126926ef7f5..2b2882615e8b 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -56,8 +56,7 @@ /* level of occupied TX descriptors under which we wake up TX process */ #define MACB_TX_WAKEUP_THRESH(bp) (3 * (bp)->tx_ring_size / 4) -#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \ - | MACB_BIT(ISR_ROVR)) +#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(ISR_ROVR)) #define MACB_TX_ERR_FLAGS (MACB_BIT(ISR_TUND) \ | MACB_BIT(ISR_RLE) \ | MACB_BIT(TXERR)) @@ -1270,7 +1269,7 @@ static int macb_poll(struct napi_struct *napi, int budget) queue_writel(queue, ISR, MACB_BIT(RCOMP)); napi_reschedule(napi); } else { - queue_writel(queue, IER, MACB_RX_INT_FLAGS); + queue_writel(queue, IER, bp->rx_intr_mask); } } @@ -1288,7 +1287,7 @@ static void macb_hresp_error_task(unsigned long data) u32 ctrl; for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { - queue_writel(queue, IDR, MACB_RX_INT_FLAGS | + queue_writel(queue, IDR, bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP)); } @@ -1318,7 +1317,7 @@ static void macb_hresp_error_task(unsigned long data) /* Enable interrupts */ queue_writel(queue, IER, - MACB_RX_INT_FLAGS | + bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP)); } @@ -1372,14 +1371,14 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) (unsigned int)(queue - bp->queues), (unsigned long)status); - if (status & MACB_RX_INT_FLAGS) { + if (status & bp->rx_intr_mask) { /* There's no point taking any more interrupts * until we have processed the buffers. The * scheduling call may fail if the poll routine * is already scheduled, so disable interrupts * now. */ - queue_writel(queue, IDR, MACB_RX_INT_FLAGS); + queue_writel(queue, IDR, bp->rx_intr_mask); if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) queue_writel(queue, ISR, MACB_BIT(RCOMP)); @@ -1412,8 +1411,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) /* There is a hardware issue under heavy load where DMA can * stop, this causes endless "used buffer descriptor read" * interrupts but it can be cleared by re-enabling RX. See - * the at91 manual, section 41.3.1 or the Zynq manual - * section 16.7.4 for details. + * the at91rm9200 manual, section 41.3.1 or the Zynq manual + * section 16.7.4 for details. RXUBR is only enabled for + * these two versions. */ if (status & MACB_BIT(RXUBR)) { ctrl = macb_readl(bp, NCR); @@ -1738,12 +1738,8 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev) *skb = nskb; } - if (padlen) { - if (padlen >= ETH_FCS_LEN) - skb_put_zero(*skb, padlen - ETH_FCS_LEN); - else - skb_trim(*skb, ETH_FCS_LEN - padlen); - } + if (padlen > ETH_FCS_LEN) + skb_put_zero(*skb, padlen - ETH_FCS_LEN); add_fcs: /* set FCS to packet */ @@ -2263,7 +2259,7 @@ static void macb_init_hw(struct macb *bp) /* Enable interrupts */ queue_writel(queue, IER, - MACB_RX_INT_FLAGS | + bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP)); } @@ -3911,6 +3907,7 @@ static const struct macb_config sama5d4_config = { }; static const struct macb_config emac_config = { + .caps = MACB_CAPS_NEEDS_RSTONUBR, .clk_init = at91ether_clk_init, .init = at91ether_init, }; @@ -3932,7 +3929,8 @@ static const struct macb_config zynqmp_config = { }; static const struct macb_config zynq_config = { - .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_NO_GIGABIT_HALF, + .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_NO_GIGABIT_HALF | + MACB_CAPS_NEEDS_RSTONUBR, .dma_burst_length = 16, .clk_init = macb_clk_init, .init = macb_init, @@ -4087,6 +4085,10 @@ static int macb_probe(struct platform_device *pdev) macb_dma_desc_get_size(bp); } + bp->rx_intr_mask = MACB_RX_INT_FLAGS; + if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR) + bp->rx_intr_mask |= MACB_BIT(RXUBR); + mac = of_get_mac_address(np); if (mac) { ether_addr_copy(bp->dev->dev_addr, mac); diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig index 5f03199a3acf..05f4a3b21e29 100644 --- a/drivers/net/ethernet/cavium/Kconfig +++ b/drivers/net/ethernet/cavium/Kconfig @@ -54,7 +54,6 @@ config CAVIUM_PTP tristate "Cavium PTP coprocessor as PTP clock" depends on 64BIT && PCI imply PTP_1588_CLOCK - default y ---help--- This driver adds support for the Precision Time Protocol Clocks and Timestamping coprocessor (PTP) found on Cavium processors. diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h index f4d81765221e..62636c1ed141 100644 --- a/drivers/net/ethernet/cavium/thunder/nic.h +++ b/drivers/net/ethernet/cavium/thunder/nic.h @@ -271,7 +271,7 @@ struct xcast_addr_list { }; struct nicvf_work { - struct delayed_work work; + struct work_struct work; u8 mode; struct xcast_addr_list *mc; }; @@ -327,7 +327,11 @@ struct nicvf { struct nicvf_work rx_mode_work; /* spinlock to protect workqueue arguments from concurrent access */ spinlock_t rx_mode_wq_lock; - + /* workqueue for handling kernel ndo_set_rx_mode() calls */ + struct workqueue_struct *nicvf_rx_mode_wq; + /* mutex to protect VF's mailbox contents from concurrent access */ + struct mutex rx_mode_mtx; + struct delayed_work link_change_work; /* PTP timestamp */ struct cavium_ptp *ptp_clock; /* Inbound timestamping is on */ @@ -575,10 +579,8 @@ struct set_ptp { struct xcast { u8 msg; - union { - u8 mode; - u64 mac; - } data; + u8 mode; + u64 mac:48; }; /* 128 bit shared memory between PF and each VF */ diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c index 6c8dcb65ff03..c90252829ed3 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_main.c +++ b/drivers/net/ethernet/cavium/thunder/nic_main.c @@ -57,14 +57,8 @@ struct nicpf { #define NIC_GET_BGX_FROM_VF_LMAC_MAP(map) ((map >> 4) & 0xF) #define NIC_GET_LMAC_FROM_VF_LMAC_MAP(map) (map & 0xF) u8 *vf_lmac_map; - struct delayed_work dwork; - struct workqueue_struct *check_link; - u8 *link; - u8 *duplex; - u32 *speed; u16 cpi_base[MAX_NUM_VFS_SUPPORTED]; u16 rssi_base[MAX_NUM_VFS_SUPPORTED]; - bool mbx_lock[MAX_NUM_VFS_SUPPORTED]; /* MSI-X */ u8 num_vec; @@ -929,6 +923,35 @@ static void nic_config_timestamp(struct nicpf *nic, int vf, struct set_ptp *ptp) nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3), pkind_val); } +/* Get BGX LMAC link status and update corresponding VF + * if there is a change, valid only if internal L2 switch + * is not present otherwise VF link is always treated as up + */ +static void nic_link_status_get(struct nicpf *nic, u8 vf) +{ + union nic_mbx mbx = {}; + struct bgx_link_status link; + u8 bgx, lmac; + + mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE; + + /* Get BGX, LMAC indices for the VF */ + bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); + lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); + + /* Get interface link status */ + bgx_get_lmac_link_state(nic->node, bgx, lmac, &link); + + /* Send a mbox message to VF with current link status */ + mbx.link_status.link_up = link.link_up; + mbx.link_status.duplex = link.duplex; + mbx.link_status.speed = link.speed; + mbx.link_status.mac_type = link.mac_type; + + /* reply with link status */ + nic_send_msg_to_vf(nic, vf, &mbx); +} + /* Interrupt handler to handle mailbox messages from VFs */ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) { @@ -941,8 +964,6 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) int i; int ret = 0; - nic->mbx_lock[vf] = true; - mbx_addr = nic_get_mbx_addr(vf); mbx_data = (u64 *)&mbx; @@ -957,12 +978,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) switch (mbx.msg.msg) { case NIC_MBOX_MSG_READY: nic_mbx_send_ready(nic, vf); - if (vf < nic->num_vf_en) { - nic->link[vf] = 0; - nic->duplex[vf] = 0; - nic->speed[vf] = 0; - } - goto unlock; + return; case NIC_MBOX_MSG_QS_CFG: reg_addr = NIC_PF_QSET_0_127_CFG | (mbx.qs.num << NIC_QS_ID_SHIFT); @@ -1031,7 +1047,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) break; case NIC_MBOX_MSG_RSS_SIZE: nic_send_rss_size(nic, vf); - goto unlock; + return; case NIC_MBOX_MSG_RSS_CFG: case NIC_MBOX_MSG_RSS_CFG_CONT: nic_config_rss(nic, &mbx.rss_cfg); @@ -1039,7 +1055,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) case NIC_MBOX_MSG_CFG_DONE: /* Last message of VF config msg sequence */ nic_enable_vf(nic, vf, true); - goto unlock; + break; case NIC_MBOX_MSG_SHUTDOWN: /* First msg in VF teardown sequence */ if (vf >= nic->num_vf_en) @@ -1049,19 +1065,19 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) break; case NIC_MBOX_MSG_ALLOC_SQS: nic_alloc_sqs(nic, &mbx.sqs_alloc); - goto unlock; + return; case NIC_MBOX_MSG_NICVF_PTR: nic->nicvf[vf] = mbx.nicvf.nicvf; break; case NIC_MBOX_MSG_PNICVF_PTR: nic_send_pnicvf(nic, vf); - goto unlock; + return; case NIC_MBOX_MSG_SNICVF_PTR: nic_send_snicvf(nic, &mbx.nicvf); - goto unlock; + return; case NIC_MBOX_MSG_BGX_STATS: nic_get_bgx_stats(nic, &mbx.bgx_stats); - goto unlock; + return; case NIC_MBOX_MSG_LOOPBACK: ret = nic_config_loopback(nic, &mbx.lbk); break; @@ -1070,7 +1086,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) break; case NIC_MBOX_MSG_PFC: nic_pause_frame(nic, vf, &mbx.pfc); - goto unlock; + return; case NIC_MBOX_MSG_PTP_CFG: nic_config_timestamp(nic, vf, &mbx.ptp); break; @@ -1094,7 +1110,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); bgx_set_dmac_cam_filter(nic->node, bgx, lmac, - mbx.xcast.data.mac, + mbx.xcast.mac, vf < NIC_VF_PER_MBX_REG ? vf : vf - NIC_VF_PER_MBX_REG); break; @@ -1106,8 +1122,15 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) } bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); - bgx_set_xcast_mode(nic->node, bgx, lmac, mbx.xcast.data.mode); + bgx_set_xcast_mode(nic->node, bgx, lmac, mbx.xcast.mode); break; + case NIC_MBOX_MSG_BGX_LINK_CHANGE: + if (vf >= nic->num_vf_en) { + ret = -1; /* NACK */ + break; + } + nic_link_status_get(nic, vf); + return; default: dev_err(&nic->pdev->dev, "Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg); @@ -1121,8 +1144,6 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) mbx.msg.msg, vf); nic_mbx_send_nack(nic, vf); } -unlock: - nic->mbx_lock[vf] = false; } static irqreturn_t nic_mbx_intr_handler(int irq, void *nic_irq) @@ -1270,52 +1291,6 @@ static int nic_sriov_init(struct pci_dev *pdev, struct nicpf *nic) return 0; } -/* Poll for BGX LMAC link status and update corresponding VF - * if there is a change, valid only if internal L2 switch - * is not present otherwise VF link is always treated as up - */ -static void nic_poll_for_link(struct work_struct *work) -{ - union nic_mbx mbx = {}; - struct nicpf *nic; - struct bgx_link_status link; - u8 vf, bgx, lmac; - - nic = container_of(work, struct nicpf, dwork.work); - - mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE; - - for (vf = 0; vf < nic->num_vf_en; vf++) { - /* Poll only if VF is UP */ - if (!nic->vf_enabled[vf]) - continue; - - /* Get BGX, LMAC indices for the VF */ - bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); - lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); - /* Get interface link status */ - bgx_get_lmac_link_state(nic->node, bgx, lmac, &link); - - /* Inform VF only if link status changed */ - if (nic->link[vf] == link.link_up) - continue; - - if (!nic->mbx_lock[vf]) { - nic->link[vf] = link.link_up; - nic->duplex[vf] = link.duplex; - nic->speed[vf] = link.speed; - - /* Send a mbox message to VF with current link status */ - mbx.link_status.link_up = link.link_up; - mbx.link_status.duplex = link.duplex; - mbx.link_status.speed = link.speed; - mbx.link_status.mac_type = link.mac_type; - nic_send_msg_to_vf(nic, vf, &mbx); - } - } - queue_delayed_work(nic->check_link, &nic->dwork, HZ * 2); -} - static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct device *dev = &pdev->dev; @@ -1384,18 +1359,6 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (!nic->vf_lmac_map) goto err_release_regions; - nic->link = devm_kmalloc_array(dev, max_lmac, sizeof(u8), GFP_KERNEL); - if (!nic->link) - goto err_release_regions; - - nic->duplex = devm_kmalloc_array(dev, max_lmac, sizeof(u8), GFP_KERNEL); - if (!nic->duplex) - goto err_release_regions; - - nic->speed = devm_kmalloc_array(dev, max_lmac, sizeof(u32), GFP_KERNEL); - if (!nic->speed) - goto err_release_regions; - /* Initialize hardware */ nic_init_hw(nic); @@ -1411,22 +1374,8 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto err_unregister_interrupts; - /* Register a physical link status poll fn() */ - nic->check_link = alloc_workqueue("check_link_status", - WQ_UNBOUND | WQ_MEM_RECLAIM, 1); - if (!nic->check_link) { - err = -ENOMEM; - goto err_disable_sriov; - } - - INIT_DELAYED_WORK(&nic->dwork, nic_poll_for_link); - queue_delayed_work(nic->check_link, &nic->dwork, 0); - return 0; -err_disable_sriov: - if (nic->flags & NIC_SRIOV_ENABLED) - pci_disable_sriov(pdev); err_unregister_interrupts: nic_unregister_interrupts(nic); err_release_regions: @@ -1447,12 +1396,6 @@ static void nic_remove(struct pci_dev *pdev) if (nic->flags & NIC_SRIOV_ENABLED) pci_disable_sriov(pdev); - if (nic->check_link) { - /* Destroy work Queue */ - cancel_delayed_work_sync(&nic->dwork); - destroy_workqueue(nic->check_link); - } - nic_unregister_interrupts(nic); pci_release_regions(pdev); diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index 88f8a8fa93cd..503cfadff4ac 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -68,9 +68,6 @@ module_param(cpi_alg, int, 0444); MODULE_PARM_DESC(cpi_alg, "PFC algorithm (0=none, 1=VLAN, 2=VLAN16, 3=IP Diffserv)"); -/* workqueue for handling kernel ndo_set_rx_mode() calls */ -static struct workqueue_struct *nicvf_rx_mode_wq; - static inline u8 nicvf_netdev_qidx(struct nicvf *nic, u8 qidx) { if (nic->sqs_mode) @@ -127,6 +124,9 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx *mbx) { int timeout = NIC_MBOX_MSG_TIMEOUT; int sleep = 10; + int ret = 0; + + mutex_lock(&nic->rx_mode_mtx); nic->pf_acked = false; nic->pf_nacked = false; @@ -139,7 +139,8 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx *mbx) netdev_err(nic->netdev, "PF NACK to mbox msg 0x%02x from VF%d\n", (mbx->msg.msg & 0xFF), nic->vf_id); - return -EINVAL; + ret = -EINVAL; + break; } msleep(sleep); if (nic->pf_acked) @@ -149,10 +150,12 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx *mbx) netdev_err(nic->netdev, "PF didn't ACK to mbox msg 0x%02x from VF%d\n", (mbx->msg.msg & 0xFF), nic->vf_id); - return -EBUSY; + ret = -EBUSY; + break; } } - return 0; + mutex_unlock(&nic->rx_mode_mtx); + return ret; } /* Checks if VF is able to comminicate with PF @@ -172,6 +175,17 @@ static int nicvf_check_pf_ready(struct nicvf *nic) return 1; } +static void nicvf_send_cfg_done(struct nicvf *nic) +{ + union nic_mbx mbx = {}; + + mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE; + if (nicvf_send_msg_to_pf(nic, &mbx)) { + netdev_err(nic->netdev, + "PF didn't respond to CFG DONE msg\n"); + } +} + static void nicvf_read_bgx_stats(struct nicvf *nic, struct bgx_stats_msg *bgx) { if (bgx->rx) @@ -228,21 +242,24 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic) break; case NIC_MBOX_MSG_BGX_LINK_CHANGE: nic->pf_acked = true; - nic->link_up = mbx.link_status.link_up; - nic->duplex = mbx.link_status.duplex; - nic->speed = mbx.link_status.speed; - nic->mac_type = mbx.link_status.mac_type; - if (nic->link_up) { - netdev_info(nic->netdev, "Link is Up %d Mbps %s duplex\n", - nic->speed, - nic->duplex == DUPLEX_FULL ? - "Full" : "Half"); - netif_carrier_on(nic->netdev); - netif_tx_start_all_queues(nic->netdev); - } else { - netdev_info(nic->netdev, "Link is Down\n"); - netif_carrier_off(nic->netdev); - netif_tx_stop_all_queues(nic->netdev); + if (nic->link_up != mbx.link_status.link_up) { + nic->link_up = mbx.link_status.link_up; + nic->duplex = mbx.link_status.duplex; + nic->speed = mbx.link_status.speed; + nic->mac_type = mbx.link_status.mac_type; + if (nic->link_up) { + netdev_info(nic->netdev, + "Link is Up %d Mbps %s duplex\n", + nic->speed, + nic->duplex == DUPLEX_FULL ? + "Full" : "Half"); + netif_carrier_on(nic->netdev); + netif_tx_start_all_queues(nic->netdev); + } else { + netdev_info(nic->netdev, "Link is Down\n"); + netif_carrier_off(nic->netdev); + netif_tx_stop_all_queues(nic->netdev); + } } break; case NIC_MBOX_MSG_ALLOC_SQS: @@ -1311,6 +1328,11 @@ int nicvf_stop(struct net_device *netdev) struct nicvf_cq_poll *cq_poll = NULL; union nic_mbx mbx = {}; + cancel_delayed_work_sync(&nic->link_change_work); + + /* wait till all queued set_rx_mode tasks completes */ + drain_workqueue(nic->nicvf_rx_mode_wq); + mbx.msg.msg = NIC_MBOX_MSG_SHUTDOWN; nicvf_send_msg_to_pf(nic, &mbx); @@ -1410,13 +1432,27 @@ static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu) return nicvf_send_msg_to_pf(nic, &mbx); } +static void nicvf_link_status_check_task(struct work_struct *work_arg) +{ + struct nicvf *nic = container_of(work_arg, + struct nicvf, + link_change_work.work); + union nic_mbx mbx = {}; + mbx.msg.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE; + nicvf_send_msg_to_pf(nic, &mbx); + queue_delayed_work(nic->nicvf_rx_mode_wq, + &nic->link_change_work, 2 * HZ); +} + int nicvf_open(struct net_device *netdev) { int cpu, err, qidx; struct nicvf *nic = netdev_priv(netdev); struct queue_set *qs = nic->qs; struct nicvf_cq_poll *cq_poll = NULL; - union nic_mbx mbx = {}; + + /* wait till all queued set_rx_mode tasks completes if any */ + drain_workqueue(nic->nicvf_rx_mode_wq); netif_carrier_off(netdev); @@ -1512,8 +1548,12 @@ int nicvf_open(struct net_device *netdev) nicvf_enable_intr(nic, NICVF_INTR_RBDR, qidx); /* Send VF config done msg to PF */ - mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE; - nicvf_write_to_mbx(nic, &mbx); + nicvf_send_cfg_done(nic); + + INIT_DELAYED_WORK(&nic->link_change_work, + nicvf_link_status_check_task); + queue_delayed_work(nic->nicvf_rx_mode_wq, + &nic->link_change_work, 0); return 0; cleanup: @@ -1941,15 +1981,17 @@ static void __nicvf_set_rx_mode_task(u8 mode, struct xcast_addr_list *mc_addrs, /* flush DMAC filters and reset RX mode */ mbx.xcast.msg = NIC_MBOX_MSG_RESET_XCAST; - nicvf_send_msg_to_pf(nic, &mbx); + if (nicvf_send_msg_to_pf(nic, &mbx) < 0) + goto free_mc; if (mode & BGX_XCAST_MCAST_FILTER) { /* once enabling filtering, we need to signal to PF to add * its' own LMAC to the filter to accept packets for it. */ mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST; - mbx.xcast.data.mac = 0; - nicvf_send_msg_to_pf(nic, &mbx); + mbx.xcast.mac = 0; + if (nicvf_send_msg_to_pf(nic, &mbx) < 0) + goto free_mc; } /* check if we have any specific MACs to be added to PF DMAC filter */ @@ -1957,23 +1999,25 @@ static void __nicvf_set_rx_mode_task(u8 mode, struct xcast_addr_list *mc_addrs, /* now go through kernel list of MACs and add them one by one */ for (idx = 0; idx < mc_addrs->count; idx++) { mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST; - mbx.xcast.data.mac = mc_addrs->mc[idx]; - nicvf_send_msg_to_pf(nic, &mbx); + mbx.xcast.mac = mc_addrs->mc[idx]; + if (nicvf_send_msg_to_pf(nic, &mbx) < 0) + goto free_mc; } - kfree(mc_addrs); } /* and finally set rx mode for PF accordingly */ mbx.xcast.msg = NIC_MBOX_MSG_SET_XCAST; - mbx.xcast.data.mode = mode; + mbx.xcast.mode = mode; nicvf_send_msg_to_pf(nic, &mbx); +free_mc: + kfree(mc_addrs); } static void nicvf_set_rx_mode_task(struct work_struct *work_arg) { struct nicvf_work *vf_work = container_of(work_arg, struct nicvf_work, - work.work); + work); struct nicvf *nic = container_of(vf_work, struct nicvf, rx_mode_work); u8 mode; struct xcast_addr_list *mc; @@ -2030,7 +2074,7 @@ static void nicvf_set_rx_mode(struct net_device *netdev) kfree(nic->rx_mode_work.mc); nic->rx_mode_work.mc = mc_list; nic->rx_mode_work.mode = mode; - queue_delayed_work(nicvf_rx_mode_wq, &nic->rx_mode_work.work, 0); + queue_work(nic->nicvf_rx_mode_wq, &nic->rx_mode_work.work); spin_unlock(&nic->rx_mode_wq_lock); } @@ -2187,8 +2231,12 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) INIT_WORK(&nic->reset_task, nicvf_reset_task); - INIT_DELAYED_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task); + nic->nicvf_rx_mode_wq = alloc_ordered_workqueue("nicvf_rx_mode_wq_VF%d", + WQ_MEM_RECLAIM, + nic->vf_id); + INIT_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task); spin_lock_init(&nic->rx_mode_wq_lock); + mutex_init(&nic->rx_mode_mtx); err = register_netdev(netdev); if (err) { @@ -2228,13 +2276,15 @@ static void nicvf_remove(struct pci_dev *pdev) nic = netdev_priv(netdev); pnetdev = nic->pnicvf->netdev; - cancel_delayed_work_sync(&nic->rx_mode_work.work); - /* Check if this Qset is assigned to different VF. * If yes, clean primary and all secondary Qsets. */ if (pnetdev && (pnetdev->reg_state == NETREG_REGISTERED)) unregister_netdev(pnetdev); + if (nic->nicvf_rx_mode_wq) { + destroy_workqueue(nic->nicvf_rx_mode_wq); + nic->nicvf_rx_mode_wq = NULL; + } nicvf_unregister_interrupts(nic); pci_set_drvdata(pdev, NULL); if (nic->drv_stats) @@ -2261,17 +2311,11 @@ static struct pci_driver nicvf_driver = { static int __init nicvf_init_module(void) { pr_info("%s, ver %s\n", DRV_NAME, DRV_VERSION); - nicvf_rx_mode_wq = alloc_ordered_workqueue("nicvf_generic", - WQ_MEM_RECLAIM); return pci_register_driver(&nicvf_driver); } static void __exit nicvf_cleanup_module(void) { - if (nicvf_rx_mode_wq) { - destroy_workqueue(nicvf_rx_mode_wq); - nicvf_rx_mode_wq = NULL; - } pci_unregister_driver(&nicvf_driver); } diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index fcaf18fa3904..5b4d3badcb73 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -59,7 +59,7 @@ static int nicvf_alloc_q_desc_mem(struct nicvf *nic, struct q_desc_mem *dmem, dmem->q_len = q_len; dmem->size = (desc_size * q_len) + align_bytes; /* Save address, need it while freeing */ - dmem->unalign_base = dma_zalloc_coherent(&nic->pdev->dev, dmem->size, + dmem->unalign_base = dma_alloc_coherent(&nic->pdev->dev, dmem->size, &dmem->dma, GFP_KERNEL); if (!dmem->unalign_base) return -ENOMEM; diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index e337da6ba2a4..673c57b8023f 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -1217,7 +1217,7 @@ static void bgx_init_hw(struct bgx *bgx) /* Disable MAC steering (NCSI traffic) */ for (i = 0; i < RX_TRAFFIC_STEER_RULE_COUNT; i++) - bgx_reg_write(bgx, 0, BGX_CMR_RX_STREERING + (i * 8), 0x00); + bgx_reg_write(bgx, 0, BGX_CMR_RX_STEERING + (i * 8), 0x00); } static u8 bgx_get_lane2sds_cfg(struct bgx *bgx, struct lmac *lmac) diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h index cbdd20b9ee6f..5cbc54e9eb19 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h @@ -60,7 +60,7 @@ #define RX_DMACX_CAM_EN BIT_ULL(48) #define RX_DMACX_CAM_LMACID(x) (((u64)x) << 49) #define RX_DMAC_COUNT 32 -#define BGX_CMR_RX_STREERING 0x300 +#define BGX_CMR_RX_STEERING 0x300 #define RX_TRAFFIC_STEER_RULE_COUNT 8 #define BGX_CMR_CHAN_MSK_AND 0x450 #define BGX_CMR_BIST_STATUS 0x460 diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index 20b6e1b3f5e3..89db739b7819 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -620,7 +620,7 @@ static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size, { size_t len = nelem * elem_size; void *s = NULL; - void *p = dma_zalloc_coherent(&pdev->dev, len, phys, GFP_KERNEL); + void *p = dma_alloc_coherent(&pdev->dev, len, phys, GFP_KERNEL); if (!p) return NULL; @@ -2381,7 +2381,7 @@ no_mem: lro_add_page(adap, qs, fl, G_RSPD_LEN(len), flags & F_RSPD_EOP); - goto next_fl; + goto next_fl; } skb = get_packet_pg(adap, fl, q, @@ -3214,11 +3214,13 @@ void t3_start_sge_timers(struct adapter *adap) for (i = 0; i < SGE_QSETS; ++i) { struct sge_qset *q = &adap->sge.qs[i]; - if (q->tx_reclaim_timer.function) - mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); + if (q->tx_reclaim_timer.function) + mod_timer(&q->tx_reclaim_timer, + jiffies + TX_RECLAIM_PERIOD); - if (q->rx_reclaim_timer.function) - mod_timer(&q->rx_reclaim_timer, jiffies + RX_RECLAIM_PERIOD); + if (q->rx_reclaim_timer.function) + mod_timer(&q->rx_reclaim_timer, + jiffies + RX_RECLAIM_PERIOD); } } diff --git a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c index 080918af773c..0a9f2c596624 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c @@ -1082,7 +1082,7 @@ int t3_check_fw_version(struct adapter *adapter) CH_WARN(adapter, "found newer FW version(%u.%u), " "driver compiled for version %u.%u\n", major, minor, FW_VERSION_MAJOR, FW_VERSION_MINOR); - return 0; + return 0; } return -EINVAL; } @@ -3619,7 +3619,7 @@ int t3_reset_adapter(struct adapter *adapter) static int init_parity(struct adapter *adap) { - int i, err, addr; + int i, err, addr; if (t3_read_reg(adap, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) return -EBUSY; @@ -3806,6 +3806,6 @@ int t3_replay_prep_adapter(struct adapter *adapter) p->phy.ops->power_down(&p->phy, 1); } -return 0; + return 0; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c index 9f9d6cae39d5..58a039c3224a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c @@ -378,10 +378,10 @@ static void cxgb4_init_ptp_timer(struct adapter *adapter) int err; memset(&c, 0, sizeof(c)); - c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PTP_CMD) | - FW_CMD_REQUEST_F | - FW_CMD_WRITE_F | - FW_PTP_CMD_PORTID_V(0)); + c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PTP_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | + FW_PTP_CMD_PORTID_V(0)); c.retval_len16 = cpu_to_be32(FW_CMD_LEN16_V(sizeof(c) / 16)); c.u.scmd.sc = FW_PTP_SC_INIT_TIMER; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c index 9a6065a3fa46..b3654598a2d5 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c @@ -78,7 +78,7 @@ static void free_msix_idx_in_bmap(struct adapter *adap, unsigned int msix_idx) unsigned long flags; spin_lock_irqsave(&bmap->lock, flags); - __clear_bit(msix_idx, bmap->msix_bmap); + __clear_bit(msix_idx, bmap->msix_bmap); spin_unlock_irqrestore(&bmap->lock, flags); } @@ -660,6 +660,7 @@ static void uld_init(struct adapter *adap, struct cxgb4_lld_info *lld) lld->cclk_ps = 1000000000 / adap->params.vpd.cclk; lld->udb_density = 1 << adap->params.sge.eq_qpp; lld->ucq_density = 1 << adap->params.sge.iq_qpp; + lld->sge_host_page_size = 1 << (adap->params.sge.hps + 10); lld->filt_mode = adap->params.tp.vlan_pri_map; /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */ for (i = 0; i < NCHAN; i++) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 5fa9a2d5fc4b..21da34a4ca24 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -336,6 +336,7 @@ struct cxgb4_lld_info { unsigned int cclk_ps; /* Core clock period in psec */ unsigned short udb_density; /* # of user DB/page */ unsigned short ucq_density; /* # of user CQs/page */ + unsigned int sge_host_page_size; /* SGE host page size */ unsigned short filt_mode; /* filter optional components */ unsigned short tx_modq[NCHAN]; /* maps each tx channel to a */ /* scheduler queue */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index b90188401d4a..fc0bc6458e84 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -694,7 +694,7 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size, { size_t len = nelem * elem_size + stat_size; void *s = NULL; - void *p = dma_zalloc_coherent(dev, len, phys, GFP_KERNEL); + void *p = dma_alloc_coherent(dev, len, phys, GFP_KERNEL); if (!p) return NULL; diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index e8c34292a0ec..2b03f6187a24 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -3794,7 +3794,7 @@ int t4_load_phy_fw(struct adapter *adap, /* If we have version number support, then check to see if the adapter * already has up-to-date PHY firmware loaded. */ - if (phy_fw_version) { + if (phy_fw_version) { new_phy_fw_vers = phy_fw_version(phy_fw_data, phy_fw_size); ret = t4_phy_fw_ver(adap, &cur_phy_fw_ver); if (ret < 0) diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c index 3007e1ac1e61..1d534f0baa69 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c @@ -756,7 +756,7 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t hwsize, * Allocate the hardware ring and PCI DMA bus address space for said. */ size_t hwlen = nelem * hwsize + stat_size; - void *hwring = dma_zalloc_coherent(dev, hwlen, busaddrp, GFP_KERNEL); + void *hwring = dma_alloc_coherent(dev, hwlen, busaddrp, GFP_KERNEL); if (!hwring) return NULL; diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 60641e202534..9a7f70db20c7 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1434,7 +1434,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, * csum is correct or is zero. */ if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc && - tcp_udp_csum_ok && ipv4_csum_ok && outer_csum_ok) { + tcp_udp_csum_ok && outer_csum_ok && + (ipv4_csum_ok || ipv6)) { skb->ip_summed = CHECKSUM_UNNECESSARY; skb->csum_level = encap; } diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c index 13430f75496c..f1a2da15dd0a 100644 --- a/drivers/net/ethernet/dec/tulip/de2104x.c +++ b/drivers/net/ethernet/dec/tulip/de2104x.c @@ -585,7 +585,7 @@ static void de_tx (struct de_private *de) netif_dbg(de, tx_done, de->dev, "tx done, slot %d\n", tx_tail); } - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); } next: diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 1e9d882c04ef..59a7f0b99069 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1808,9 +1808,9 @@ int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf) total_size = buf_len; get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024; - get_fat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, - get_fat_cmd.size, - &get_fat_cmd.dma, GFP_ATOMIC); + get_fat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, + get_fat_cmd.size, + &get_fat_cmd.dma, GFP_ATOMIC); if (!get_fat_cmd.va) return -ENOMEM; @@ -2302,8 +2302,8 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter, return -EINVAL; cmd.size = sizeof(struct be_cmd_resp_port_type); - cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, - GFP_ATOMIC); + cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, + GFP_ATOMIC); if (!cmd.va) { dev_err(&adapter->pdev->dev, "Memory allocation failed\n"); return -ENOMEM; @@ -3066,8 +3066,8 @@ int lancer_fw_download(struct be_adapter *adapter, flash_cmd.size = sizeof(struct lancer_cmd_req_write_object) + LANCER_FW_DOWNLOAD_CHUNK; - flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, - &flash_cmd.dma, GFP_KERNEL); + flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma, + GFP_KERNEL); if (!flash_cmd.va) return -ENOMEM; @@ -3184,8 +3184,8 @@ int be_fw_download(struct be_adapter *adapter, const struct firmware *fw) } flash_cmd.size = sizeof(struct be_cmd_write_flashrom); - flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, &flash_cmd.dma, - GFP_KERNEL); + flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma, + GFP_KERNEL); if (!flash_cmd.va) return -ENOMEM; @@ -3435,8 +3435,8 @@ int be_cmd_get_phy_info(struct be_adapter *adapter) goto err; } cmd.size = sizeof(struct be_cmd_req_get_phy_info); - cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, - GFP_ATOMIC); + cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, + GFP_ATOMIC); if (!cmd.va) { dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); status = -ENOMEM; @@ -3522,9 +3522,9 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter) memset(&attribs_cmd, 0, sizeof(struct be_dma_mem)); attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs); - attribs_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, - attribs_cmd.size, - &attribs_cmd.dma, GFP_ATOMIC); + attribs_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, + attribs_cmd.size, + &attribs_cmd.dma, GFP_ATOMIC); if (!attribs_cmd.va) { dev_err(&adapter->pdev->dev, "Memory allocation failure\n"); status = -ENOMEM; @@ -3699,10 +3699,10 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem)); get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list); - get_mac_list_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, - get_mac_list_cmd.size, - &get_mac_list_cmd.dma, - GFP_ATOMIC); + get_mac_list_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, + get_mac_list_cmd.size, + &get_mac_list_cmd.dma, + GFP_ATOMIC); if (!get_mac_list_cmd.va) { dev_err(&adapter->pdev->dev, @@ -3829,8 +3829,8 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, memset(&cmd, 0, sizeof(struct be_dma_mem)); cmd.size = sizeof(struct be_cmd_req_set_mac_list); - cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, - GFP_KERNEL); + cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, + GFP_KERNEL); if (!cmd.va) return -ENOMEM; @@ -4035,8 +4035,8 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter) memset(&cmd, 0, sizeof(struct be_dma_mem)); cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1); - cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, - GFP_ATOMIC); + cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, + GFP_ATOMIC); if (!cmd.va) { dev_err(&adapter->pdev->dev, "Memory allocation failure\n"); status = -ENOMEM; @@ -4089,9 +4089,9 @@ int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level) memset(&extfat_cmd, 0, sizeof(struct be_dma_mem)); extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps); - extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, - extfat_cmd.size, &extfat_cmd.dma, - GFP_ATOMIC); + extfat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, + extfat_cmd.size, &extfat_cmd.dma, + GFP_ATOMIC); if (!extfat_cmd.va) return -ENOMEM; @@ -4127,9 +4127,9 @@ int be_cmd_get_fw_log_level(struct be_adapter *adapter) memset(&extfat_cmd, 0, sizeof(struct be_dma_mem)); extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps); - extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, - extfat_cmd.size, &extfat_cmd.dma, - GFP_ATOMIC); + extfat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, + extfat_cmd.size, &extfat_cmd.dma, + GFP_ATOMIC); if (!extfat_cmd.va) { dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n", @@ -4354,8 +4354,8 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res) memset(&cmd, 0, sizeof(struct be_dma_mem)); cmd.size = sizeof(struct be_cmd_resp_get_func_config); - cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, - GFP_ATOMIC); + cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, + GFP_ATOMIC); if (!cmd.va) { dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); status = -ENOMEM; @@ -4452,8 +4452,8 @@ int be_cmd_get_profile_config(struct be_adapter *adapter, memset(&cmd, 0, sizeof(struct be_dma_mem)); cmd.size = sizeof(struct be_cmd_resp_get_profile_config); - cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, - GFP_ATOMIC); + cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, + GFP_ATOMIC); if (!cmd.va) return -ENOMEM; @@ -4539,8 +4539,8 @@ static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc, memset(&cmd, 0, sizeof(struct be_dma_mem)); cmd.size = sizeof(struct be_cmd_req_set_profile_config); - cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, - GFP_ATOMIC); + cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, + GFP_ATOMIC); if (!cmd.va) return -ENOMEM; diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 3f6749fc889f..4c218341c51b 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -274,8 +274,8 @@ static int lancer_cmd_read_file(struct be_adapter *adapter, u8 *file_name, int status = 0; read_cmd.size = LANCER_READ_FILE_CHUNK; - read_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, read_cmd.size, - &read_cmd.dma, GFP_ATOMIC); + read_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, read_cmd.size, + &read_cmd.dma, GFP_ATOMIC); if (!read_cmd.va) { dev_err(&adapter->pdev->dev, @@ -815,7 +815,7 @@ static int be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) } cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config); - cmd.va = dma_zalloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL); + cmd.va = dma_alloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL); if (!cmd.va) return -ENOMEM; @@ -851,9 +851,9 @@ static int be_test_ddr_dma(struct be_adapter *adapter) }; ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test); - ddrdma_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, - ddrdma_cmd.size, &ddrdma_cmd.dma, - GFP_KERNEL); + ddrdma_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, + ddrdma_cmd.size, &ddrdma_cmd.dma, + GFP_KERNEL); if (!ddrdma_cmd.va) return -ENOMEM; @@ -1014,9 +1014,9 @@ static int be_read_eeprom(struct net_device *netdev, memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem)); eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read); - eeprom_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, - eeprom_cmd.size, &eeprom_cmd.dma, - GFP_KERNEL); + eeprom_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, + eeprom_cmd.size, &eeprom_cmd.dma, + GFP_KERNEL); if (!eeprom_cmd.va) return -ENOMEM; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 852f5bfe5f6d..d5026909dec5 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -167,8 +167,8 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q, q->len = len; q->entry_size = entry_size; mem->size = len * entry_size; - mem->va = dma_zalloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma, - GFP_KERNEL); + mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size, + &mem->dma, GFP_KERNEL); if (!mem->va) return -ENOMEM; return 0; @@ -5766,9 +5766,9 @@ static int be_drv_init(struct be_adapter *adapter) int status = 0; mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16; - mbox_mem_alloc->va = dma_zalloc_coherent(dev, mbox_mem_alloc->size, - &mbox_mem_alloc->dma, - GFP_KERNEL); + mbox_mem_alloc->va = dma_alloc_coherent(dev, mbox_mem_alloc->size, + &mbox_mem_alloc->dma, + GFP_KERNEL); if (!mbox_mem_alloc->va) return -ENOMEM; @@ -5777,8 +5777,8 @@ static int be_drv_init(struct be_adapter *adapter) mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); rx_filter->size = sizeof(struct be_cmd_req_rx_filter); - rx_filter->va = dma_zalloc_coherent(dev, rx_filter->size, - &rx_filter->dma, GFP_KERNEL); + rx_filter->va = dma_alloc_coherent(dev, rx_filter->size, + &rx_filter->dma, GFP_KERNEL); if (!rx_filter->va) { status = -ENOMEM; goto free_mbox; @@ -5792,8 +5792,8 @@ static int be_drv_init(struct be_adapter *adapter) stats_cmd->size = sizeof(struct be_cmd_req_get_stats_v1); else stats_cmd->size = sizeof(struct be_cmd_req_get_stats_v2); - stats_cmd->va = dma_zalloc_coherent(dev, stats_cmd->size, - &stats_cmd->dma, GFP_KERNEL); + stats_cmd->va = dma_alloc_coherent(dev, stats_cmd->size, + &stats_cmd->dma, GFP_KERNEL); if (!stats_cmd->va) { status = -ENOMEM; goto free_rx_filter; diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index 4d673225ed3e..3e5e97186fc4 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -935,16 +935,14 @@ static int ftgmac100_alloc_rings(struct ftgmac100 *priv) return -ENOMEM; /* Allocate descriptors */ - priv->rxdes = dma_zalloc_coherent(priv->dev, - MAX_RX_QUEUE_ENTRIES * - sizeof(struct ftgmac100_rxdes), - &priv->rxdes_dma, GFP_KERNEL); + priv->rxdes = dma_alloc_coherent(priv->dev, + MAX_RX_QUEUE_ENTRIES * sizeof(struct ftgmac100_rxdes), + &priv->rxdes_dma, GFP_KERNEL); if (!priv->rxdes) return -ENOMEM; - priv->txdes = dma_zalloc_coherent(priv->dev, - MAX_TX_QUEUE_ENTRIES * - sizeof(struct ftgmac100_txdes), - &priv->txdes_dma, GFP_KERNEL); + priv->txdes = dma_alloc_coherent(priv->dev, + MAX_TX_QUEUE_ENTRIES * sizeof(struct ftgmac100_txdes), + &priv->txdes_dma, GFP_KERNEL); if (!priv->txdes) return -ENOMEM; diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c index 084f24daf2b5..2a0e820526dc 100644 --- a/drivers/net/ethernet/faraday/ftmac100.c +++ b/drivers/net/ethernet/faraday/ftmac100.c @@ -734,10 +734,9 @@ static int ftmac100_alloc_buffers(struct ftmac100 *priv) { int i; - priv->descs = dma_zalloc_coherent(priv->dev, - sizeof(struct ftmac100_descs), - &priv->descs_dma_addr, - GFP_KERNEL); + priv->descs = dma_alloc_coherent(priv->dev, + sizeof(struct ftmac100_descs), + &priv->descs_dma_addr, GFP_KERNEL); if (!priv->descs) return -ENOMEM; diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index f53090cde041..dfebc30c4841 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -2051,6 +2051,7 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev) bool nonlinear = skb_is_nonlinear(skb); struct rtnl_link_stats64 *percpu_stats; struct dpaa_percpu_priv *percpu_priv; + struct netdev_queue *txq; struct dpaa_priv *priv; struct qm_fd fd; int offset = 0; @@ -2100,6 +2101,11 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev) if (unlikely(err < 0)) goto skb_to_fd_failed; + txq = netdev_get_tx_queue(net_dev, queue_mapping); + + /* LLTX requires to do our own update of trans_start */ + txq->trans_start = jiffies; + if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { fd.cmd |= cpu_to_be32(FM_FD_CMD_UPD); skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; diff --git a/drivers/net/ethernet/freescale/dpaa2/Kconfig b/drivers/net/ethernet/freescale/dpaa2/Kconfig index 809a155eb193..f6d244c663fd 100644 --- a/drivers/net/ethernet/freescale/dpaa2/Kconfig +++ b/drivers/net/ethernet/freescale/dpaa2/Kconfig @@ -9,8 +9,9 @@ config FSL_DPAA2_ETH config FSL_DPAA2_PTP_CLOCK tristate "Freescale DPAA2 PTP Clock" - depends on FSL_DPAA2_ETH && POSIX_TIMERS - select PTP_1588_CLOCK + depends on FSL_DPAA2_ETH + imply PTP_1588_CLOCK + default y help This driver adds support for using the DPAA2 1588 timer module as a PTP clock. diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index ae0f88bce9aa..697c2427f2b7 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2098,6 +2098,7 @@ static int fec_enet_get_regs_len(struct net_device *ndev) #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ defined(CONFIG_ARM64) || defined(CONFIG_COMPILE_TEST) +static __u32 fec_enet_register_version = 2; static u32 fec_enet_register_offset[] = { FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0, FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL, @@ -2128,6 +2129,7 @@ static u32 fec_enet_register_offset[] = { IEEE_R_FDXFC, IEEE_R_OCTETS_OK }; #else +static __u32 fec_enet_register_version = 1; static u32 fec_enet_register_offset[] = { FEC_ECNTRL, FEC_IEVENT, FEC_IMASK, FEC_IVEC, FEC_R_DES_ACTIVE_0, FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2, FEC_X_DES_ACTIVE_0, @@ -2149,6 +2151,8 @@ static void fec_enet_get_regs(struct net_device *ndev, u32 *buf = (u32 *)regbuf; u32 i, off; + regs->version = fec_enet_register_version; + memset(buf, 0, regs->len); for (i = 0; i < ARRAY_SIZE(fec_enet_register_offset); i++) { @@ -3467,7 +3471,7 @@ fec_probe(struct platform_device *pdev) if (ret) goto failed_clk_ipg; - fep->reg_phy = devm_regulator_get(&pdev->dev, "phy"); + fep->reg_phy = devm_regulator_get_optional(&pdev->dev, "phy"); if (!IS_ERR(fep->reg_phy)) { ret = regulator_enable(fep->reg_phy); if (ret) { diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c index b90bab72efdb..c1968b3ecec8 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c @@ -369,7 +369,7 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id) dma_unmap_single(dev->dev.parent, bd->skb_pa, skb->len, DMA_TO_DEVICE); - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); } spin_unlock(&priv->lock); diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index c3d539e209ed..eb3e65e8868f 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -1879,6 +1879,8 @@ static void ucc_geth_free_tx(struct ucc_geth_private *ugeth) u16 i, j; u8 __iomem *bd; + netdev_reset_queue(ugeth->ndev); + ug_info = ugeth->ug_info; uf_info = &ug_info->uf_info; diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c index 471805ea363b..e5d853b7b454 100644 --- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c +++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c @@ -1006,8 +1006,8 @@ static int hix5hd2_init_hw_desc_queue(struct hix5hd2_priv *priv) for (i = 0; i < QUEUE_NUMS; i++) { size = priv->pool[i].count * sizeof(struct hix5hd2_desc); - virt_addr = dma_zalloc_coherent(dev, size, &phys_addr, - GFP_KERNEL); + virt_addr = dma_alloc_coherent(dev, size, &phys_addr, + GFP_KERNEL); if (virt_addr == NULL) goto error_free_pool; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index ad1779fc410e..a78bfafd212c 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -147,12 +147,10 @@ static void hns_ae_put_handle(struct hnae_handle *handle) struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); int i; - vf_cb->mac_cb = NULL; - - kfree(vf_cb); - for (i = 0; i < handle->q_num; i++) hns_ae_get_ring_pair(handle->qs[i])->used_by_vf = 0; + + kfree(vf_cb); } static int hns_ae_wait_flow_down(struct hnae_handle *handle) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 3b9e74be5fbd..ac55db065f16 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -3081,6 +3081,7 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset) dsaf_dev = dev_get_drvdata(&pdev->dev); if (!dsaf_dev) { dev_err(&pdev->dev, "dsaf_dev is NULL\n"); + put_device(&pdev->dev); return -ENODEV; } @@ -3088,6 +3089,7 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset) if (AE_IS_VER1(dsaf_dev->dsaf_ver)) { dev_err(dsaf_dev->dev, "%s v1 chip doesn't support RoCE!\n", dsaf_dev->ae_dev.name); + put_device(&pdev->dev); return -ENODEV; } @@ -3126,6 +3128,9 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset) dsaf_set_bit(credit, DSAF_SBM_ROCEE_CFG_CRD_EN_B, 1); dsaf_write_dev(dsaf_dev, DSAF_SBM_ROCEE_CFG_REG_REG, credit); } + + put_device(&pdev->dev); + return 0; } EXPORT_SYMBOL(hns_dsaf_roce_reset); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 5748d3f722f6..60e7d7ae3787 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1170,6 +1170,13 @@ int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h) if (!h->phy_dev) return 0; + ethtool_convert_legacy_u32_to_link_mode(supported, h->if_support); + linkmode_and(phy_dev->supported, phy_dev->supported, supported); + linkmode_copy(phy_dev->advertising, phy_dev->supported); + + if (h->phy_if == PHY_INTERFACE_MODE_XGMII) + phy_dev->autoneg = false; + if (h->phy_if != PHY_INTERFACE_MODE_XGMII) { phy_dev->dev_flags = 0; @@ -1181,16 +1188,6 @@ int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h) if (unlikely(ret)) return -ENODEV; - ethtool_convert_legacy_u32_to_link_mode(supported, h->if_support); - linkmode_and(phy_dev->supported, phy_dev->supported, supported); - linkmode_copy(phy_dev->advertising, phy_dev->supported); - - if (h->phy_if == PHY_INTERFACE_MODE_XGMII) - phy_dev->autoneg = false; - - if (h->phy_if == PHY_INTERFACE_MODE_SGMII) - phy_stop(phy_dev); - return 0; } @@ -2421,6 +2418,8 @@ static int hns_nic_dev_probe(struct platform_device *pdev) out_notify_fail: (void)cancel_work_sync(&priv->service_task); out_read_prop_fail: + /* safe for ACPI FW */ + of_node_put(to_of_node(priv->fwnode)); free_netdev(ndev); return ret; } @@ -2450,6 +2449,9 @@ static int hns_nic_dev_remove(struct platform_device *pdev) set_bit(NIC_STATE_REMOVING, &priv->state); (void)cancel_work_sync(&priv->service_task); + /* safe for ACPI FW */ + of_node_put(to_of_node(priv->fwnode)); + free_netdev(ndev); return 0; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 8e9b95871d30..ce15d2350db9 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -1157,16 +1157,18 @@ static int hns_get_regs_len(struct net_device *net_dev) */ static int hns_nic_nway_reset(struct net_device *netdev) { - int ret = 0; struct phy_device *phy = netdev->phydev; - if (netif_running(netdev)) { - /* if autoneg is disabled, don't restart auto-negotiation */ - if (phy && phy->autoneg == AUTONEG_ENABLE) - ret = genphy_restart_aneg(phy); - } + if (!netif_running(netdev)) + return 0; - return ret; + if (!phy) + return -EOPNOTSUPP; + + if (phy->autoneg != AUTONEG_ENABLE) + return -EINVAL; + + return genphy_restart_aneg(phy); } static u32 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 07cd58798083..1bf7a5f116a0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2041,9 +2041,8 @@ static int hns3_alloc_desc(struct hns3_enet_ring *ring) { int size = ring->desc_num * sizeof(ring->desc[0]); - ring->desc = dma_zalloc_coherent(ring_to_dev(ring), size, - &ring->desc_dma_addr, - GFP_KERNEL); + ring->desc = dma_alloc_coherent(ring_to_dev(ring), size, + &ring->desc_dma_addr, GFP_KERNEL); if (!ring->desc) return -ENOMEM; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 8af0cef5609b..e483a6e730e6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -39,9 +39,8 @@ static int hclge_alloc_cmd_desc(struct hclge_cmq_ring *ring) { int size = ring->desc_num * sizeof(struct hclge_desc); - ring->desc = dma_zalloc_coherent(cmq_ring_to_dev(ring), - size, &ring->desc_dma_addr, - GFP_KERNEL); + ring->desc = dma_alloc_coherent(cmq_ring_to_dev(ring), size, + &ring->desc_dma_addr, GFP_KERNEL); if (!ring->desc) return -ENOMEM; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c index d5765c8cf3a3..4e78e8812a04 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c @@ -115,9 +115,8 @@ static int hclgevf_alloc_cmd_desc(struct hclgevf_cmq_ring *ring) { int size = ring->desc_num * sizeof(struct hclgevf_desc); - ring->desc = dma_zalloc_coherent(cmq_ring_to_dev(ring), - size, &ring->desc_dma_addr, - GFP_KERNEL); + ring->desc = dma_alloc_coherent(cmq_ring_to_dev(ring), size, + &ring->desc_dma_addr, GFP_KERNEL); if (!ring->desc) return -ENOMEM; diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c index 017e08452d8c..baf5cc251f32 100644 --- a/drivers/net/ethernet/hisilicon/hns_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -321,7 +321,7 @@ static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum) } hns_mdio_cmd_write(mdio_dev, is_c45, - MDIO_C45_WRITE_ADDR, phy_id, devad); + MDIO_C45_READ, phy_id, devad); } /* Step 5: waitting for MDIO_COMMAND_REG 's mdio_start==0,*/ diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c index c40603a183df..b4fefb4c3064 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c @@ -613,8 +613,8 @@ static int alloc_cmd_buf(struct hinic_api_cmd_chain *chain, u8 *cmd_vaddr; int err = 0; - cmd_vaddr = dma_zalloc_coherent(&pdev->dev, API_CMD_BUF_SIZE, - &cmd_paddr, GFP_KERNEL); + cmd_vaddr = dma_alloc_coherent(&pdev->dev, API_CMD_BUF_SIZE, + &cmd_paddr, GFP_KERNEL); if (!cmd_vaddr) { dev_err(&pdev->dev, "Failed to allocate API CMD DMA memory\n"); return -ENOMEM; @@ -663,8 +663,8 @@ static int api_cmd_create_cell(struct hinic_api_cmd_chain *chain, dma_addr_t node_paddr; int err; - node = dma_zalloc_coherent(&pdev->dev, chain->cell_size, - &node_paddr, GFP_KERNEL); + node = dma_alloc_coherent(&pdev->dev, chain->cell_size, &node_paddr, + GFP_KERNEL); if (!node) { dev_err(&pdev->dev, "Failed to allocate dma API CMD cell\n"); return -ENOMEM; @@ -821,10 +821,10 @@ static int api_chain_init(struct hinic_api_cmd_chain *chain, if (!chain->cell_ctxt) return -ENOMEM; - chain->wb_status = dma_zalloc_coherent(&pdev->dev, - sizeof(*chain->wb_status), - &chain->wb_status_paddr, - GFP_KERNEL); + chain->wb_status = dma_alloc_coherent(&pdev->dev, + sizeof(*chain->wb_status), + &chain->wb_status_paddr, + GFP_KERNEL); if (!chain->wb_status) { dev_err(&pdev->dev, "Failed to allocate DMA wb status\n"); return -ENOMEM; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c index 7cb8b9b94726..683e67515016 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c @@ -593,10 +593,10 @@ static int alloc_eq_pages(struct hinic_eq *eq) } for (pg = 0; pg < eq->num_pages; pg++) { - eq->virt_addr[pg] = dma_zalloc_coherent(&pdev->dev, - eq->page_size, - &eq->dma_addr[pg], - GFP_KERNEL); + eq->virt_addr[pg] = dma_alloc_coherent(&pdev->dev, + eq->page_size, + &eq->dma_addr[pg], + GFP_KERNEL); if (!eq->virt_addr[pg]) { err = -ENOMEM; goto err_dma_alloc; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c index 8e5897669a3a..a322a22d9357 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c @@ -355,9 +355,9 @@ int hinic_io_create_qps(struct hinic_func_to_io *func_to_io, goto err_sq_db; } - ci_addr_base = dma_zalloc_coherent(&pdev->dev, CI_TABLE_SIZE(num_qps), - &func_to_io->ci_dma_base, - GFP_KERNEL); + ci_addr_base = dma_alloc_coherent(&pdev->dev, CI_TABLE_SIZE(num_qps), + &func_to_io->ci_dma_base, + GFP_KERNEL); if (!ci_addr_base) { dev_err(&pdev->dev, "Failed to allocate CI area\n"); err = -ENOMEM; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c index bbf9bdd0ee3e..d62cf509646a 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c @@ -336,9 +336,9 @@ static int alloc_rq_cqe(struct hinic_rq *rq) goto err_cqe_dma_arr_alloc; for (i = 0; i < wq->q_depth; i++) { - rq->cqe[i] = dma_zalloc_coherent(&pdev->dev, - sizeof(*rq->cqe[i]), - &rq->cqe_dma[i], GFP_KERNEL); + rq->cqe[i] = dma_alloc_coherent(&pdev->dev, + sizeof(*rq->cqe[i]), + &rq->cqe_dma[i], GFP_KERNEL); if (!rq->cqe[i]) goto err_cqe_alloc; } @@ -415,8 +415,8 @@ int hinic_init_rq(struct hinic_rq *rq, struct hinic_hwif *hwif, /* HW requirements: Must be at least 32 bit */ pi_size = ALIGN(sizeof(*rq->pi_virt_addr), sizeof(u32)); - rq->pi_virt_addr = dma_zalloc_coherent(&pdev->dev, pi_size, - &rq->pi_dma_addr, GFP_KERNEL); + rq->pi_virt_addr = dma_alloc_coherent(&pdev->dev, pi_size, + &rq->pi_dma_addr, GFP_KERNEL); if (!rq->pi_virt_addr) { dev_err(&pdev->dev, "Failed to allocate PI address\n"); err = -ENOMEM; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c index 1dfa7eb05c10..cb66e7024659 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c @@ -114,8 +114,8 @@ static int queue_alloc_page(struct hinic_hwif *hwif, u64 **vaddr, u64 *paddr, struct pci_dev *pdev = hwif->pdev; dma_addr_t dma_addr; - *vaddr = dma_zalloc_coherent(&pdev->dev, page_sz, &dma_addr, - GFP_KERNEL); + *vaddr = dma_alloc_coherent(&pdev->dev, page_sz, &dma_addr, + GFP_KERNEL); if (!*vaddr) { dev_err(&pdev->dev, "Failed to allocate dma for wqs page\n"); return -ENOMEM; @@ -482,8 +482,8 @@ static int alloc_wq_pages(struct hinic_wq *wq, struct hinic_hwif *hwif, u64 *paddr = &wq->block_vaddr[i]; dma_addr_t dma_addr; - *vaddr = dma_zalloc_coherent(&pdev->dev, wq->wq_page_size, - &dma_addr, GFP_KERNEL); + *vaddr = dma_alloc_coherent(&pdev->dev, wq->wq_page_size, + &dma_addr, GFP_KERNEL); if (!*vaddr) { dev_err(&pdev->dev, "Failed to allocate wq page\n"); goto err_alloc_wq_pages; diff --git a/drivers/net/ethernet/i825xx/82596.c b/drivers/net/ethernet/i825xx/82596.c index d719668a6684..92929750f832 100644 --- a/drivers/net/ethernet/i825xx/82596.c +++ b/drivers/net/ethernet/i825xx/82596.c @@ -1310,7 +1310,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id) dev->stats.tx_aborted_errors++; } - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); tx_cmd->cmd.command = 0; /* Mark free */ break; diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c index fff09dcf9e34..787d5aca5278 100644 --- a/drivers/net/ethernet/ibm/emac/mal.c +++ b/drivers/net/ethernet/ibm/emac/mal.c @@ -636,8 +636,8 @@ static int mal_probe(struct platform_device *ofdev) bd_size = sizeof(struct mal_descriptor) * (NUM_TX_BUFF * mal->num_tx_chans + NUM_RX_BUFF * mal->num_rx_chans); - mal->bd_virt = dma_zalloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma, - GFP_KERNEL); + mal->bd_virt = dma_alloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma, + GFP_KERNEL); if (mal->bd_virt == NULL) { err = -ENOMEM; goto fail_unmap; diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 098d8764c0ea..dd71d5db7274 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -1313,7 +1313,6 @@ static int ibmveth_poll(struct napi_struct *napi, int budget) unsigned long lpar_rc; u16 mss = 0; -restart_poll: while (frames_processed < budget) { if (!ibmveth_rxq_pending_buffer(adapter)) break; @@ -1401,7 +1400,6 @@ restart_poll: napi_reschedule(napi)) { lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); - goto restart_poll; } } diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index 31fb76ee9d82..a1246e89aad4 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig @@ -159,7 +159,7 @@ config IXGBE tristate "Intel(R) 10GbE PCI Express adapters support" depends on PCI select MDIO - select MDIO_DEVICE + select PHYLIB imply PTP_1588_CLOCK ---help--- This driver supports Intel(R) 10GbE PCI Express family of diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c index 2569a168334c..a41008523c98 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c +++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c @@ -993,8 +993,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) txdr->size = txdr->count * sizeof(struct e1000_tx_desc); txdr->size = ALIGN(txdr->size, 4096); - txdr->desc = dma_zalloc_coherent(&pdev->dev, txdr->size, &txdr->dma, - GFP_KERNEL); + txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma, + GFP_KERNEL); if (!txdr->desc) { ret_val = 2; goto err_nomem; @@ -1051,8 +1051,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) } rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc); - rxdr->desc = dma_zalloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma, - GFP_KERNEL); + rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma, + GFP_KERNEL); if (!rxdr->desc) { ret_val = 6; goto err_nomem; diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 308c006cb41d..189f231075c2 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -2305,8 +2305,8 @@ static int e1000_alloc_ring_dma(struct e1000_adapter *adapter, { struct pci_dev *pdev = adapter->pdev; - ring->desc = dma_zalloc_coherent(&pdev->dev, ring->size, &ring->dma, - GFP_KERNEL); + ring->desc = dma_alloc_coherent(&pdev->dev, ring->size, &ring->dma, + GFP_KERNEL); if (!ring->desc) return -ENOMEM; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 4d40878e395a..e4ff531db14a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -109,8 +109,8 @@ int i40e_allocate_dma_mem_d(struct i40e_hw *hw, struct i40e_dma_mem *mem, struct i40e_pf *pf = (struct i40e_pf *)hw->back; mem->size = ALIGN(size, alignment); - mem->va = dma_zalloc_coherent(&pf->pdev->dev, mem->size, - &mem->pa, GFP_KERNEL); + mem->va = dma_alloc_coherent(&pf->pdev->dev, mem->size, &mem->pa, + GFP_KERNEL); if (!mem->va) return -ENOMEM; @@ -3289,8 +3289,11 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring) i40e_alloc_rx_buffers_zc(ring, I40E_DESC_UNUSED(ring)) : !i40e_alloc_rx_buffers(ring, I40E_DESC_UNUSED(ring)); if (!ok) { + /* Log this in case the user has forgotten to give the kernel + * any buffers, even later in the application. + */ dev_info(&vsi->back->pdev->dev, - "Failed allocate some buffers on %sRx ring %d (pf_q %d)\n", + "Failed to allocate some buffers on %sRx ring %d (pf_q %d)\n", ring->xsk_umem ? "UMEM enabled " : "", ring->queue_index, pf_q); } @@ -6725,8 +6728,13 @@ void i40e_down(struct i40e_vsi *vsi) for (i = 0; i < vsi->num_queue_pairs; i++) { i40e_clean_tx_ring(vsi->tx_rings[i]); - if (i40e_enabled_xdp_vsi(vsi)) + if (i40e_enabled_xdp_vsi(vsi)) { + /* Make sure that in-progress ndo_xdp_xmit + * calls are completed. + */ + synchronize_rcu(); i40e_clean_tx_ring(vsi->xdp_rings[i]); + } i40e_clean_rx_ring(vsi->rx_rings[i]); } @@ -11895,6 +11903,14 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, if (old_prog) bpf_prog_put(old_prog); + /* Kick start the NAPI context if there is an AF_XDP socket open + * on that queue id. This so that receiving will start. + */ + if (need_reset && prog) + for (i = 0; i < vsi->num_queue_pairs; i++) + if (vsi->xdp_rings[i]->xsk_umem) + (void)i40e_xsk_async_xmit(vsi->netdev, i); + return 0; } @@ -11955,8 +11971,13 @@ static void i40e_queue_pair_reset_stats(struct i40e_vsi *vsi, int queue_pair) static void i40e_queue_pair_clean_rings(struct i40e_vsi *vsi, int queue_pair) { i40e_clean_tx_ring(vsi->tx_rings[queue_pair]); - if (i40e_enabled_xdp_vsi(vsi)) + if (i40e_enabled_xdp_vsi(vsi)) { + /* Make sure that in-progress ndo_xdp_xmit calls are + * completed. + */ + synchronize_rcu(); i40e_clean_tx_ring(vsi->xdp_rings[queue_pair]); + } i40e_clean_rx_ring(vsi->rx_rings[queue_pair]); } diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index a7e14e98889f..6c97667d20ef 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -3709,6 +3709,7 @@ int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, struct i40e_netdev_priv *np = netdev_priv(dev); unsigned int queue_index = smp_processor_id(); struct i40e_vsi *vsi = np->vsi; + struct i40e_pf *pf = vsi->back; struct i40e_ring *xdp_ring; int drops = 0; int i; @@ -3716,7 +3717,8 @@ int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, if (test_bit(__I40E_VSI_DOWN, vsi->state)) return -ENETDOWN; - if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs) + if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs || + test_bit(__I40E_CONFIG_BUSY, pf->state)) return -ENXIO; if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index 870cf654e436..3827f16e6923 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -183,6 +183,11 @@ static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem, err = i40e_queue_pair_enable(vsi, qid); if (err) return err; + + /* Kick start the NAPI context so that receiving will start */ + err = i40e_xsk_async_xmit(vsi->netdev, qid); + if (err) + return err; } return 0; diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index fe1592ae8769..ca54e268d157 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -515,7 +515,7 @@ struct igb_adapter { /* OS defined structs */ struct pci_dev *pdev; - struct mutex stats64_lock; + spinlock_t stats64_lock; struct rtnl_link_stats64 stats64; /* structs defined in e1000_hw.h */ diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index 7426060b678f..c57671068245 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -2295,7 +2295,7 @@ static void igb_get_ethtool_stats(struct net_device *netdev, int i, j; char *p; - mutex_lock(&adapter->stats64_lock); + spin_lock(&adapter->stats64_lock); igb_update_stats(adapter); for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { @@ -2338,7 +2338,7 @@ static void igb_get_ethtool_stats(struct net_device *netdev, } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start)); i += IGB_RX_QUEUE_STATS_LEN; } - mutex_unlock(&adapter->stats64_lock); + spin_unlock(&adapter->stats64_lock); } static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 87bdf1604ae2..7137e7f9c7f3 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2203,9 +2203,9 @@ void igb_down(struct igb_adapter *adapter) del_timer_sync(&adapter->phy_info_timer); /* record the stats before reset*/ - mutex_lock(&adapter->stats64_lock); + spin_lock(&adapter->stats64_lock); igb_update_stats(adapter); - mutex_unlock(&adapter->stats64_lock); + spin_unlock(&adapter->stats64_lock); adapter->link_speed = 0; adapter->link_duplex = 0; @@ -3840,7 +3840,7 @@ static int igb_sw_init(struct igb_adapter *adapter) adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; spin_lock_init(&adapter->nfc_lock); - mutex_init(&adapter->stats64_lock); + spin_lock_init(&adapter->stats64_lock); #ifdef CONFIG_PCI_IOV switch (hw->mac.type) { case e1000_82576: @@ -5406,9 +5406,9 @@ no_wait: } } - mutex_lock(&adapter->stats64_lock); + spin_lock(&adapter->stats64_lock); igb_update_stats(adapter); - mutex_unlock(&adapter->stats64_lock); + spin_unlock(&adapter->stats64_lock); for (i = 0; i < adapter->num_tx_queues; i++) { struct igb_ring *tx_ring = adapter->tx_ring[i]; @@ -6235,10 +6235,10 @@ static void igb_get_stats64(struct net_device *netdev, { struct igb_adapter *adapter = netdev_priv(netdev); - mutex_lock(&adapter->stats64_lock); + spin_lock(&adapter->stats64_lock); igb_update_stats(adapter); memcpy(stats, &adapter->stats64, sizeof(*stats)); - mutex_unlock(&adapter->stats64_lock); + spin_unlock(&adapter->stats64_lock); } /** diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c index 1d4d1686909a..e5ac2d3fd816 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -680,8 +680,8 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter) txdr->size = txdr->count * sizeof(struct ixgb_tx_desc); txdr->size = ALIGN(txdr->size, 4096); - txdr->desc = dma_zalloc_coherent(&pdev->dev, txdr->size, &txdr->dma, - GFP_KERNEL); + txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma, + GFP_KERNEL); if (!txdr->desc) { vfree(txdr->buffer_info); return -ENOMEM; @@ -763,8 +763,8 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter) rxdr->size = rxdr->count * sizeof(struct ixgb_rx_desc); rxdr->size = ALIGN(rxdr->size, 4096); - rxdr->desc = dma_zalloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma, - GFP_KERNEL); + rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma, + GFP_KERNEL); if (!rxdr->desc) { vfree(rxdr->buffer_info); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index daff8183534b..cb35d8202572 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3953,8 +3953,11 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) else mrqc = IXGBE_MRQC_VMDQRSS64EN; - /* Enable L3/L4 for Tx Switched packets */ - mrqc |= IXGBE_MRQC_L3L4TXSWEN; + /* Enable L3/L4 for Tx Switched packets only for X550, + * older devices do not support this feature + */ + if (hw->mac.type >= ixgbe_mac_X550) + mrqc |= IXGBE_MRQC_L3L4TXSWEN; } else { if (tcs > 4) mrqc = IXGBE_MRQC_RTRSS8TCEN; @@ -10225,6 +10228,7 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog) int i, frame_size = dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; struct ixgbe_adapter *adapter = netdev_priv(dev); struct bpf_prog *old_prog; + bool need_reset; if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) return -EINVAL; @@ -10247,9 +10251,10 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog) return -ENOMEM; old_prog = xchg(&adapter->xdp_prog, prog); + need_reset = (!!prog != !!old_prog); /* If transitioning XDP modes reconfigure rings */ - if (!!prog != !!old_prog) { + if (need_reset) { int err = ixgbe_setup_tc(dev, adapter->hw_tcs); if (err) { @@ -10265,6 +10270,14 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog) if (old_prog) bpf_prog_put(old_prog); + /* Kick start the NAPI context if there is an AF_XDP socket open + * on that queue id. This so that receiving will start. + */ + if (need_reset && prog) + for (i = 0; i < adapter->num_rx_queues; i++) + if (adapter->xdp_ring[i]->xsk_umem) + (void)ixgbe_xsk_async_xmit(adapter->netdev, i); + return 0; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c index 65c3e2c979d4..36a8879536a4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c @@ -144,11 +144,19 @@ static int ixgbe_xsk_umem_enable(struct ixgbe_adapter *adapter, ixgbe_txrx_ring_disable(adapter, qid); err = ixgbe_add_xsk_umem(adapter, umem, qid); + if (err) + return err; - if (if_running) + if (if_running) { ixgbe_txrx_ring_enable(adapter, qid); - return err; + /* Kick start the NAPI context so that receiving will start */ + err = ixgbe_xsk_async_xmit(adapter->netdev, qid); + if (err) + return err; + } + + return 0; } static int ixgbe_xsk_umem_disable(struct ixgbe_adapter *adapter, u16 qid) @@ -634,7 +642,8 @@ static bool ixgbe_xmit_zc(struct ixgbe_ring *xdp_ring, unsigned int budget) dma_addr_t dma; while (budget-- > 0) { - if (unlikely(!ixgbe_desc_unused(xdp_ring))) { + if (unlikely(!ixgbe_desc_unused(xdp_ring)) || + !netif_carrier_ok(xdp_ring->netdev)) { work_done = false; break; } diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 2f427271a793..292a668ce88e 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -2879,7 +2879,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) ret = mv643xx_eth_shared_of_probe(pdev); if (ret) - return ret; + goto err_put_clk; pd = dev_get_platdata(&pdev->dev); msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ? @@ -2887,6 +2887,11 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) infer_hw_params(msp); return 0; + +err_put_clk: + if (!IS_ERR(msp->clk)) + clk_disable_unprepare(msp->clk); + return ret; } static int mv643xx_eth_shared_remove(struct platform_device *pdev) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 9d4568eb2297..8433fb9c3eee 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -2146,7 +2146,7 @@ err_drop_frame: if (unlikely(!skb)) goto err_drop_frame_ret_pool; - dma_sync_single_range_for_cpu(dev->dev.parent, + dma_sync_single_range_for_cpu(&pp->bm_priv->pdev->dev, rx_desc->buf_phys_addr, MVNETA_MH_SIZE + NET_SKB_PAD, rx_bytes, diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index e0875476a780..16066c2d5b3a 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -2044,9 +2044,9 @@ static int mvpp2_aggr_txq_init(struct platform_device *pdev, u32 txq_dma; /* Allocate memory for TX descriptors */ - aggr_txq->descs = dma_zalloc_coherent(&pdev->dev, - MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE, - &aggr_txq->descs_dma, GFP_KERNEL); + aggr_txq->descs = dma_alloc_coherent(&pdev->dev, + MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE, + &aggr_txq->descs_dma, GFP_KERNEL); if (!aggr_txq->descs) return -ENOMEM; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index 742f0c1f60df..6d55e3d0b7ea 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -825,7 +825,7 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (!cgx->cgx_cmd_workq) { dev_err(dev, "alloc workqueue failed for cgx cmd"); err = -ENOMEM; - goto err_release_regions; + goto err_free_irq_vectors; } list_add(&cgx->cgx_list, &cgx_list); @@ -841,6 +841,8 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id) err_release_lmac: cgx_lmac_exit(cgx); list_del(&cgx->cgx_list); +err_free_irq_vectors: + pci_free_irq_vectors(pdev); err_release_regions: pci_release_regions(pdev); err_disable_device: diff --git a/drivers/net/ethernet/marvell/octeontx2/af/common.h b/drivers/net/ethernet/marvell/octeontx2/af/common.h index ec50a21c5aaf..e332e82fc066 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/common.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/common.h @@ -64,7 +64,7 @@ static inline int qmem_alloc(struct device *dev, struct qmem **q, qmem->entry_sz = entry_sz; qmem->alloc_sz = (qsize * entry_sz) + OTX2_ALIGN; - qmem->base = dma_zalloc_coherent(dev, qmem->alloc_sz, + qmem->base = dma_alloc_coherent(dev, qmem->alloc_sz, &qmem->iova, GFP_KERNEL); if (!qmem->base) return -ENOMEM; diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 0bd4351b2a49..f8a6d6e3cb7a 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -557,9 +557,9 @@ static int init_hash_table(struct pxa168_eth_private *pep) * table is full. */ if (!pep->htpr) { - pep->htpr = dma_zalloc_coherent(pep->dev->dev.parent, - HASH_ADDR_TABLE_SIZE, - &pep->htpr_dma, GFP_KERNEL); + pep->htpr = dma_alloc_coherent(pep->dev->dev.parent, + HASH_ADDR_TABLE_SIZE, + &pep->htpr_dma, GFP_KERNEL); if (!pep->htpr) return -ENOMEM; } else { @@ -1044,9 +1044,9 @@ static int rxq_init(struct net_device *dev) pep->rx_desc_count = 0; size = pep->rx_ring_size * sizeof(struct rx_desc); pep->rx_desc_area_size = size; - pep->p_rx_desc_area = dma_zalloc_coherent(pep->dev->dev.parent, size, - &pep->rx_desc_dma, - GFP_KERNEL); + pep->p_rx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size, + &pep->rx_desc_dma, + GFP_KERNEL); if (!pep->p_rx_desc_area) goto out; @@ -1103,9 +1103,9 @@ static int txq_init(struct net_device *dev) pep->tx_desc_count = 0; size = pep->tx_ring_size * sizeof(struct tx_desc); pep->tx_desc_area_size = size; - pep->p_tx_desc_area = dma_zalloc_coherent(pep->dev->dev.parent, size, - &pep->tx_desc_dma, - GFP_KERNEL); + pep->p_tx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size, + &pep->tx_desc_dma, + GFP_KERNEL); if (!pep->p_tx_desc_area) goto out; /* Initialize the next_desc_ptr links in the Tx descriptors ring */ diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 04fd1f135011..654ac534b10e 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -152,8 +152,10 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs, memset(p, 0, regs->len); memcpy_fromio(p, io, B3_RAM_ADDR); - memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, - regs->len - B3_RI_WTO_R1); + if (regs->len > B3_RI_WTO_R1) { + memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, + regs->len - B3_RI_WTO_R1); + } } /* Wake on Lan only supported on Yukon chips with rev 1 or above */ diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index f3a5fa84860f..57727fe1501e 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -5073,7 +5073,7 @@ static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) INIT_WORK(&hw->restart_work, sky2_restart); pci_set_drvdata(pdev, hw); - pdev->d3_delay = 200; + pdev->d3_delay = 300; return 0; diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 399f565dd85a..49f926b7a91c 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -258,11 +258,6 @@ static void mtk_phy_link_adjust(struct net_device *dev) mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); - if (dev->phydev->link) - netif_carrier_on(dev); - else - netif_carrier_off(dev); - if (!of_phy_is_fixed_link(mac->of_node)) phy_print_status(dev->phydev); } @@ -347,17 +342,6 @@ static int mtk_phy_connect(struct net_device *dev) if (mtk_phy_connect_node(eth, mac, np)) goto err_phy; - dev->phydev->autoneg = AUTONEG_ENABLE; - dev->phydev->speed = 0; - dev->phydev->duplex = 0; - - phy_set_max_speed(dev->phydev, SPEED_1000); - phy_support_asym_pause(dev->phydev); - linkmode_copy(dev->phydev->advertising, dev->phydev->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, - dev->phydev->advertising); - phy_start_aneg(dev->phydev); - of_node_put(np); return 0; @@ -598,10 +582,10 @@ static int mtk_init_fq_dma(struct mtk_eth *eth) dma_addr_t dma_addr; int i; - eth->scratch_ring = dma_zalloc_coherent(eth->dev, - cnt * sizeof(struct mtk_tx_dma), - ð->phy_scratch_ring, - GFP_ATOMIC); + eth->scratch_ring = dma_alloc_coherent(eth->dev, + cnt * sizeof(struct mtk_tx_dma), + ð->phy_scratch_ring, + GFP_ATOMIC); if (unlikely(!eth->scratch_ring)) return -ENOMEM; @@ -1213,8 +1197,8 @@ static int mtk_tx_alloc(struct mtk_eth *eth) if (!ring->buf) goto no_tx_mem; - ring->dma = dma_zalloc_coherent(eth->dev, MTK_DMA_SIZE * sz, - &ring->phys, GFP_ATOMIC); + ring->dma = dma_alloc_coherent(eth->dev, MTK_DMA_SIZE * sz, + &ring->phys, GFP_ATOMIC); if (!ring->dma) goto no_tx_mem; @@ -1310,9 +1294,9 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) return -ENOMEM; } - ring->dma = dma_zalloc_coherent(eth->dev, - rx_dma_size * sizeof(*ring->dma), - &ring->phys, GFP_ATOMIC); + ring->dma = dma_alloc_coherent(eth->dev, + rx_dma_size * sizeof(*ring->dma), + &ring->phys, GFP_ATOMIC); if (!ring->dma) return -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c index 9af34e03892c..dbc483e4a2ef 100644 --- a/drivers/net/ethernet/mellanox/mlx4/alloc.c +++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c @@ -584,8 +584,8 @@ static int mlx4_buf_direct_alloc(struct mlx4_dev *dev, int size, buf->npages = 1; buf->page_shift = get_order(size) + PAGE_SHIFT; buf->direct.buf = - dma_zalloc_coherent(&dev->persist->pdev->dev, - size, &t, GFP_KERNEL); + dma_alloc_coherent(&dev->persist->pdev->dev, size, &t, + GFP_KERNEL); if (!buf->direct.buf) return -ENOMEM; @@ -624,8 +624,8 @@ int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct, for (i = 0; i < buf->nbufs; ++i) { buf->page_list[i].buf = - dma_zalloc_coherent(&dev->persist->pdev->dev, - PAGE_SIZE, &t, GFP_KERNEL); + dma_alloc_coherent(&dev->persist->pdev->dev, + PAGE_SIZE, &t, GFP_KERNEL); if (!buf->page_list[i].buf) goto err_free; diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c index db909b6069b5..65f8a4b6ed0c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/cq.c @@ -306,14 +306,16 @@ static int mlx4_init_user_cqes(void *buf, int entries, int cqe_size) if (entries_per_copy < entries) { for (i = 0; i < entries / entries_per_copy; i++) { - err = copy_to_user(buf, init_ents, PAGE_SIZE); + err = copy_to_user((void __user *)buf, init_ents, PAGE_SIZE) ? + -EFAULT : 0; if (err) goto out; buf += PAGE_SIZE; } } else { - err = copy_to_user(buf, init_ents, entries * cqe_size); + err = copy_to_user((void __user *)buf, init_ents, entries * cqe_size) ? + -EFAULT : 0; } out: diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 6b88881b8e35..c1438ae52a11 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -3360,7 +3360,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, dev->addr_len = ETH_ALEN; mlx4_en_u64_to_mac(dev->dev_addr, mdev->dev->caps.def_mac[priv->port]); if (!is_valid_ether_addr(dev->dev_addr)) { - en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n", + en_err(priv, "Port: %d, invalid mac burned: %pM, quitting\n", priv->port, dev->dev_addr); err = -EINVAL; goto out; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 9a0881cb7f51..6c01314e87b0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -617,6 +617,8 @@ static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb, } #endif +#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN) + /* We reach this function only after checking that any of * the (IPv4 | IPv6) bits are set in cqe->status. */ @@ -624,9 +626,20 @@ static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va, netdev_features_t dev_features) { __wsum hw_checksum = 0; + void *hdr; + + /* CQE csum doesn't cover padding octets in short ethernet + * frames. And the pad field is appended prior to calculating + * and appending the FCS field. + * + * Detecting these padded frames requires to verify and parse + * IP headers, so we simply force all those small frames to skip + * checksum complete. + */ + if (short_frame(skb->len)) + return -EINVAL; - void *hdr = (u8 *)va + sizeof(struct ethhdr); - + hdr = (u8 *)va + sizeof(struct ethhdr); hw_checksum = csum_unfold((__force __sum16)cqe->checksum); if (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_CVLAN_PRESENT_MASK) && @@ -819,6 +832,11 @@ xdp_drop_no_cnt: skb_record_rx_queue(skb, cq_ring); if (likely(dev->features & NETIF_F_RXCSUM)) { + /* TODO: For IP non TCP/UDP packets when csum complete is + * not an option (not supported or any other reason) we can + * actually check cqe IPOK status bit and report + * CHECKSUM_UNNECESSARY rather than CHECKSUM_NONE + */ if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP | MLX4_CQE_STATUS_UDP)) && (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) && diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 7df728f1e5b5..6e501af0e532 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -2067,9 +2067,11 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, { struct mlx4_cmd_mailbox *mailbox; __be32 *outbox; + u64 qword_field; u32 dword_field; - int err; + u16 word_field; u8 byte_field; + int err; static const u8 a0_dmfs_query_hw_steering[] = { [0] = MLX4_STEERING_DMFS_A0_DEFAULT, [1] = MLX4_STEERING_DMFS_A0_DYNAMIC, @@ -2097,19 +2099,32 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, /* QPC/EEC/CQC/EQC/RDMARC attributes */ - MLX4_GET(param->qpc_base, outbox, INIT_HCA_QPC_BASE_OFFSET); - MLX4_GET(param->log_num_qps, outbox, INIT_HCA_LOG_QP_OFFSET); - MLX4_GET(param->srqc_base, outbox, INIT_HCA_SRQC_BASE_OFFSET); - MLX4_GET(param->log_num_srqs, outbox, INIT_HCA_LOG_SRQ_OFFSET); - MLX4_GET(param->cqc_base, outbox, INIT_HCA_CQC_BASE_OFFSET); - MLX4_GET(param->log_num_cqs, outbox, INIT_HCA_LOG_CQ_OFFSET); - MLX4_GET(param->altc_base, outbox, INIT_HCA_ALTC_BASE_OFFSET); - MLX4_GET(param->auxc_base, outbox, INIT_HCA_AUXC_BASE_OFFSET); - MLX4_GET(param->eqc_base, outbox, INIT_HCA_EQC_BASE_OFFSET); - MLX4_GET(param->log_num_eqs, outbox, INIT_HCA_LOG_EQ_OFFSET); - MLX4_GET(param->num_sys_eqs, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET); - MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET); - MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET); + MLX4_GET(qword_field, outbox, INIT_HCA_QPC_BASE_OFFSET); + param->qpc_base = qword_field & ~((u64)0x1f); + MLX4_GET(byte_field, outbox, INIT_HCA_LOG_QP_OFFSET); + param->log_num_qps = byte_field & 0x1f; + MLX4_GET(qword_field, outbox, INIT_HCA_SRQC_BASE_OFFSET); + param->srqc_base = qword_field & ~((u64)0x1f); + MLX4_GET(byte_field, outbox, INIT_HCA_LOG_SRQ_OFFSET); + param->log_num_srqs = byte_field & 0x1f; + MLX4_GET(qword_field, outbox, INIT_HCA_CQC_BASE_OFFSET); + param->cqc_base = qword_field & ~((u64)0x1f); + MLX4_GET(byte_field, outbox, INIT_HCA_LOG_CQ_OFFSET); + param->log_num_cqs = byte_field & 0x1f; + MLX4_GET(qword_field, outbox, INIT_HCA_ALTC_BASE_OFFSET); + param->altc_base = qword_field; + MLX4_GET(qword_field, outbox, INIT_HCA_AUXC_BASE_OFFSET); + param->auxc_base = qword_field; + MLX4_GET(qword_field, outbox, INIT_HCA_EQC_BASE_OFFSET); + param->eqc_base = qword_field & ~((u64)0x1f); + MLX4_GET(byte_field, outbox, INIT_HCA_LOG_EQ_OFFSET); + param->log_num_eqs = byte_field & 0x1f; + MLX4_GET(word_field, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET); + param->num_sys_eqs = word_field & 0xfff; + MLX4_GET(qword_field, outbox, INIT_HCA_RDMARC_BASE_OFFSET); + param->rdmarc_base = qword_field & ~((u64)0x1f); + MLX4_GET(byte_field, outbox, INIT_HCA_LOG_RD_OFFSET); + param->log_rd_per_qp = byte_field & 0x7; MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET); if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) { @@ -2128,22 +2143,21 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, /* steering attributes */ if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET); - MLX4_GET(param->log_mc_entry_sz, outbox, - INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); - MLX4_GET(param->log_mc_table_sz, outbox, - INIT_HCA_FS_LOG_TABLE_SZ_OFFSET); - MLX4_GET(byte_field, outbox, - INIT_HCA_FS_A0_OFFSET); + MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); + param->log_mc_entry_sz = byte_field & 0x1f; + MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_TABLE_SZ_OFFSET); + param->log_mc_table_sz = byte_field & 0x1f; + MLX4_GET(byte_field, outbox, INIT_HCA_FS_A0_OFFSET); param->dmfs_high_steer_mode = a0_dmfs_query_hw_steering[(byte_field >> 6) & 3]; } else { MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET); - MLX4_GET(param->log_mc_entry_sz, outbox, - INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); - MLX4_GET(param->log_mc_hash_sz, outbox, - INIT_HCA_LOG_MC_HASH_SZ_OFFSET); - MLX4_GET(param->log_mc_table_sz, outbox, - INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); + MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); + param->log_mc_entry_sz = byte_field & 0x1f; + MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_HASH_SZ_OFFSET); + param->log_mc_hash_sz = byte_field & 0x1f; + MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); + param->log_mc_table_sz = byte_field & 0x1f; } /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */ @@ -2167,15 +2181,18 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, /* TPT attributes */ MLX4_GET(param->dmpt_base, outbox, INIT_HCA_DMPT_BASE_OFFSET); - MLX4_GET(param->mw_enabled, outbox, INIT_HCA_TPT_MW_OFFSET); - MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET); + MLX4_GET(byte_field, outbox, INIT_HCA_TPT_MW_OFFSET); + param->mw_enabled = byte_field >> 7; + MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET); + param->log_mpt_sz = byte_field & 0x3f; MLX4_GET(param->mtt_base, outbox, INIT_HCA_MTT_BASE_OFFSET); MLX4_GET(param->cmpt_base, outbox, INIT_HCA_CMPT_BASE_OFFSET); /* UAR attributes */ MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET); - MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET); + MLX4_GET(byte_field, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET); + param->log_uar_sz = byte_field & 0xf; /* phv_check enable */ MLX4_GET(byte_field, outbox, INIT_HCA_CACHELINE_SZ_OFFSET); diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c index 4b4351141b94..d89a3da89e5a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/drivers/net/ethernet/mellanox/mlx4/icm.c @@ -57,12 +57,12 @@ static void mlx4_free_icm_pages(struct mlx4_dev *dev, struct mlx4_icm_chunk *chu int i; if (chunk->nsg > 0) - pci_unmap_sg(dev->persist->pdev, chunk->mem, chunk->npages, - PCI_DMA_BIDIRECTIONAL); + dma_unmap_sg(&dev->persist->pdev->dev, chunk->sg, chunk->npages, + DMA_BIDIRECTIONAL); for (i = 0; i < chunk->npages; ++i) - __free_pages(sg_page(&chunk->mem[i]), - get_order(chunk->mem[i].length)); + __free_pages(sg_page(&chunk->sg[i]), + get_order(chunk->sg[i].length)); } static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk *chunk) @@ -71,9 +71,9 @@ static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk * for (i = 0; i < chunk->npages; ++i) dma_free_coherent(&dev->persist->pdev->dev, - chunk->mem[i].length, - lowmem_page_address(sg_page(&chunk->mem[i])), - sg_dma_address(&chunk->mem[i])); + chunk->buf[i].size, + chunk->buf[i].addr, + chunk->buf[i].dma_addr); } void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent) @@ -111,22 +111,21 @@ static int mlx4_alloc_icm_pages(struct scatterlist *mem, int order, return 0; } -static int mlx4_alloc_icm_coherent(struct device *dev, struct scatterlist *mem, - int order, gfp_t gfp_mask) +static int mlx4_alloc_icm_coherent(struct device *dev, struct mlx4_icm_buf *buf, + int order, gfp_t gfp_mask) { - void *buf = dma_alloc_coherent(dev, PAGE_SIZE << order, - &sg_dma_address(mem), gfp_mask); - if (!buf) + buf->addr = dma_alloc_coherent(dev, PAGE_SIZE << order, + &buf->dma_addr, gfp_mask); + if (!buf->addr) return -ENOMEM; - if (offset_in_page(buf)) { - dma_free_coherent(dev, PAGE_SIZE << order, - buf, sg_dma_address(mem)); + if (offset_in_page(buf->addr)) { + dma_free_coherent(dev, PAGE_SIZE << order, buf->addr, + buf->dma_addr); return -ENOMEM; } - sg_set_buf(mem, buf, PAGE_SIZE << order); - sg_dma_len(mem) = PAGE_SIZE << order; + buf->size = PAGE_SIZE << order; return 0; } @@ -159,21 +158,21 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, while (npages > 0) { if (!chunk) { - chunk = kmalloc_node(sizeof(*chunk), + chunk = kzalloc_node(sizeof(*chunk), gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN), dev->numa_node); if (!chunk) { - chunk = kmalloc(sizeof(*chunk), + chunk = kzalloc(sizeof(*chunk), gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN)); if (!chunk) goto fail; } + chunk->coherent = coherent; - sg_init_table(chunk->mem, MLX4_ICM_CHUNK_LEN); - chunk->npages = 0; - chunk->nsg = 0; + if (!coherent) + sg_init_table(chunk->sg, MLX4_ICM_CHUNK_LEN); list_add_tail(&chunk->list, &icm->chunk_list); } @@ -186,10 +185,10 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, if (coherent) ret = mlx4_alloc_icm_coherent(&dev->persist->pdev->dev, - &chunk->mem[chunk->npages], - cur_order, mask); + &chunk->buf[chunk->npages], + cur_order, mask); else - ret = mlx4_alloc_icm_pages(&chunk->mem[chunk->npages], + ret = mlx4_alloc_icm_pages(&chunk->sg[chunk->npages], cur_order, mask, dev->numa_node); @@ -205,9 +204,9 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, if (coherent) ++chunk->nsg; else if (chunk->npages == MLX4_ICM_CHUNK_LEN) { - chunk->nsg = pci_map_sg(dev->persist->pdev, chunk->mem, - chunk->npages, - PCI_DMA_BIDIRECTIONAL); + chunk->nsg = dma_map_sg(&dev->persist->pdev->dev, + chunk->sg, chunk->npages, + DMA_BIDIRECTIONAL); if (chunk->nsg <= 0) goto fail; @@ -220,9 +219,8 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, } if (!coherent && chunk) { - chunk->nsg = pci_map_sg(dev->persist->pdev, chunk->mem, - chunk->npages, - PCI_DMA_BIDIRECTIONAL); + chunk->nsg = dma_map_sg(&dev->persist->pdev->dev, chunk->sg, + chunk->npages, DMA_BIDIRECTIONAL); if (chunk->nsg <= 0) goto fail; @@ -320,7 +318,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, u64 idx; struct mlx4_icm_chunk *chunk; struct mlx4_icm *icm; - struct page *page = NULL; + void *addr = NULL; if (!table->lowmem) return NULL; @@ -336,28 +334,49 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, list_for_each_entry(chunk, &icm->chunk_list, list) { for (i = 0; i < chunk->npages; ++i) { + dma_addr_t dma_addr; + size_t len; + + if (table->coherent) { + len = chunk->buf[i].size; + dma_addr = chunk->buf[i].dma_addr; + addr = chunk->buf[i].addr; + } else { + struct page *page; + + len = sg_dma_len(&chunk->sg[i]); + dma_addr = sg_dma_address(&chunk->sg[i]); + + /* XXX: we should never do this for highmem + * allocation. This function either needs + * to be split, or the kernel virtual address + * return needs to be made optional. + */ + page = sg_page(&chunk->sg[i]); + addr = lowmem_page_address(page); + } + if (dma_handle && dma_offset >= 0) { - if (sg_dma_len(&chunk->mem[i]) > dma_offset) - *dma_handle = sg_dma_address(&chunk->mem[i]) + - dma_offset; - dma_offset -= sg_dma_len(&chunk->mem[i]); + if (len > dma_offset) + *dma_handle = dma_addr + dma_offset; + dma_offset -= len; } + /* * DMA mapping can merge pages but not split them, * so if we found the page, dma_handle has already * been assigned to. */ - if (chunk->mem[i].length > offset) { - page = sg_page(&chunk->mem[i]); + if (len > offset) goto out; - } - offset -= chunk->mem[i].length; + offset -= len; } } + addr = NULL; out: mutex_unlock(&table->mutex); - return page ? lowmem_page_address(page) + offset : NULL; + return addr ? addr + offset : NULL; } int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.h b/drivers/net/ethernet/mellanox/mlx4/icm.h index c9169a490557..d199874b1c07 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.h +++ b/drivers/net/ethernet/mellanox/mlx4/icm.h @@ -47,11 +47,21 @@ enum { MLX4_ICM_PAGE_SIZE = 1 << MLX4_ICM_PAGE_SHIFT, }; +struct mlx4_icm_buf { + void *addr; + size_t size; + dma_addr_t dma_addr; +}; + struct mlx4_icm_chunk { struct list_head list; int npages; int nsg; - struct scatterlist mem[MLX4_ICM_CHUNK_LEN]; + bool coherent; + union { + struct scatterlist sg[MLX4_ICM_CHUNK_LEN]; + struct mlx4_icm_buf buf[MLX4_ICM_CHUNK_LEN]; + }; }; struct mlx4_icm { @@ -114,12 +124,18 @@ static inline void mlx4_icm_next(struct mlx4_icm_iter *iter) static inline dma_addr_t mlx4_icm_addr(struct mlx4_icm_iter *iter) { - return sg_dma_address(&iter->chunk->mem[iter->page_idx]); + if (iter->chunk->coherent) + return iter->chunk->buf[iter->page_idx].dma_addr; + else + return sg_dma_address(&iter->chunk->sg[iter->page_idx]); } static inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter) { - return sg_dma_len(&iter->chunk->mem[iter->page_idx]); + if (iter->chunk->coherent) + return iter->chunk->buf[iter->page_idx].size; + else + return sg_dma_len(&iter->chunk->sg[iter->page_idx]); } int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c index 456f30007ad6..421b9c3c8bf7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c @@ -63,8 +63,8 @@ static void *mlx5_dma_zalloc_coherent_node(struct mlx5_core_dev *dev, mutex_lock(&priv->alloc_mutex); original_node = dev_to_node(&dev->pdev->dev); set_dev_node(&dev->pdev->dev, node); - cpu_handle = dma_zalloc_coherent(&dev->pdev->dev, size, - dma_handle, GFP_KERNEL); + cpu_handle = dma_alloc_coherent(&dev->pdev->dev, size, dma_handle, + GFP_KERNEL); set_dev_node(&dev->pdev->dev, original_node); mutex_unlock(&priv->alloc_mutex); return cpu_handle; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index d3125cdf69db..e267ff93e8a8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -1583,6 +1583,24 @@ no_trig: spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags); } +void mlx5_cmd_flush(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd *cmd = &dev->cmd; + int i; + + for (i = 0; i < cmd->max_reg_cmds; i++) + while (down_trylock(&cmd->sem)) + mlx5_cmd_trigger_completions(dev); + + while (down_trylock(&cmd->pages_sem)) + mlx5_cmd_trigger_completions(dev); + + /* Unlock cmdif */ + up(&cmd->pages_sem); + for (i = 0; i < cmd->max_reg_cmds; i++) + up(&cmd->sem); +} + static int status_to_err(u8 status) { return status ? -1 : 0; /* TBD more meaningful codes */ @@ -1789,8 +1807,8 @@ static int alloc_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd) { struct device *ddev = &dev->pdev->dev; - cmd->cmd_alloc_buf = dma_zalloc_coherent(ddev, MLX5_ADAPTER_PAGE_SIZE, - &cmd->alloc_dma, GFP_KERNEL); + cmd->cmd_alloc_buf = dma_alloc_coherent(ddev, MLX5_ADAPTER_PAGE_SIZE, + &cmd->alloc_dma, GFP_KERNEL); if (!cmd->cmd_alloc_buf) return -ENOMEM; @@ -1804,9 +1822,9 @@ static int alloc_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd) dma_free_coherent(ddev, MLX5_ADAPTER_PAGE_SIZE, cmd->cmd_alloc_buf, cmd->alloc_dma); - cmd->cmd_alloc_buf = dma_zalloc_coherent(ddev, - 2 * MLX5_ADAPTER_PAGE_SIZE - 1, - &cmd->alloc_dma, GFP_KERNEL); + cmd->cmd_alloc_buf = dma_alloc_coherent(ddev, + 2 * MLX5_ADAPTER_PAGE_SIZE - 1, + &cmd->alloc_dma, GFP_KERNEL); if (!cmd->cmd_alloc_buf) return -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 8fa8fdd30b85..448a92561567 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -657,6 +657,7 @@ struct mlx5e_channel_stats { enum { MLX5E_STATE_OPENED, MLX5E_STATE_DESTROYING, + MLX5E_STATE_XDP_TX_ENABLED, }; struct mlx5e_rqt { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c index 046948ead152..f3c7ab6faea5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c @@ -256,6 +256,7 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv, e->m_neigh.family = n->ops->family; memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len); e->out_dev = out_dev; + e->route_dev = route_dev; /* It's important to add the neigh to the hash table before checking * the neigh validity state. So if we'll get a notification, in case the @@ -369,6 +370,7 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv, e->m_neigh.family = n->ops->family; memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len); e->out_dev = out_dev; + e->route_dev = route_dev; /* It's importent to add the neigh to the hash table before checking * the neigh validity state. So if we'll get a notification, in case the @@ -612,16 +614,18 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev, struct mlx5_flow_spec *spec, struct tc_cls_flower_offload *f, void *headers_c, - void *headers_v) + void *headers_v, u8 *match_level) { int tunnel_type; int err = 0; tunnel_type = mlx5e_tc_tun_get_type(filter_dev); if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN) { + *match_level = MLX5_MATCH_L4; err = mlx5e_tc_tun_parse_vxlan(priv, spec, f, headers_c, headers_v); } else if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_GRETAP) { + *match_level = MLX5_MATCH_L3; err = mlx5e_tc_tun_parse_gretap(priv, spec, f, headers_c, headers_v); } else { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h index 706ce7bf15e7..b63f15de899d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h @@ -39,6 +39,6 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev, struct mlx5_flow_spec *spec, struct tc_cls_flower_offload *f, void *headers_c, - void *headers_v); + void *headers_v, u8 *match_level); #endif //__MLX5_EN_TC_TUNNEL_H__ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c index 3740177eed09..03b2a9f9c589 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c @@ -365,7 +365,8 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, int sq_num; int i; - if (unlikely(!test_bit(MLX5E_STATE_OPENED, &priv->state))) + /* this flag is sufficient, no need to test internal sq state */ + if (unlikely(!mlx5e_xdp_tx_is_enabled(priv))) return -ENETDOWN; if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) @@ -378,9 +379,6 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, sq = &priv->channels.c[sq_num]->xdpsq; - if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &sq->state))) - return -ENETDOWN; - for (i = 0; i < n; i++) { struct xdp_frame *xdpf = frames[i]; struct mlx5e_xdp_info xdpi; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h index 3a67cb3cd179..ee27a7c8cd87 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h @@ -50,6 +50,23 @@ void mlx5e_xdp_rx_poll_complete(struct mlx5e_rq *rq); int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, u32 flags); +static inline void mlx5e_xdp_tx_enable(struct mlx5e_priv *priv) +{ + set_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state); +} + +static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv) +{ + clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state); + /* let other device's napi(s) see our new state */ + synchronize_rcu(); +} + +static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv) +{ + return test_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state); +} + static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq) { if (sq->doorbell_cseg) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index c9df08133718..47233b9a4f81 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -354,9 +354,6 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv, new_channels.params = priv->channels.params; new_channels.params.num_channels = count; - if (!netif_is_rxfh_configured(priv->netdev)) - mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt, - MLX5E_INDIR_RQT_SIZE, count); if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) { priv->channels.params = new_channels.params; @@ -372,6 +369,10 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv, if (arfs_enabled) mlx5e_arfs_disable(priv); + if (!netif_is_rxfh_configured(priv->netdev)) + mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt, + MLX5E_INDIR_RQT_SIZE, count); + /* Switch to new channels, set new parameters and close old ones */ mlx5e_switch_priv_channels(priv, &new_channels, NULL); @@ -844,9 +845,12 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv, ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Autoneg); - if (get_fec_supported_advertised(mdev, link_ksettings)) + err = get_fec_supported_advertised(mdev, link_ksettings); + if (err) { netdev_dbg(priv->netdev, "%s: FEC caps query failed: %d\n", __func__, err); + err = 0; /* don't fail caps query because of FEC error */ + } if (!an_disable_admin) ethtool_link_ksettings_add_link_mode(link_ksettings, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 8cfd2ec7c0a2..93e50ccd44c3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -950,7 +950,7 @@ static int mlx5e_open_rq(struct mlx5e_channel *c, if (params->rx_dim_enabled) __set_bit(MLX5E_RQ_STATE_AM, &c->rq.state); - if (params->pflags & MLX5E_PFLAG_RX_NO_CSUM_COMPLETE) + if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_NO_CSUM_COMPLETE)) __set_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &c->rq.state); return 0; @@ -2938,6 +2938,7 @@ void mlx5e_activate_priv_channels(struct mlx5e_priv *priv) mlx5e_build_tx2sq_maps(priv); mlx5e_activate_channels(&priv->channels); + mlx5e_xdp_tx_enable(priv); netif_tx_start_all_queues(priv->netdev); if (mlx5e_is_vport_rep(priv)) @@ -2959,6 +2960,7 @@ void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv) */ netif_tx_stop_all_queues(priv->netdev); netif_tx_disable(priv->netdev); + mlx5e_xdp_tx_disable(priv); mlx5e_deactivate_channels(&priv->channels); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 96cc0c6a4014..ef9e472daffb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -58,7 +58,8 @@ struct mlx5e_rep_indr_block_priv { struct list_head list; }; -static void mlx5e_rep_indr_unregister_block(struct net_device *netdev); +static void mlx5e_rep_indr_unregister_block(struct mlx5e_rep_priv *rpriv, + struct net_device *netdev); static void mlx5e_rep_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) @@ -179,6 +180,7 @@ static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv) s->tx_packets += sq_stats->packets; s->tx_bytes += sq_stats->bytes; + s->tx_queue_dropped += sq_stats->dropped; } } } @@ -594,6 +596,10 @@ static void mlx5e_rep_update_flows(struct mlx5e_priv *priv, if (neigh_connected && !(e->flags & MLX5_ENCAP_ENTRY_VALID)) { ether_addr_copy(e->h_dest, ha); ether_addr_copy(eth->h_dest, ha); + /* Update the encap source mac, in case that we delete + * the flows when encap source mac changed. + */ + ether_addr_copy(eth->h_source, e->route_dev->dev_addr); mlx5e_tc_encap_flows_add(priv, e); } @@ -663,7 +669,7 @@ static void mlx5e_rep_indr_clean_block_privs(struct mlx5e_rep_priv *rpriv) struct list_head *head = &rpriv->uplink_priv.tc_indr_block_priv_list; list_for_each_entry_safe(cb_priv, temp, head, list) { - mlx5e_rep_indr_unregister_block(cb_priv->netdev); + mlx5e_rep_indr_unregister_block(rpriv, cb_priv->netdev); kfree(cb_priv); } } @@ -735,7 +741,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev, err = tcf_block_cb_register(f->block, mlx5e_rep_indr_setup_block_cb, - netdev, indr_priv, f->extack); + indr_priv, indr_priv, f->extack); if (err) { list_del(&indr_priv->list); kfree(indr_priv); @@ -743,14 +749,15 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev, return err; case TC_BLOCK_UNBIND: + indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev); + if (!indr_priv) + return -ENOENT; + tcf_block_cb_unregister(f->block, mlx5e_rep_indr_setup_block_cb, - netdev); - indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev); - if (indr_priv) { - list_del(&indr_priv->list); - kfree(indr_priv); - } + indr_priv); + list_del(&indr_priv->list); + kfree(indr_priv); return 0; default: @@ -779,7 +786,7 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv, err = __tc_indr_block_cb_register(netdev, rpriv, mlx5e_rep_indr_setup_tc_cb, - netdev); + rpriv); if (err) { struct mlx5e_priv *priv = netdev_priv(rpriv->netdev); @@ -789,10 +796,11 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv, return err; } -static void mlx5e_rep_indr_unregister_block(struct net_device *netdev) +static void mlx5e_rep_indr_unregister_block(struct mlx5e_rep_priv *rpriv, + struct net_device *netdev) { __tc_indr_block_cb_unregister(netdev, mlx5e_rep_indr_setup_tc_cb, - netdev); + rpriv); } static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb, @@ -811,7 +819,7 @@ static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb, mlx5e_rep_indr_register_block(rpriv, netdev); break; case NETDEV_UNREGISTER: - mlx5e_rep_indr_unregister_block(netdev); + mlx5e_rep_indr_unregister_block(rpriv, netdev); break; } return NOTIFY_OK; @@ -1122,9 +1130,17 @@ static int mlx5e_rep_get_phys_port_name(struct net_device *dev, struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5_eswitch_rep *rep = rpriv->rep; - int ret; + int ret, pf_num; + + ret = mlx5_lag_get_pf_num(priv->mdev, &pf_num); + if (ret) + return ret; + + if (rep->vport == FDB_UPLINK_VPORT) + ret = snprintf(buf, len, "p%d", pf_num); + else + ret = snprintf(buf, len, "pf%dvf%d", pf_num, rep->vport - 1); - ret = snprintf(buf, len, "%d", rep->vport - 1); if (ret >= len) return -EOPNOTSUPP; @@ -1281,6 +1297,18 @@ static int mlx5e_uplink_rep_set_mac(struct net_device *netdev, void *addr) return 0; } +static int mlx5e_uplink_rep_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos, + __be16 vlan_proto) +{ + netdev_warn_once(dev, "legacy vf vlan setting isn't supported in switchdev mode\n"); + + if (vlan != 0) + return -EOPNOTSUPP; + + /* allow setting 0-vid for compatibility with libvirt */ + return 0; +} + static const struct switchdev_ops mlx5e_rep_switchdev_ops = { .switchdev_port_attr_get = mlx5e_attr_get, }; @@ -1315,6 +1343,7 @@ static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = { .ndo_set_vf_rate = mlx5e_set_vf_rate, .ndo_get_vf_config = mlx5e_get_vf_config, .ndo_get_vf_stats = mlx5e_get_vf_stats, + .ndo_set_vf_vlan = mlx5e_uplink_rep_set_vf_vlan, }; bool mlx5e_eswitch_rep(struct net_device *netdev) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index edd722824697..36eafc877e6b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -148,6 +148,7 @@ struct mlx5e_encap_entry { unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ struct net_device *out_dev; + struct net_device *route_dev; int tunnel_type; int tunnel_hlen; int reformat_type; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 1d0bb5ff8c26..f86e4804e83e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -732,6 +732,8 @@ static u8 get_ip_proto(struct sk_buff *skb, int network_depth, __be16 proto) ((struct ipv6hdr *)ip_p)->nexthdr; } +#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN) + static inline void mlx5e_handle_csum(struct net_device *netdev, struct mlx5_cqe64 *cqe, struct mlx5e_rq *rq, @@ -754,6 +756,17 @@ static inline void mlx5e_handle_csum(struct net_device *netdev, if (unlikely(test_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &rq->state))) goto csum_unnecessary; + /* CQE csum doesn't cover padding octets in short ethernet + * frames. And the pad field is appended prior to calculating + * and appending the FCS field. + * + * Detecting these padded frames requires to verify and parse + * IP headers, so we simply force all those small frames to be + * CHECKSUM_UNNECESSARY even if they are not padded. + */ + if (short_frame(skb->len)) + goto csum_unnecessary; + if (likely(is_last_ethertype_ip(skb, &network_depth, &proto))) { if (unlikely(get_ip_proto(skb, network_depth, proto) == IPPROTO_SCTP)) goto csum_unnecessary; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index cae6c6d48984..b5c1b039375a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -128,6 +128,7 @@ struct mlx5e_tc_flow_parse_attr { struct net_device *filter_dev; struct mlx5_flow_spec spec; int num_mod_hdr_actions; + int max_mod_hdr_actions; void *mod_hdr_actions; int mirred_ifindex[MLX5_MAX_FLOW_FWD_VPORTS]; }; @@ -1302,7 +1303,7 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, static int parse_tunnel_attr(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec, struct tc_cls_flower_offload *f, - struct net_device *filter_dev) + struct net_device *filter_dev, u8 *match_level) { struct netlink_ext_ack *extack = f->common.extack; void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, @@ -1317,7 +1318,7 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv, int err = 0; err = mlx5e_tc_tun_parse(filter_dev, priv, spec, f, - headers_c, headers_v); + headers_c, headers_v, match_level); if (err) { NL_SET_ERR_MSG_MOD(extack, "failed to parse tunnel attributes"); @@ -1426,7 +1427,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec, struct tc_cls_flower_offload *f, struct net_device *filter_dev, - u8 *match_level) + u8 *match_level, u8 *tunnel_match_level) { struct netlink_ext_ack *extack = f->common.extack; void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, @@ -1477,7 +1478,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, switch (key->addr_type) { case FLOW_DISSECTOR_KEY_IPV4_ADDRS: case FLOW_DISSECTOR_KEY_IPV6_ADDRS: - if (parse_tunnel_attr(priv, spec, f, filter_dev)) + if (parse_tunnel_attr(priv, spec, f, filter_dev, tunnel_match_level)) return -EOPNOTSUPP; break; default: @@ -1826,11 +1827,11 @@ static int parse_cls_flower(struct mlx5e_priv *priv, struct mlx5_core_dev *dev = priv->mdev; struct mlx5_eswitch *esw = dev->priv.eswitch; struct mlx5e_rep_priv *rpriv = priv->ppriv; + u8 match_level, tunnel_match_level = MLX5_MATCH_NONE; struct mlx5_eswitch_rep *rep; - u8 match_level; int err; - err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level); + err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level, &tunnel_match_level); if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) { rep = rpriv->rep; @@ -1846,10 +1847,12 @@ static int parse_cls_flower(struct mlx5e_priv *priv, } } - if (flow->flags & MLX5E_TC_FLOW_ESWITCH) + if (flow->flags & MLX5E_TC_FLOW_ESWITCH) { flow->esw_attr->match_level = match_level; - else + flow->esw_attr->tunnel_match_level = tunnel_match_level; + } else { flow->nic_attr->match_level = match_level; + } return err; } @@ -1934,9 +1937,9 @@ static struct mlx5_fields fields[] = { OFFLOAD(UDP_DPORT, 2, udp.dest, 0), }; -/* On input attr->num_mod_hdr_actions tells how many HW actions can be parsed at - * max from the SW pedit action. On success, it says how many HW actions were - * actually parsed. +/* On input attr->max_mod_hdr_actions tells how many HW actions can be parsed at + * max from the SW pedit action. On success, attr->num_mod_hdr_actions + * says how many HW actions were actually parsed. */ static int offload_pedit_fields(struct pedit_headers *masks, struct pedit_headers *vals, @@ -1960,9 +1963,11 @@ static int offload_pedit_fields(struct pedit_headers *masks, add_vals = &vals[TCA_PEDIT_KEY_EX_CMD_ADD]; action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto); - action = parse_attr->mod_hdr_actions; - max_actions = parse_attr->num_mod_hdr_actions; - nactions = 0; + action = parse_attr->mod_hdr_actions + + parse_attr->num_mod_hdr_actions * action_size; + + max_actions = parse_attr->max_mod_hdr_actions; + nactions = parse_attr->num_mod_hdr_actions; for (i = 0; i < ARRAY_SIZE(fields); i++) { f = &fields[i]; @@ -2073,7 +2078,7 @@ static int alloc_mod_hdr_actions(struct mlx5e_priv *priv, if (!parse_attr->mod_hdr_actions) return -ENOMEM; - parse_attr->num_mod_hdr_actions = max_actions; + parse_attr->max_mod_hdr_actions = max_actions; return 0; } @@ -2119,9 +2124,11 @@ static int parse_tc_pedit_action(struct mlx5e_priv *priv, goto out_err; } - err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr); - if (err) - goto out_err; + if (!parse_attr->mod_hdr_actions) { + err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr); + if (err) + goto out_err; + } err = offload_pedit_fields(masks, vals, parse_attr, extack); if (err < 0) @@ -2179,6 +2186,7 @@ static bool csum_offload_supported(struct mlx5e_priv *priv, static bool modify_header_match_supported(struct mlx5_flow_spec *spec, struct tcf_exts *exts, + u32 actions, struct netlink_ext_ack *extack) { const struct tc_action *a; @@ -2188,7 +2196,11 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec, u16 ethertype; int nkeys, i; - headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers); + if (actions & MLX5_FLOW_CONTEXT_ACTION_DECAP) + headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, inner_headers); + else + headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers); + ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype); /* for non-IP we only re-write MACs, so we're okay */ @@ -2245,7 +2257,7 @@ static bool actions_match_supported(struct mlx5e_priv *priv, if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) return modify_header_match_supported(&parse_attr->spec, exts, - extack); + actions, extack); return true; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 598ad7e4d5c9..0e55cd1f2e98 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -387,8 +387,14 @@ netdev_tx_t mlx5e_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb, num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS); contig_wqebbs_room = mlx5_wq_cyc_get_contig_wqebbs(wq, pi); if (unlikely(contig_wqebbs_room < num_wqebbs)) { +#ifdef CONFIG_MLX5_EN_IPSEC + struct mlx5_wqe_eth_seg cur_eth = wqe->eth; +#endif mlx5e_fill_sq_frag_edge(sq, wq, pi, contig_wqebbs_room); mlx5e_sq_fetch_wqe(sq, &wqe, &pi); +#ifdef CONFIG_MLX5_EN_IPSEC + wqe->eth = cur_eth; +#endif } /* fill wqe */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index a44ea7b85614..5b492b67f4e1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1134,13 +1134,6 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw, int err = 0; u8 *smac_v; - if (vport->info.spoofchk && !is_valid_ether_addr(vport->info.mac)) { - mlx5_core_warn(esw->dev, - "vport[%d] configure ingress rules failed, illegal mac with spoofchk\n", - vport->vport); - return -EPERM; - } - esw_vport_cleanup_ingress_rules(esw, vport); if (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) { @@ -1728,7 +1721,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) int vport_num; int err; - if (!MLX5_ESWITCH_MANAGER(dev)) + if (!MLX5_VPORT_MANAGER(dev)) return 0; esw_info(dev, @@ -1797,7 +1790,7 @@ abort: void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) { - if (!esw || !MLX5_ESWITCH_MANAGER(esw->dev)) + if (!esw || !MLX5_VPORT_MANAGER(esw->dev)) return; esw_info(esw->dev, "cleanup\n"); @@ -1827,13 +1820,10 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, mutex_lock(&esw->state_lock); evport = &esw->vports[vport]; - if (evport->info.spoofchk && !is_valid_ether_addr(mac)) { + if (evport->info.spoofchk && !is_valid_ether_addr(mac)) mlx5_core_warn(esw->dev, - "MAC invalidation is not allowed when spoofchk is on, vport(%d)\n", + "Set invalid MAC while spoofchk is on, vport(%d)\n", vport); - err = -EPERM; - goto unlock; - } err = mlx5_modify_nic_vport_mac_address(esw->dev, vport, mac); if (err) { @@ -1979,6 +1969,10 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw, evport = &esw->vports[vport]; pschk = evport->info.spoofchk; evport->info.spoofchk = spoofchk; + if (pschk && !is_valid_ether_addr(evport->info.mac)) + mlx5_core_warn(esw->dev, + "Spoofchk in set while MAC is invalid, vport(%d)\n", + evport->vport); if (evport->enabled && esw->mode == SRIOV_LEGACY) err = esw_vport_ingress_config(esw, evport); if (err) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 9c89eea9b2c3..748ff178a1d6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -312,6 +312,7 @@ struct mlx5_esw_flow_attr { } dests[MLX5_MAX_FLOW_FWD_VPORTS]; u32 mod_hdr_id; u8 match_level; + u8 tunnel_match_level; struct mlx5_fc *counter; u32 chain; u16 prio; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 53065b6ae593..d4e6fe5b9300 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -160,14 +160,15 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_eswitch_owner_vhca_id); - if (attr->match_level == MLX5_MATCH_NONE) - spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS; - else - spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS | - MLX5_MATCH_MISC_PARAMETERS; - - if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) - spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS; + spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS; + if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) { + if (attr->tunnel_match_level != MLX5_MATCH_NONE) + spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; + if (attr->match_level != MLX5_MATCH_NONE) + spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS; + } else if (attr->match_level != MLX5_MATCH_NONE) { + spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; + } if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) flow_act.modify_id = attr->mod_hdr_id; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c index fbc42b7252a9..503035469d2d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/events.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c @@ -211,11 +211,10 @@ static int port_module(struct notifier_block *nb, unsigned long type, void *data enum port_module_event_status_type module_status; enum port_module_event_error_type error_type; struct mlx5_eqe_port_module *module_event_eqe; - const char *status_str, *error_str; + const char *status_str; u8 module_num; module_event_eqe = &eqe->data.port_module; - module_num = module_event_eqe->module; module_status = module_event_eqe->module_status & PORT_MODULE_EVENT_MODULE_STATUS_MASK; error_type = module_event_eqe->error_type & @@ -223,25 +222,27 @@ static int port_module(struct notifier_block *nb, unsigned long type, void *data if (module_status < MLX5_MODULE_STATUS_NUM) events->pme_stats.status_counters[module_status]++; - status_str = mlx5_pme_status_to_string(module_status); - if (module_status == MLX5_MODULE_STATUS_ERROR) { + if (module_status == MLX5_MODULE_STATUS_ERROR) if (error_type < MLX5_MODULE_EVENT_ERROR_NUM) events->pme_stats.error_counters[error_type]++; - error_str = mlx5_pme_error_to_string(error_type); - } if (!printk_ratelimit()) return NOTIFY_OK; - if (module_status == MLX5_MODULE_STATUS_ERROR) + module_num = module_event_eqe->module; + status_str = mlx5_pme_status_to_string(module_status); + if (module_status == MLX5_MODULE_STATUS_ERROR) { + const char *error_str = mlx5_pme_error_to_string(error_type); + mlx5_core_err(events->dev, "Port module event[error]: module %u, %s, %s\n", module_num, status_str, error_str); - else + } else { mlx5_core_info(events->dev, "Port module event: module %u, %s\n", module_num, status_str); + } return NOTIFY_OK; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 196c07383082..cb9fa3430c53 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -103,7 +103,7 @@ void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force) mlx5_core_err(dev, "start\n"); if (pci_channel_offline(dev->pdev) || in_fatal(dev) || force) { dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; - mlx5_cmd_trigger_completions(dev); + mlx5_cmd_flush(dev); } mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_SYS_ERROR, (void *)1); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c index 3a6baed722d8..2d223385dc81 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c @@ -616,6 +616,27 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev) } } +int mlx5_lag_get_pf_num(struct mlx5_core_dev *dev, int *pf_num) +{ + struct mlx5_lag *ldev; + int n; + + ldev = mlx5_lag_dev_get(dev); + if (!ldev) { + mlx5_core_warn(dev, "no lag device, can't get pf num\n"); + return -EINVAL; + } + + for (n = 0; n < MLX5_MAX_PORTS; n++) + if (ldev->pf[n].dev == dev) { + *pf_num = n; + return 0; + } + + mlx5_core_warn(dev, "wasn't able to locate pf in the lag device\n"); + return -EINVAL; +} + /* Must be called with intf_mutex held */ void mlx5_lag_remove(struct mlx5_core_dev *dev) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index c68dcea5985b..4fdac020b795 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -126,6 +126,7 @@ u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev, struct ptp_system_timestamp *sts); void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev); +void mlx5_cmd_flush(struct mlx5_core_dev *dev); int mlx5_cq_debugfs_init(struct mlx5_core_dev *dev); void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev); @@ -187,6 +188,8 @@ static inline int mlx5_lag_is_lacp_owner(struct mlx5_core_dev *dev) MLX5_CAP_GEN(dev, lag_master); } +int mlx5_lag_get_pf_num(struct mlx5_core_dev *dev, int *pf_num); + void mlx5_reload_interface(struct mlx5_core_dev *mdev, int protocol); void mlx5_lag_update(struct mlx5_core_dev *dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c index 388f205a497f..370ca94b6775 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/qp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c @@ -44,14 +44,15 @@ static struct mlx5_core_rsc_common * mlx5_get_rsc(struct mlx5_qp_table *table, u32 rsn) { struct mlx5_core_rsc_common *common; + unsigned long flags; - spin_lock(&table->lock); + spin_lock_irqsave(&table->lock, flags); common = radix_tree_lookup(&table->tree, rsn); if (common) atomic_inc(&common->refcount); - spin_unlock(&table->lock); + spin_unlock_irqrestore(&table->lock, flags); return common; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig index 080ddd1942ec..b9a25aed5d11 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig +++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig @@ -78,6 +78,7 @@ config MLXSW_SPECTRUM depends on IPV6 || IPV6=n depends on NET_IPGRE || NET_IPGRE=n depends on IPV6_GRE || IPV6_GRE=n + depends on VXLAN || VXLAN=n select GENERIC_ALLOCATOR select PARMAN select OBJAGG diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 66b8098c6fd2..a2321fe8d6a0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -604,29 +604,31 @@ static void mlxsw_pci_cq_tasklet(unsigned long data) u16 wqe_counter = mlxsw_pci_cqe_wqe_counter_get(cqe); u8 sendq = mlxsw_pci_cqe_sr_get(q->u.cq.v, cqe); u8 dqn = mlxsw_pci_cqe_dqn_get(q->u.cq.v, cqe); + char ncqe[MLXSW_PCI_CQE_SIZE_MAX]; + + memcpy(ncqe, cqe, q->elem_size); + mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q); if (sendq) { struct mlxsw_pci_queue *sdq; sdq = mlxsw_pci_sdq_get(mlxsw_pci, dqn); mlxsw_pci_cqe_sdq_handle(mlxsw_pci, sdq, - wqe_counter, cqe); + wqe_counter, ncqe); q->u.cq.comp_sdq_count++; } else { struct mlxsw_pci_queue *rdq; rdq = mlxsw_pci_rdq_get(mlxsw_pci, dqn); mlxsw_pci_cqe_rdq_handle(mlxsw_pci, rdq, - wqe_counter, q->u.cq.v, cqe); + wqe_counter, q->u.cq.v, ncqe); q->u.cq.comp_rdq_count++; } if (++items == credits) break; } - if (items) { - mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q); + if (items) mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q); - } } static u16 mlxsw_pci_cq_elem_count(const struct mlxsw_pci_queue *q) @@ -1365,10 +1367,10 @@ static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci, u32 val = mlxsw_pci_read32(mlxsw_pci, FW_READY); if ((val & MLXSW_PCI_FW_READY_MASK) == MLXSW_PCI_FW_READY_MAGIC) - break; + return 0; cond_resched(); } while (time_before(jiffies, end)); - return 0; + return -EBUSY; } static int mlxsw_pci_alloc_irq_vectors(struct mlxsw_pci *mlxsw_pci) diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h index bb99f6d41fe0..ffee38e36ce8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h +++ b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h @@ -27,7 +27,7 @@ #define MLXSW_PCI_SW_RESET 0xF0010 #define MLXSW_PCI_SW_RESET_RST_BIT BIT(0) -#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 5000 +#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 13000 #define MLXSW_PCI_SW_RESET_WAIT_MSECS 100 #define MLXSW_PCI_FW_READY 0xA1844 #define MLXSW_PCI_FW_READY_MASK 0xFFFF @@ -53,6 +53,7 @@ #define MLXSW_PCI_WQE_SIZE 32 /* 32 bytes per element */ #define MLXSW_PCI_CQE01_SIZE 16 /* 16 bytes per element */ #define MLXSW_PCI_CQE2_SIZE 32 /* 32 bytes per element */ +#define MLXSW_PCI_CQE_SIZE_MAX MLXSW_PCI_CQE2_SIZE #define MLXSW_PCI_EQE_SIZE 16 /* 16 bytes per element */ #define MLXSW_PCI_WQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE) #define MLXSW_PCI_CQE01_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE01_SIZE) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index eed1045e4d96..b65e274b02e9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -862,8 +862,9 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { bool configure = false; bool pfc = false; + u16 thres_cells; + u16 delay_cells; bool lossy; - u16 thres; for (j = 0; j < IEEE_8021QAZ_MAX_TCS; j++) { if (prio_tc[j] == i) { @@ -877,10 +878,11 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, continue; lossy = !(pfc || pause_en); - thres = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu); - delay = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay, pfc, - pause_en); - mlxsw_sp_pg_buf_pack(pbmc_pl, i, thres + delay, thres, lossy); + thres_cells = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu); + delay_cells = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay, + pfc, pause_en); + mlxsw_sp_pg_buf_pack(pbmc_pl, i, thres_cells + delay_cells, + thres_cells, lossy); } return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); @@ -5005,12 +5007,15 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev, lower_dev, upper_dev); } else if (netif_is_lag_master(upper_dev)) { - if (info->linking) + if (info->linking) { err = mlxsw_sp_port_lag_join(mlxsw_sp_port, upper_dev); - else + } else { + mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port, + false); mlxsw_sp_port_lag_leave(mlxsw_sp_port, upper_dev); + } } else if (netif_is_ovs_master(upper_dev)) { if (info->linking) err = mlxsw_sp_port_ovs_join(mlxsw_sp_port); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c index b0f2d8e8ded0..ac222833a5cf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c @@ -72,7 +72,15 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, act_set = mlxsw_afa_block_first_set(rulei->act_block); mlxsw_reg_ptce2_flex_action_set_memcpy_to(ptce2_pl, act_set); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl); + if (err) + goto err_ptce2_write; + + return 0; + +err_ptce2_write: + cregion->ops->entry_remove(cregion, centry); + return err; } static void diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c index 1c19feefa5f2..2941967e1cc5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c @@ -1022,7 +1022,6 @@ void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion, { struct objagg_obj *objagg_obj = (struct objagg_obj *) erp_mask; - ASSERT_RTNL(); objagg_obj_put(aregion->erp_table->objagg, objagg_obj); } @@ -1054,7 +1053,6 @@ void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_acl_erp *erp = objagg_obj_root_priv(objagg_obj); unsigned int erp_bank; - ASSERT_RTNL(); if (!mlxsw_sp_acl_erp_table_is_used(erp->erp_table)) return; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c index 055cc6943b34..9d9aa28684af 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c @@ -997,8 +997,8 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = { static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = { .type = MLXSW_SP_FID_TYPE_DUMMY, .fid_size = sizeof(struct mlxsw_sp_fid), - .start_index = MLXSW_SP_RFID_BASE - 1, - .end_index = MLXSW_SP_RFID_BASE - 1, + .start_index = VLAN_N_VID - 1, + .end_index = VLAN_N_VID - 1, .ops = &mlxsw_sp_fid_dummy_ops, }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c index 0a31fff2516e..fb1c48c698f2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c @@ -816,14 +816,14 @@ int mlxsw_sp_nve_fid_enable(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid, ops = nve->nve_ops_arr[params->type]; if (!ops->can_offload(nve, params->dev, extack)) - return -EOPNOTSUPP; + return -EINVAL; memset(&config, 0, sizeof(config)); ops->nve_config(nve, params->dev, &config); if (nve->num_nve_tunnels && memcmp(&config, &nve->config, sizeof(config))) { NL_SET_ERR_MSG_MOD(extack, "Conflicting NVE tunnels configuration"); - return -EOPNOTSUPP; + return -EINVAL; } err = mlxsw_sp_nve_tunnel_init(mlxsw_sp, &config); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 1bd2c6e15f8d..c772109b638d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1078,8 +1078,7 @@ static int mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp_bridge_port *bridge_port, u16 vid, bool is_untagged, bool is_pvid, - struct netlink_ext_ack *extack, - struct switchdev_trans *trans) + struct netlink_ext_ack *extack) { u16 pvid = mlxsw_sp_port_pvid_determine(mlxsw_sp_port, vid, is_pvid); struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; @@ -1095,9 +1094,6 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port, mlxsw_sp_port_vlan->bridge_port != bridge_port) return -EEXIST; - if (switchdev_trans_ph_prepare(trans)) - return 0; - if (!mlxsw_sp_port_vlan) { mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port, vid); @@ -1188,6 +1184,9 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port, return err; } + if (switchdev_trans_ph_commit(trans)) + return 0; + bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev); if (WARN_ON(!bridge_port)) return -EINVAL; @@ -1200,7 +1199,7 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port, err = mlxsw_sp_bridge_port_vlan_add(mlxsw_sp_port, bridge_port, vid, flag_untagged, - flag_pvid, extack, trans); + flag_pvid, extack); if (err) return err; } @@ -1234,7 +1233,7 @@ mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp, static enum mlxsw_reg_sfd_rec_policy mlxsw_sp_sfd_rec_policy(bool dynamic) { return dynamic ? MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS : - MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY; + MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_MLAG; } static enum mlxsw_reg_sfd_op mlxsw_sp_sfd_op(bool adding) @@ -1291,7 +1290,7 @@ out: static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port, const char *mac, u16 fid, bool adding, enum mlxsw_reg_sfd_rec_action action, - bool dynamic) + enum mlxsw_reg_sfd_rec_policy policy) { char *sfd_pl; u8 num_rec; @@ -1302,8 +1301,7 @@ static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port, return -ENOMEM; mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0); - mlxsw_reg_sfd_uc_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic), - mac, fid, action, local_port); + mlxsw_reg_sfd_uc_pack(sfd_pl, 0, policy, mac, fid, action, local_port); num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl); if (err) @@ -1322,7 +1320,8 @@ static int mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port, bool dynamic) { return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid, adding, - MLXSW_REG_SFD_REC_ACTION_NOP, dynamic); + MLXSW_REG_SFD_REC_ACTION_NOP, + mlxsw_sp_sfd_rec_policy(dynamic)); } int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid, @@ -1330,7 +1329,7 @@ int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid, { return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, 0, mac, fid, adding, MLXSW_REG_SFD_REC_ACTION_FORWARD_IP_ROUTER, - false); + MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY); } static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id, @@ -1808,7 +1807,7 @@ static void mlxsw_sp_bridge_port_vlan_del(struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp_bridge_port *bridge_port, u16 vid) { - u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : vid; + u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : mlxsw_sp_port->pvid; struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid); @@ -3207,7 +3206,6 @@ mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_bridge_device *bridge_device, const struct net_device *vxlan_dev, u16 vid, bool flag_untagged, bool flag_pvid, - struct switchdev_trans *trans, struct netlink_ext_ack *extack) { struct vxlan_dev *vxlan = netdev_priv(vxlan_dev); @@ -3225,9 +3223,6 @@ mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_bridge_8021q_vxlan_dev_find(bridge_device->dev, vid)) return -EINVAL; - if (switchdev_trans_ph_prepare(trans)) - return 0; - if (!netif_running(vxlan_dev)) return 0; @@ -3345,6 +3340,9 @@ mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev, port_obj_info->handled = true; + if (switchdev_trans_ph_commit(trans)) + return 0; + bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev); if (!bridge_device) return -EINVAL; @@ -3358,8 +3356,7 @@ mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev, err = mlxsw_sp_switchdev_vxlan_vlan_add(mlxsw_sp, bridge_device, vxlan_dev, vid, flag_untagged, - flag_pvid, trans, - extack); + flag_pvid, extack); if (err) return err; } diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c index f6ecfa778660..8f72587b5a2c 100644 --- a/drivers/net/ethernet/microchip/enc28j60.c +++ b/drivers/net/ethernet/microchip/enc28j60.c @@ -1681,5 +1681,5 @@ MODULE_DESCRIPTION(DRV_NAME " ethernet driver"); MODULE_AUTHOR("Claudio Lanconelli <lanconelli.claudio@eptar.com>"); MODULE_LICENSE("GPL"); module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., ffff=all)"); +MODULE_PARM_DESC(debug, "Debug verbosity level in amount of bits set (0=none, ..., 31=all)"); MODULE_ALIAS("spi:" DRV_NAME); diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index 20c9377e99cb..4d1b4a24907f 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -962,13 +962,10 @@ static void lan743x_phy_link_status_change(struct net_device *netdev) memset(&ksettings, 0, sizeof(ksettings)); phy_ethtool_get_link_ksettings(netdev, &ksettings); - local_advertisement = phy_read(phydev, MII_ADVERTISE); - if (local_advertisement < 0) - return; - - remote_advertisement = phy_read(phydev, MII_LPA); - if (remote_advertisement < 0) - return; + local_advertisement = + linkmode_adv_to_mii_adv_t(phydev->advertising); + remote_advertisement = + linkmode_adv_to_mii_adv_t(phydev->lp_advertising); lan743x_phy_update_flowcontrol(adapter, ksettings.base.duplex, @@ -1403,7 +1400,8 @@ static int lan743x_tx_frame_start(struct lan743x_tx *tx, } static void lan743x_tx_frame_add_lso(struct lan743x_tx *tx, - unsigned int frame_length) + unsigned int frame_length, + int nr_frags) { /* called only from within lan743x_tx_xmit_frame. * assuming tx->ring_lock has already been acquired. @@ -1413,6 +1411,10 @@ static void lan743x_tx_frame_add_lso(struct lan743x_tx *tx, /* wrap up previous descriptor */ tx->frame_data0 |= TX_DESC_DATA0_EXT_; + if (nr_frags <= 0) { + tx->frame_data0 |= TX_DESC_DATA0_LS_; + tx->frame_data0 |= TX_DESC_DATA0_IOC_; + } tx_descriptor = &tx->ring_cpu_ptr[tx->frame_tail]; tx_descriptor->data0 = tx->frame_data0; @@ -1517,8 +1519,11 @@ static void lan743x_tx_frame_end(struct lan743x_tx *tx, u32 tx_tail_flags = 0; /* wrap up previous descriptor */ - tx->frame_data0 |= TX_DESC_DATA0_LS_; - tx->frame_data0 |= TX_DESC_DATA0_IOC_; + if ((tx->frame_data0 & TX_DESC_DATA0_DTYPE_MASK_) == + TX_DESC_DATA0_DTYPE_DATA_) { + tx->frame_data0 |= TX_DESC_DATA0_LS_; + tx->frame_data0 |= TX_DESC_DATA0_IOC_; + } tx_descriptor = &tx->ring_cpu_ptr[tx->frame_tail]; buffer_info = &tx->buffer_info[tx->frame_tail]; @@ -1603,7 +1608,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx, } if (gso) - lan743x_tx_frame_add_lso(tx, frame_length); + lan743x_tx_frame_add_lso(tx, frame_length, nr_frags); if (nr_frags <= 0) goto finish; diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 5f384f73007d..19ce0e605096 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -3604,9 +3604,9 @@ static int myri10ge_alloc_slices(struct myri10ge_priv *mgp) for (i = 0; i < mgp->num_slices; i++) { ss = &mgp->ss[i]; bytes = mgp->max_intr_slots * sizeof(*ss->rx_done.entry); - ss->rx_done.entry = dma_zalloc_coherent(&pdev->dev, bytes, - &ss->rx_done.bus, - GFP_KERNEL); + ss->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes, + &ss->rx_done.bus, + GFP_KERNEL); if (ss->rx_done.entry == NULL) goto abort; bytes = sizeof(*ss->fw_stats); diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c index e23ca90289f7..0a868c829b90 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c @@ -1291,15 +1291,10 @@ wrp_alu64_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, static int wrp_alu32_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, - enum alu_op alu_op, bool skip) + enum alu_op alu_op) { const struct bpf_insn *insn = &meta->insn; - if (skip) { - meta->skip = true; - return 0; - } - wrp_alu_imm(nfp_prog, insn->dst_reg * 2, alu_op, insn->imm); wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0); @@ -2309,7 +2304,7 @@ static int xor_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) static int xor_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) { - return wrp_alu32_imm(nfp_prog, meta, ALU_OP_XOR, !~meta->insn.imm); + return wrp_alu32_imm(nfp_prog, meta, ALU_OP_XOR); } static int and_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) @@ -2319,7 +2314,7 @@ static int and_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) static int and_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) { - return wrp_alu32_imm(nfp_prog, meta, ALU_OP_AND, !~meta->insn.imm); + return wrp_alu32_imm(nfp_prog, meta, ALU_OP_AND); } static int or_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) @@ -2329,7 +2324,7 @@ static int or_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) static int or_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) { - return wrp_alu32_imm(nfp_prog, meta, ALU_OP_OR, !meta->insn.imm); + return wrp_alu32_imm(nfp_prog, meta, ALU_OP_OR); } static int add_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) @@ -2339,7 +2334,7 @@ static int add_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) static int add_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) { - return wrp_alu32_imm(nfp_prog, meta, ALU_OP_ADD, !meta->insn.imm); + return wrp_alu32_imm(nfp_prog, meta, ALU_OP_ADD); } static int sub_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) @@ -2349,7 +2344,7 @@ static int sub_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) static int sub_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) { - return wrp_alu32_imm(nfp_prog, meta, ALU_OP_SUB, !meta->insn.imm); + return wrp_alu32_imm(nfp_prog, meta, ALU_OP_SUB); } static int mul_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index e97636d2e6ee..7d2d4241498f 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -2170,9 +2170,9 @@ nfp_net_tx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_tx_ring *tx_ring) tx_ring->cnt = dp->txd_cnt; tx_ring->size = array_size(tx_ring->cnt, sizeof(*tx_ring->txds)); - tx_ring->txds = dma_zalloc_coherent(dp->dev, tx_ring->size, - &tx_ring->dma, - GFP_KERNEL | __GFP_NOWARN); + tx_ring->txds = dma_alloc_coherent(dp->dev, tx_ring->size, + &tx_ring->dma, + GFP_KERNEL | __GFP_NOWARN); if (!tx_ring->txds) { netdev_warn(dp->netdev, "failed to allocate TX descriptor ring memory, requested descriptor count: %d, consider lowering descriptor count\n", tx_ring->cnt); @@ -2328,9 +2328,9 @@ nfp_net_rx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_rx_ring *rx_ring) rx_ring->cnt = dp->rxd_cnt; rx_ring->size = array_size(rx_ring->cnt, sizeof(*rx_ring->rxds)); - rx_ring->rxds = dma_zalloc_coherent(dp->dev, rx_ring->size, - &rx_ring->dma, - GFP_KERNEL | __GFP_NOWARN); + rx_ring->rxds = dma_alloc_coherent(dp->dev, rx_ring->size, + &rx_ring->dma, + GFP_KERNEL | __GFP_NOWARN); if (!rx_ring->rxds) { netdev_warn(dp->netdev, "failed to allocate RX descriptor ring memory, requested descriptor count: %d, consider lowering descriptor count\n", rx_ring->cnt); diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c index 0611f2335b4a..1e408d1a9b5f 100644 --- a/drivers/net/ethernet/ni/nixge.c +++ b/drivers/net/ethernet/ni/nixge.c @@ -287,9 +287,9 @@ static int nixge_hw_dma_bd_init(struct net_device *ndev) priv->rx_bd_ci = 0; /* Allocate the Tx and Rx buffer descriptors. */ - priv->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent, - sizeof(*priv->tx_bd_v) * TX_BD_NUM, - &priv->tx_bd_p, GFP_KERNEL); + priv->tx_bd_v = dma_alloc_coherent(ndev->dev.parent, + sizeof(*priv->tx_bd_v) * TX_BD_NUM, + &priv->tx_bd_p, GFP_KERNEL); if (!priv->tx_bd_v) goto out; @@ -299,9 +299,9 @@ static int nixge_hw_dma_bd_init(struct net_device *ndev) if (!priv->tx_skb) goto out; - priv->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent, - sizeof(*priv->rx_bd_v) * RX_BD_NUM, - &priv->rx_bd_p, GFP_KERNEL); + priv->rx_bd_v = dma_alloc_coherent(ndev->dev.parent, + sizeof(*priv->rx_bd_v) * RX_BD_NUM, + &priv->rx_bd_p, GFP_KERNEL); if (!priv->rx_bd_v) goto out; diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 43c0c10dfeb7..552d930e3940 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -1440,8 +1440,8 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter, size = rx_ring->count * bufsz + PCH_GBE_RESERVE_MEMORY; rx_ring->rx_buff_pool = - dma_zalloc_coherent(&pdev->dev, size, - &rx_ring->rx_buff_pool_logic, GFP_KERNEL); + dma_alloc_coherent(&pdev->dev, size, + &rx_ring->rx_buff_pool_logic, GFP_KERNEL); if (!rx_ring->rx_buff_pool) return -ENOMEM; @@ -1755,8 +1755,8 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter, tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc); - tx_ring->desc = dma_zalloc_coherent(&pdev->dev, tx_ring->size, - &tx_ring->dma, GFP_KERNEL); + tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size, + &tx_ring->dma, GFP_KERNEL); if (!tx_ring->desc) { vfree(tx_ring->buffer_info); return -ENOMEM; @@ -1798,8 +1798,8 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter, return -ENOMEM; rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc); - rx_ring->desc = dma_zalloc_coherent(&pdev->dev, rx_ring->size, - &rx_ring->dma, GFP_KERNEL); + rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, + &rx_ring->dma, GFP_KERNEL); if (!rx_ring->desc) { vfree(rx_ring->buffer_info); return -ENOMEM; diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index 8a31a02c9f47..d21041554507 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -401,9 +401,9 @@ static int pasemi_mac_setup_rx_resources(const struct net_device *dev) if (pasemi_dma_alloc_ring(&ring->chan, RX_RING_SIZE)) goto out_ring_desc; - ring->buffers = dma_zalloc_coherent(&mac->dma_pdev->dev, - RX_RING_SIZE * sizeof(u64), - &ring->buf_dma, GFP_KERNEL); + ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev, + RX_RING_SIZE * sizeof(u64), + &ring->buf_dma, GFP_KERNEL); if (!ring->buffers) goto out_ring_desc; diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index 24a90163775e..2d8a77cc156b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -53,7 +53,7 @@ extern const struct qed_common_ops qed_common_ops_pass; #define QED_MAJOR_VERSION 8 -#define QED_MINOR_VERSION 33 +#define QED_MINOR_VERSION 37 #define QED_REVISION_VERSION 0 #define QED_ENGINEERING_VERSION 20 diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c index dc1c1b616084..c2ad405b2f50 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_cxt.c +++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c @@ -936,9 +936,9 @@ static int qed_cxt_src_t2_alloc(struct qed_hwfn *p_hwfn) u32 size = min_t(u32, total_size, psz); void **p_virt = &p_mngr->t2[i].p_virt; - *p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev, - size, &p_mngr->t2[i].p_phys, - GFP_KERNEL); + *p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, size, + &p_mngr->t2[i].p_phys, + GFP_KERNEL); if (!p_mngr->t2[i].p_virt) { rc = -ENOMEM; goto t2_fail; @@ -1054,8 +1054,8 @@ static int qed_ilt_blk_alloc(struct qed_hwfn *p_hwfn, u32 size; size = min_t(u32, sz_left, p_blk->real_size_in_page); - p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev, size, - &p_phys, GFP_KERNEL); + p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, size, + &p_phys, GFP_KERNEL); if (!p_virt) return -ENOMEM; @@ -2306,9 +2306,9 @@ qed_cxt_dynamic_ilt_alloc(struct qed_hwfn *p_hwfn, goto out0; } - p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev, - p_blk->real_size_in_page, &p_phys, - GFP_KERNEL); + p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, + p_blk->real_size_in_page, &p_phys, + GFP_KERNEL); if (!p_virt) { rc = -ENOMEM; goto out1; diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 8f6551421945..2ecaaaa4469a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -795,19 +795,19 @@ static void qed_init_qm_pq(struct qed_hwfn *p_hwfn, /* get pq index according to PQ_FLAGS */ static u16 *qed_init_qm_get_idx_from_flags(struct qed_hwfn *p_hwfn, - u32 pq_flags) + unsigned long pq_flags) { struct qed_qm_info *qm_info = &p_hwfn->qm_info; /* Can't have multiple flags set here */ - if (bitmap_weight((unsigned long *)&pq_flags, + if (bitmap_weight(&pq_flags, sizeof(pq_flags) * BITS_PER_BYTE) > 1) { - DP_ERR(p_hwfn, "requested multiple pq flags 0x%x\n", pq_flags); + DP_ERR(p_hwfn, "requested multiple pq flags 0x%lx\n", pq_flags); goto err; } if (!(qed_get_pq_flags(p_hwfn) & pq_flags)) { - DP_ERR(p_hwfn, "pq flag 0x%x is not set\n", pq_flags); + DP_ERR(p_hwfn, "pq flag 0x%lx is not set\n", pq_flags); goto err; } diff --git a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c index beb8e5d6401a..ded556b7bab5 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c @@ -1688,6 +1688,15 @@ qed_iwarp_parse_rx_pkt(struct qed_hwfn *p_hwfn, eth_hlen = ETH_HLEN + (vlan_valid ? sizeof(u32) : 0); + if (!ether_addr_equal(ethh->h_dest, + p_hwfn->p_rdma_info->iwarp.mac_addr)) { + DP_VERBOSE(p_hwfn, + QED_MSG_RDMA, + "Got unexpected mac %pM instead of %pM\n", + ethh->h_dest, p_hwfn->p_rdma_info->iwarp.mac_addr); + return -EINVAL; + } + ether_addr_copy(remote_mac_addr, ethh->h_source); ether_addr_copy(local_mac_addr, ethh->h_dest); @@ -2605,7 +2614,7 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, struct qed_iwarp_info *iwarp_info; struct qed_ll2_acquire_data data; struct qed_ll2_cbs cbs; - u32 mpa_buff_size; + u32 buff_size; u16 n_ooo_bufs; int rc = 0; int i; @@ -2632,7 +2641,7 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, memset(&data, 0, sizeof(data)); data.input.conn_type = QED_LL2_TYPE_IWARP; - data.input.mtu = QED_IWARP_MAX_SYN_PKT_SIZE; + data.input.mtu = params->max_mtu; data.input.rx_num_desc = QED_IWARP_LL2_SYN_RX_SIZE; data.input.tx_num_desc = QED_IWARP_LL2_SYN_TX_SIZE; data.input.tx_max_bds_per_packet = 1; /* will never be fragmented */ @@ -2654,9 +2663,10 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, goto err; } + buff_size = QED_IWARP_MAX_BUF_SIZE(params->max_mtu); rc = qed_iwarp_ll2_alloc_buffers(p_hwfn, QED_IWARP_LL2_SYN_RX_SIZE, - QED_IWARP_MAX_SYN_PKT_SIZE, + buff_size, iwarp_info->ll2_syn_handle); if (rc) goto err; @@ -2710,10 +2720,9 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, if (rc) goto err; - mpa_buff_size = QED_IWARP_MAX_BUF_SIZE(params->max_mtu); rc = qed_iwarp_ll2_alloc_buffers(p_hwfn, data.input.rx_num_desc, - mpa_buff_size, + buff_size, iwarp_info->ll2_mpa_handle); if (rc) goto err; @@ -2726,7 +2735,7 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, iwarp_info->max_num_partial_fpdus = (u16)p_hwfn->p_rdma_info->num_qps; - iwarp_info->mpa_intermediate_buf = kzalloc(mpa_buff_size, GFP_KERNEL); + iwarp_info->mpa_intermediate_buf = kzalloc(buff_size, GFP_KERNEL); if (!iwarp_info->mpa_intermediate_buf) goto err; diff --git a/drivers/net/ethernet/qlogic/qed/qed_iwarp.h b/drivers/net/ethernet/qlogic/qed/qed_iwarp.h index b8f612d00241..7ac959038324 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.h @@ -46,7 +46,6 @@ enum qed_iwarp_qp_state qed_roce2iwarp_state(enum qed_roce_qp_state state); #define QED_IWARP_LL2_SYN_TX_SIZE (128) #define QED_IWARP_LL2_SYN_RX_SIZE (256) -#define QED_IWARP_MAX_SYN_PKT_SIZE (128) #define QED_IWARP_LL2_OOO_DEF_TX_SIZE (256) #define QED_IWARP_MAX_OOO (16) diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 67c02ea93906..58be1c4c6668 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -609,6 +609,10 @@ qed_sp_update_accept_mode(struct qed_hwfn *p_hwfn, (!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) && !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED))); + SET_FIELD(state, ETH_VPORT_TX_MODE_UCAST_ACCEPT_ALL, + (!!(accept_filter & QED_ACCEPT_UCAST_MATCHED) && + !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED))); + SET_FIELD(state, ETH_VPORT_TX_MODE_BCAST_ACCEPT_ALL, !!(accept_filter & QED_ACCEPT_BCAST)); @@ -744,6 +748,11 @@ int qed_sp_vport_update(struct qed_hwfn *p_hwfn, return rc; } + if (p_params->update_ctl_frame_check) { + p_cmn->ctl_frame_mac_check_en = p_params->mac_chk_en; + p_cmn->ctl_frame_ethtype_check_en = p_params->ethtype_chk_en; + } + /* Update mcast bins for VFs, PF doesn't use this functionality */ qed_sp_update_mcast_bin(p_hwfn, p_ramrod, p_params); @@ -2207,7 +2216,7 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev, u16 num_queues = 0; /* Since the feature controls only queue-zones, - * make sure we have the contexts [rx, tx, xdp] to + * make sure we have the contexts [rx, xdp, tcs] to * match. */ for_each_hwfn(cdev, i) { @@ -2217,7 +2226,8 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev, u16 cids; cids = hwfn->pf_params.eth_pf_params.num_cons; - num_queues += min_t(u16, l2_queues, cids / 3); + cids /= (2 + info->num_tc); + num_queues += min_t(u16, l2_queues, cids); } /* queues might theoretically be >256, but interrupts' @@ -2688,7 +2698,8 @@ static int qed_configure_filter_rx_mode(struct qed_dev *cdev, if (type == QED_FILTER_RX_MODE_TYPE_PROMISC) { accept_flags.rx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED | QED_ACCEPT_MCAST_UNMATCHED; - accept_flags.tx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED; + accept_flags.tx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED | + QED_ACCEPT_MCAST_UNMATCHED; } else if (type == QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC) { accept_flags.rx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED; accept_flags.tx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED; @@ -2860,7 +2871,8 @@ static int qed_get_coalesce(struct qed_dev *cdev, u16 *coal, void *handle) p_hwfn = p_cid->p_owner; rc = qed_get_queue_coalesce(p_hwfn, coal, handle); if (rc) - DP_NOTICE(p_hwfn, "Unable to read queue coalescing\n"); + DP_VERBOSE(cdev, QED_MSG_DEBUG, + "Unable to read queue coalescing\n"); return rc; } diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.h b/drivers/net/ethernet/qlogic/qed/qed_l2.h index 8d80f1095d17..7127d5aaac42 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.h +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.h @@ -219,6 +219,9 @@ struct qed_sp_vport_update_params { struct qed_rss_params *rss_params; struct qed_filter_accept_flags accept_flags; struct qed_sge_tpa_params *sge_tpa_params; + u8 update_ctl_frame_check; + u8 mac_chk_en; + u8 ethtype_chk_en; }; int qed_sp_vport_update(struct qed_hwfn *p_hwfn, diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c index 90afd514ffe1..b5f419b71287 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c @@ -1619,6 +1619,10 @@ static void qed_ll2_post_rx_buffer_notify_fw(struct qed_hwfn *p_hwfn, cq_prod = qed_chain_get_prod_idx(&p_rx->rcq_chain); rx_prod.bd_prod = cpu_to_le16(bd_prod); rx_prod.cqe_prod = cpu_to_le16(cq_prod); + + /* Make sure chain element is updated before ringing the doorbell */ + dma_wmb(); + DIRECT_REG_WR(p_rx->set_prod_addr, *((u32 *)&rx_prod)); } @@ -2447,19 +2451,24 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb, { struct qed_ll2_tx_pkt_info pkt; const skb_frag_t *frag; + u8 flags = 0, nr_frags; int rc = -EINVAL, i; dma_addr_t mapping; u16 vlan = 0; - u8 flags = 0; if (unlikely(skb->ip_summed != CHECKSUM_NONE)) { DP_INFO(cdev, "Cannot transmit a checksummed packet\n"); return -EINVAL; } - if (1 + skb_shinfo(skb)->nr_frags > CORE_LL2_TX_MAX_BDS_PER_PACKET) { + /* Cache number of fragments from SKB since SKB may be freed by + * the completion routine after calling qed_ll2_prepare_tx_packet() + */ + nr_frags = skb_shinfo(skb)->nr_frags; + + if (1 + nr_frags > CORE_LL2_TX_MAX_BDS_PER_PACKET) { DP_ERR(cdev, "Cannot transmit a packet with %d fragments\n", - 1 + skb_shinfo(skb)->nr_frags); + 1 + nr_frags); return -EINVAL; } @@ -2481,7 +2490,7 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb, } memset(&pkt, 0, sizeof(pkt)); - pkt.num_of_bds = 1 + skb_shinfo(skb)->nr_frags; + pkt.num_of_bds = 1 + nr_frags; pkt.vlan = vlan; pkt.bd_flags = flags; pkt.tx_dest = QED_LL2_TX_DEST_NW; @@ -2492,12 +2501,17 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb, test_bit(QED_LL2_XMIT_FLAGS_FIP_DISCOVERY, &xmit_flags)) pkt.remove_stag = true; + /* qed_ll2_prepare_tx_packet() may actually send the packet if + * there are no fragments in the skb and subsequently the completion + * routine may run and free the SKB, so no dereferencing the SKB + * beyond this point unless skb has any fragments. + */ rc = qed_ll2_prepare_tx_packet(&cdev->hwfns[0], cdev->ll2->handle, &pkt, 1); if (rc) goto err; - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + for (i = 0; i < nr_frags; i++) { frag = &skb_shinfo(skb)->frags[i]; mapping = skb_frag_dma_map(&cdev->pdev->dev, frag, 0, diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h index 4179c9013fc6..96ab77ae6af5 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h @@ -382,6 +382,7 @@ void qed_consq_setup(struct qed_hwfn *p_hwfn); * @param p_hwfn */ void qed_consq_free(struct qed_hwfn *p_hwfn); +int qed_spq_pend_post(struct qed_hwfn *p_hwfn); /** * @file diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c index 888274fa208b..5a495fda9e9d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c @@ -604,6 +604,9 @@ int qed_sp_pf_update_stag(struct qed_hwfn *p_hwfn) p_ent->ramrod.pf_update.update_mf_vlan_flag = true; p_ent->ramrod.pf_update.mf_vlan = cpu_to_le16(p_hwfn->hw_info.ovlan); + if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits)) + p_ent->ramrod.pf_update.mf_vlan |= + cpu_to_le16(((u16)p_hwfn->ufp_info.tc << 13)); return qed_spq_post(p_hwfn, p_ent, NULL); } diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c index eb88bbc6b193..ba64ff9bedbd 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_spq.c +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c @@ -397,6 +397,11 @@ int qed_eq_completion(struct qed_hwfn *p_hwfn, void *cookie) qed_eq_prod_update(p_hwfn, qed_chain_get_prod_idx(p_chain)); + /* Attempt to post pending requests */ + spin_lock_bh(&p_hwfn->p_spq->lock); + rc = qed_spq_pend_post(p_hwfn); + spin_unlock_bh(&p_hwfn->p_spq->lock); + return rc; } @@ -767,7 +772,7 @@ static int qed_spq_post_list(struct qed_hwfn *p_hwfn, return 0; } -static int qed_spq_pend_post(struct qed_hwfn *p_hwfn) +int qed_spq_pend_post(struct qed_hwfn *p_hwfn) { struct qed_spq *p_spq = p_hwfn->p_spq; struct qed_spq_entry *p_ent = NULL; @@ -905,7 +910,6 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn, struct qed_spq_entry *p_ent = NULL; struct qed_spq_entry *tmp; struct qed_spq_entry *found = NULL; - int rc; if (!p_hwfn) return -EINVAL; @@ -963,12 +967,7 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn, */ qed_spq_return_entry(p_hwfn, found); - /* Attempt to post pending requests */ - spin_lock_bh(&p_spq->lock); - rc = qed_spq_pend_post(p_hwfn); - spin_unlock_bh(&p_spq->lock); - - return rc; + return 0; } int qed_consq_alloc(struct qed_hwfn *p_hwfn) diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c index ca6290fa0f30..71a7af134dd8 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c @@ -1969,7 +1969,9 @@ static void qed_iov_vf_mbx_start_vport(struct qed_hwfn *p_hwfn, params.vport_id = vf->vport_id; params.max_buffers_per_cqe = start->max_buffers_per_cqe; params.mtu = vf->mtu; - params.check_mac = true; + + /* Non trusted VFs should enable control frame filtering */ + params.check_mac = !vf->p_vf_info.is_trusted_configured; rc = qed_sp_eth_vport_start(p_hwfn, ¶ms); if (rc) { @@ -5130,6 +5132,9 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn) params.opaque_fid = vf->opaque_fid; params.vport_id = vf->vport_id; + params.update_ctl_frame_check = 1; + params.mac_chk_en = !vf_info->is_trusted_configured; + if (vf_info->rx_accept_mode & mask) { flags->update_rx_mode_config = 1; flags->rx_accept_filter = vf_info->rx_accept_mode; @@ -5147,7 +5152,8 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn) } if (flags->update_rx_mode_config || - flags->update_tx_mode_config) + flags->update_tx_mode_config || + params.update_ctl_frame_check) qed_sp_vport_update(hwfn, ¶ms, QED_SPQ_MODE_EBLOCK, NULL); } diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c index b6cccf44bf40..5dda547772c1 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_vf.c +++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c @@ -261,6 +261,7 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn) struct pfvf_acquire_resp_tlv *resp = &p_iov->pf2vf_reply->acquire_resp; struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info; struct vf_pf_resc_request *p_resc; + u8 retry_cnt = VF_ACQUIRE_THRESH; bool resources_acquired = false; struct vfpf_acquire_tlv *req; int rc = 0, attempts = 0; @@ -314,6 +315,15 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn) /* send acquire request */ rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + + /* Re-try acquire in case of vf-pf hw channel timeout */ + if (retry_cnt && rc == -EBUSY) { + DP_VERBOSE(p_hwfn, QED_MSG_IOV, + "VF retrying to acquire due to VPC timeout\n"); + retry_cnt--; + continue; + } + if (rc) goto exit; diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 613249d1e967..730997b13747 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -56,7 +56,7 @@ #include <net/tc_act/tc_gact.h> #define QEDE_MAJOR_VERSION 8 -#define QEDE_MINOR_VERSION 33 +#define QEDE_MINOR_VERSION 37 #define QEDE_REVISION_VERSION 0 #define QEDE_ENGINEERING_VERSION 20 #define DRV_MODULE_VERSION __stringify(QEDE_MAJOR_VERSION) "." \ @@ -494,6 +494,9 @@ struct qede_reload_args { /* Datapath functions definition */ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev); +u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb, + struct net_device *sb_dev, + select_queue_fallback_t fallback); netdev_features_t qede_features_check(struct sk_buff *skb, struct net_device *dev, netdev_features_t features); diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c index bdf816fe5a16..31b046e24565 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_fp.c +++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c @@ -1695,6 +1695,19 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_OK; } +u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb, + struct net_device *sb_dev, + select_queue_fallback_t fallback) +{ + struct qede_dev *edev = netdev_priv(dev); + int total_txq; + + total_txq = QEDE_TSS_COUNT(edev) * edev->dev_info.num_tc; + + return QEDE_TSS_COUNT(edev) ? + fallback(dev, skb, NULL) % total_txq : 0; +} + /* 8B udp header + 8B base tunnel header + 32B option length */ #define QEDE_MAX_TUN_HDR_LEN 48 diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 5a74fcbdbc2b..9790f26d17c4 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -631,6 +631,7 @@ static const struct net_device_ops qede_netdev_ops = { .ndo_open = qede_open, .ndo_stop = qede_close, .ndo_start_xmit = qede_start_xmit, + .ndo_select_queue = qede_select_queue, .ndo_set_rx_mode = qede_set_rx_mode, .ndo_set_mac_address = qede_set_mac_addr, .ndo_validate_addr = eth_validate_addr, @@ -666,6 +667,7 @@ static const struct net_device_ops qede_netdev_vf_ops = { .ndo_open = qede_open, .ndo_stop = qede_close, .ndo_start_xmit = qede_start_xmit, + .ndo_select_queue = qede_select_queue, .ndo_set_rx_mode = qede_set_rx_mode, .ndo_set_mac_address = qede_set_mac_addr, .ndo_validate_addr = eth_validate_addr, @@ -684,6 +686,7 @@ static const struct net_device_ops qede_netdev_vf_xdp_ops = { .ndo_open = qede_open, .ndo_stop = qede_close, .ndo_start_xmit = qede_start_xmit, + .ndo_select_queue = qede_select_queue, .ndo_set_rx_mode = qede_set_rx_mode, .ndo_set_mac_address = qede_set_mac_addr, .ndo_validate_addr = eth_validate_addr, diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index d344e9d43832..af38d3d73291 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -434,14 +434,14 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter, *(tx_ring->hw_consumer) = 0; rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx); - rq_addr = dma_zalloc_coherent(&adapter->pdev->dev, rq_size, - &rq_phys_addr, GFP_KERNEL); + rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size, + &rq_phys_addr, GFP_KERNEL); if (!rq_addr) return -ENOMEM; rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx); - rsp_addr = dma_zalloc_coherent(&adapter->pdev->dev, rsp_size, - &rsp_phys_addr, GFP_KERNEL); + rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size, + &rsp_phys_addr, GFP_KERNEL); if (!rsp_addr) { err = -ENOMEM; goto out_free_rq; @@ -855,8 +855,8 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args cmd; size_t nic_size = sizeof(struct qlcnic_info_le); - nic_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, nic_size, - &nic_dma_t, GFP_KERNEL); + nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, + &nic_dma_t, GFP_KERNEL); if (!nic_info_addr) return -ENOMEM; @@ -909,8 +909,8 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter, if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) return err; - nic_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, nic_size, - &nic_dma_t, GFP_KERNEL); + nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, + &nic_dma_t, GFP_KERNEL); if (!nic_info_addr) return -ENOMEM; @@ -964,8 +964,8 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter, void *pci_info_addr; int err = 0, i; - pci_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, pci_size, - &pci_info_dma_t, GFP_KERNEL); + pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size, + &pci_info_dma_t, GFP_KERNEL); if (!pci_info_addr) return -ENOMEM; @@ -1078,8 +1078,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, return -EIO; } - stats_addr = dma_zalloc_coherent(&adapter->pdev->dev, stats_size, - &stats_dma_t, GFP_KERNEL); + stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size, + &stats_dma_t, GFP_KERNEL); if (!stats_addr) return -ENOMEM; @@ -1134,8 +1134,8 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter, if (mac_stats == NULL) return -ENOMEM; - stats_addr = dma_zalloc_coherent(&adapter->pdev->dev, stats_size, - &stats_dma_t, GFP_KERNEL); + stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size, + &stats_dma_t, GFP_KERNEL); if (!stats_addr) return -ENOMEM; diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c index 031f6e6ee9c1..8d790313ee3d 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c @@ -776,7 +776,7 @@ int emac_mac_rx_tx_rings_alloc_all(struct emac_adapter *adpt) 8 + 2 * 8; /* 8 byte per one Tx and two Rx rings */ ring_header->used = 0; - ring_header->v_addr = dma_zalloc_coherent(dev, ring_header->size, + ring_header->v_addr = dma_alloc_coherent(dev, ring_header->size, &ring_header->dma_addr, GFP_KERNEL); if (!ring_header->v_addr) diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index 44f6e4873aad..4f910c4f67b0 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -691,7 +691,7 @@ static void cp_tx (struct cp_private *cp) } bytes_compl += skb->len; pkts_compl++; - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); } cp->tx_skb[tx_tail] = NULL; diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 298930d39b79..6e36b88ca7c9 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -205,6 +205,8 @@ enum cfg_version { }; static const struct pci_device_id rtl8169_pci_tbl[] = { + { PCI_VDEVICE(REALTEK, 0x2502), RTL_CFG_1 }, + { PCI_VDEVICE(REALTEK, 0x2600), RTL_CFG_1 }, { PCI_VDEVICE(REALTEK, 0x8129), RTL_CFG_0 }, { PCI_VDEVICE(REALTEK, 0x8136), RTL_CFG_2 }, { PCI_VDEVICE(REALTEK, 0x8161), RTL_CFG_1 }, @@ -706,6 +708,7 @@ module_param(use_dac, int, 0); MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); module_param_named(debug, debug.msg_enable, int, 0); MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); +MODULE_SOFTDEP("pre: realtek"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(FIRMWARE_8168D_1); MODULE_FIRMWARE(FIRMWARE_8168D_2); @@ -1283,11 +1286,13 @@ static u16 rtl_get_events(struct rtl8169_private *tp) static void rtl_ack_events(struct rtl8169_private *tp, u16 bits) { RTL_W16(tp, IntrStatus, bits); + mmiowb(); } static void rtl_irq_disable(struct rtl8169_private *tp) { RTL_W16(tp, IntrMask, 0); + mmiowb(); } #define RTL_EVENT_NAPI_RX (RxOK | RxErr) @@ -1679,11 +1684,13 @@ static bool rtl8169_reset_counters(struct rtl8169_private *tp) static bool rtl8169_update_counters(struct rtl8169_private *tp) { + u8 val = RTL_R8(tp, ChipCmd); + /* * Some chips are unable to dump tally counters when the receiver - * is disabled. + * is disabled. If 0xff chip may be in a PCI power-save state. */ - if ((RTL_R8(tp, ChipCmd) & CmdRxEnb) == 0) + if (!(val & CmdRxEnb) || val == 0xff) return true; return rtl8169_do_counters(tp, CounterDump); @@ -6067,7 +6074,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, struct device *d = tp_to_dev(tp); dma_addr_t mapping; u32 opts[2], len; - bool stop_queue; int frags; if (unlikely(!rtl_tx_slots_avail(tp, skb_shinfo(skb)->nr_frags))) { @@ -6109,6 +6115,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, txd->opts2 = cpu_to_le32(opts[1]); + netdev_sent_queue(dev, skb->len); + skb_tx_timestamp(skb); /* Force memory writes to complete before releasing descriptor */ @@ -6121,14 +6129,16 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, tp->cur_tx += frags + 1; - stop_queue = !rtl_tx_slots_avail(tp, MAX_SKB_FRAGS); - if (unlikely(stop_queue)) - netif_stop_queue(dev); + RTL_W8(tp, TxPoll, NPQ); - if (__netdev_sent_queue(dev, skb->len, skb->xmit_more)) - RTL_W8(tp, TxPoll, NPQ); + mmiowb(); - if (unlikely(stop_queue)) { + if (!rtl_tx_slots_avail(tp, MAX_SKB_FRAGS)) { + /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must + * not miss a ring update when it notices a stopped queue. + */ + smp_wmb(); + netif_stop_queue(dev); /* Sync with rtl_tx: * - publish queue status and cur_tx ring index (write barrier) * - refresh dirty_tx ring index (read barrier). @@ -6478,7 +6488,9 @@ static int rtl8169_poll(struct napi_struct *napi, int budget) if (work_done < budget) { napi_complete_done(napi, work_done); + rtl_irq_enable(tp); + mmiowb(); } return work_done; diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index ffc1ada4e6da..d28c8f9ca55b 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -343,7 +343,7 @@ static int ravb_ring_init(struct net_device *ndev, int q) int i; priv->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ : ndev->mtu) + - ETH_HLEN + VLAN_HLEN; + ETH_HLEN + VLAN_HLEN + sizeof(__sum16); /* Allocate RX and TX skb rings */ priv->rx_skb[q] = kcalloc(priv->num_rx_ring[q], @@ -524,13 +524,15 @@ static void ravb_rx_csum(struct sk_buff *skb) { u8 *hw_csum; - /* The hardware checksum is 2 bytes appended to packet data */ - if (unlikely(skb->len < 2)) + /* The hardware checksum is contained in sizeof(__sum16) (2) bytes + * appended to packet data + */ + if (unlikely(skb->len < sizeof(__sum16))) return; - hw_csum = skb_tail_pointer(skb) - 2; + hw_csum = skb_tail_pointer(skb) - sizeof(__sum16); skb->csum = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum)); skb->ip_summed = CHECKSUM_COMPLETE; - skb_trim(skb, skb->len - 2); + skb_trim(skb, skb->len - sizeof(__sum16)); } /* Packet receive function for Ethernet AVB */ diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c index 690aee88f0eb..6d22dd500790 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c @@ -400,9 +400,9 @@ static int init_tx_ring(struct device *dev, u8 queue_no, } /* allocate memory for TX descriptors */ - tx_ring->dma_tx = dma_zalloc_coherent(dev, - tx_rsize * sizeof(struct sxgbe_tx_norm_desc), - &tx_ring->dma_tx_phy, GFP_KERNEL); + tx_ring->dma_tx = dma_alloc_coherent(dev, + tx_rsize * sizeof(struct sxgbe_tx_norm_desc), + &tx_ring->dma_tx_phy, GFP_KERNEL); if (!tx_ring->dma_tx) return -ENOMEM; @@ -479,9 +479,9 @@ static int init_rx_ring(struct net_device *dev, u8 queue_no, rx_ring->queue_no = queue_no; /* allocate memory for RX descriptors */ - rx_ring->dma_rx = dma_zalloc_coherent(priv->device, - rx_rsize * sizeof(struct sxgbe_rx_norm_desc), - &rx_ring->dma_rx_phy, GFP_KERNEL); + rx_ring->dma_rx = dma_alloc_coherent(priv->device, + rx_rsize * sizeof(struct sxgbe_rx_norm_desc), + &rx_ring->dma_rx_phy, GFP_KERNEL); if (rx_ring->dma_rx == NULL) return -ENOMEM; diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index b6a50058bb8d..c08034154a9a 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -6046,22 +6046,25 @@ static const struct efx_ef10_nvram_type_info efx_ef10_nvram_types[] = { { NVRAM_PARTITION_TYPE_EXPANSION_UEFI, 0, 0, "sfc_uefi" }, { NVRAM_PARTITION_TYPE_STATUS, 0, 0, "sfc_status" } }; +#define EF10_NVRAM_PARTITION_COUNT ARRAY_SIZE(efx_ef10_nvram_types) static int efx_ef10_mtd_probe_partition(struct efx_nic *efx, struct efx_mcdi_mtd_partition *part, - unsigned int type) + unsigned int type, + unsigned long *found) { MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_METADATA_IN_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_METADATA_OUT_LENMAX); const struct efx_ef10_nvram_type_info *info; size_t size, erase_size, outlen; + int type_idx = 0; bool protected; int rc; - for (info = efx_ef10_nvram_types; ; info++) { - if (info == - efx_ef10_nvram_types + ARRAY_SIZE(efx_ef10_nvram_types)) + for (type_idx = 0; ; type_idx++) { + if (type_idx == EF10_NVRAM_PARTITION_COUNT) return -ENODEV; + info = efx_ef10_nvram_types + type_idx; if ((type & ~info->type_mask) == info->type) break; } @@ -6074,6 +6077,13 @@ static int efx_ef10_mtd_probe_partition(struct efx_nic *efx, if (protected) return -ENODEV; /* hide it */ + /* If we've already exposed a partition of this type, hide this + * duplicate. All operations on MTDs are keyed by the type anyway, + * so we can't act on the duplicate. + */ + if (__test_and_set_bit(type_idx, found)) + return -EEXIST; + part->nvram_type = type; MCDI_SET_DWORD(inbuf, NVRAM_METADATA_IN_TYPE, type); @@ -6105,6 +6115,7 @@ static int efx_ef10_mtd_probe_partition(struct efx_nic *efx, static int efx_ef10_mtd_probe(struct efx_nic *efx) { MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX); + DECLARE_BITMAP(found, EF10_NVRAM_PARTITION_COUNT) = { 0 }; struct efx_mcdi_mtd_partition *parts; size_t outlen, n_parts_total, i, n_parts; unsigned int type; @@ -6133,11 +6144,13 @@ static int efx_ef10_mtd_probe(struct efx_nic *efx) for (i = 0; i < n_parts_total; i++) { type = MCDI_ARRAY_DWORD(outbuf, NVRAM_PARTITIONS_OUT_TYPE_ID, i); - rc = efx_ef10_mtd_probe_partition(efx, &parts[n_parts], type); - if (rc == 0) - n_parts++; - else if (rc != -ENODEV) + rc = efx_ef10_mtd_probe_partition(efx, &parts[n_parts], type, + found); + if (rc == -EEXIST || rc == -ENODEV) + continue; + if (rc) goto fail; + n_parts++; } rc = efx_mtd_add(efx, &parts[0].common, n_parts, sizeof(*parts)); diff --git a/drivers/net/ethernet/sfc/falcon/nic.c b/drivers/net/ethernet/sfc/falcon/nic.c index a8ecb33390da..9c07b5175581 100644 --- a/drivers/net/ethernet/sfc/falcon/nic.c +++ b/drivers/net/ethernet/sfc/falcon/nic.c @@ -33,8 +33,8 @@ int ef4_nic_alloc_buffer(struct ef4_nic *efx, struct ef4_buffer *buffer, unsigned int len, gfp_t gfp_flags) { - buffer->addr = dma_zalloc_coherent(&efx->pci_dev->dev, len, - &buffer->dma_addr, gfp_flags); + buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len, + &buffer->dma_addr, gfp_flags); if (!buffer->addr) return -ENOMEM; buffer->len = len; diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index aa1945a858d5..c2d45a40eb48 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -34,8 +34,8 @@ int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer, unsigned int len, gfp_t gfp_flags) { - buffer->addr = dma_zalloc_coherent(&efx->pci_dev->dev, len, - &buffer->dma_addr, gfp_flags); + buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len, + &buffer->dma_addr, gfp_flags); if (!buffer->addr) return -ENOMEM; buffer->len = len; diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c index 703fbbefea44..0e1b7e960b98 100644 --- a/drivers/net/ethernet/sgi/meth.c +++ b/drivers/net/ethernet/sgi/meth.c @@ -211,8 +211,8 @@ static void meth_check_link(struct net_device *dev) static int meth_init_tx_ring(struct meth_private *priv) { /* Init TX ring */ - priv->tx_ring = dma_zalloc_coherent(NULL, TX_RING_BUFFER_SIZE, - &priv->tx_ring_dma, GFP_ATOMIC); + priv->tx_ring = dma_alloc_coherent(NULL, TX_RING_BUFFER_SIZE, + &priv->tx_ring_dma, GFP_ATOMIC); if (!priv->tx_ring) return -ENOMEM; diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c index 15c62c160953..be47d864f8b9 100644 --- a/drivers/net/ethernet/smsc/epic100.c +++ b/drivers/net/ethernet/smsc/epic100.c @@ -1037,7 +1037,7 @@ static void epic_tx(struct net_device *dev, struct epic_private *ep) skb = ep->tx_skbuff[entry]; pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); ep->tx_skbuff[entry] = NULL; } diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c index 05a0948ad929..a18149720aa2 100644 --- a/drivers/net/ethernet/socionext/netsec.c +++ b/drivers/net/ethernet/socionext/netsec.c @@ -1029,8 +1029,8 @@ static int netsec_alloc_dring(struct netsec_priv *priv, enum ring_id id) struct netsec_desc_ring *dring = &priv->desc_ring[id]; int i; - dring->vaddr = dma_zalloc_coherent(priv->dev, DESC_SZ * DESC_NUM, - &dring->desc_dma, GFP_KERNEL); + dring->vaddr = dma_alloc_coherent(priv->dev, DESC_SZ * DESC_NUM, + &dring->desc_dma, GFP_KERNEL); if (!dring->vaddr) goto err; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 7b923362ee55..3b174eae77c1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -1342,8 +1342,10 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv) } ret = phy_power_on(bsp_priv, true); - if (ret) + if (ret) { + gmac_clk_enable(bsp_priv, false); return ret; + } pm_runtime_enable(dev); pm_runtime_get_sync(dev); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c index 20299f6f65fc..736e29635b77 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c @@ -241,15 +241,18 @@ static inline void dwmac4_get_timestamp(void *desc, u32 ats, u64 *ts) static int dwmac4_rx_check_timestamp(void *desc) { struct dma_desc *p = (struct dma_desc *)desc; + unsigned int rdes0 = le32_to_cpu(p->des0); + unsigned int rdes1 = le32_to_cpu(p->des1); + unsigned int rdes3 = le32_to_cpu(p->des3); u32 own, ctxt; int ret = 1; - own = p->des3 & RDES3_OWN; - ctxt = ((p->des3 & RDES3_CONTEXT_DESCRIPTOR) + own = rdes3 & RDES3_OWN; + ctxt = ((rdes3 & RDES3_CONTEXT_DESCRIPTOR) >> RDES3_CONTEXT_DESCRIPTOR_SHIFT); if (likely(!own && ctxt)) { - if ((p->des0 == 0xffffffff) && (p->des1 == 0xffffffff)) + if ((rdes0 == 0xffffffff) && (rdes1 == 0xffffffff)) /* Corrupted value */ ret = -EINVAL; else diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index 6c5092e7771c..c5e25580a43f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -263,6 +263,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x, u32 chan) { u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan)); + u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan)); int ret = 0; /* ABNORMAL interrupts */ @@ -282,8 +283,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr, x->normal_irq_n++; if (likely(intr_status & XGMAC_RI)) { - u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan)); - if (likely(value & XGMAC_RIE)) { + if (likely(intr_en & XGMAC_RIE)) { x->rx_normal_irq_n++; ret |= handle_rx; } @@ -295,7 +295,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr, } /* Clear interrupts */ - writel(~0x0, ioaddr + XGMAC_DMA_CH_STATUS(chan)); + writel(intr_en & intr_status, ioaddr + XGMAC_DMA_CH_STATUS(chan)); return ret; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index d1f61c25d82b..3c749c327cbd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -696,33 +696,38 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev, struct ethtool_eee *edata) { struct stmmac_priv *priv = netdev_priv(dev); + int ret; - priv->eee_enabled = edata->eee_enabled; - - if (!priv->eee_enabled) + if (!edata->eee_enabled) { stmmac_disable_eee_mode(priv); - else { + } else { /* We are asking for enabling the EEE but it is safe * to verify all by invoking the eee_init function. * In case of failure it will return an error. */ - priv->eee_enabled = stmmac_eee_init(priv); - if (!priv->eee_enabled) + edata->eee_enabled = stmmac_eee_init(priv); + if (!edata->eee_enabled) return -EOPNOTSUPP; - - /* Do not change tx_lpi_timer in case of failure */ - priv->tx_lpi_timer = edata->tx_lpi_timer; } - return phy_ethtool_set_eee(dev->phydev, edata); + ret = phy_ethtool_set_eee(dev->phydev, edata); + if (ret) + return ret; + + priv->eee_enabled = edata->eee_enabled; + priv->tx_lpi_timer = edata->tx_lpi_timer; + return 0; } static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv) { unsigned long clk = clk_get_rate(priv->plat->stmmac_clk); - if (!clk) - return 0; + if (!clk) { + clk = priv->plat->clk_ref_rate; + if (!clk) + return 0; + } return (usec * (clk / 1000000)) / 256; } @@ -731,8 +736,11 @@ static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv) { unsigned long clk = clk_get_rate(priv->plat->stmmac_clk); - if (!clk) - return 0; + if (!clk) { + clk = priv->plat->clk_ref_rate; + if (!clk) + return 0; + } return (riwt * 256) / (clk / 1000000); } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 0e0a0789c2ed..685d20472358 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1549,22 +1549,18 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv) goto err_dma; if (priv->extend_desc) { - rx_q->dma_erx = dma_zalloc_coherent(priv->device, - DMA_RX_SIZE * - sizeof(struct - dma_extended_desc), - &rx_q->dma_rx_phy, - GFP_KERNEL); + rx_q->dma_erx = dma_alloc_coherent(priv->device, + DMA_RX_SIZE * sizeof(struct dma_extended_desc), + &rx_q->dma_rx_phy, + GFP_KERNEL); if (!rx_q->dma_erx) goto err_dma; } else { - rx_q->dma_rx = dma_zalloc_coherent(priv->device, - DMA_RX_SIZE * - sizeof(struct - dma_desc), - &rx_q->dma_rx_phy, - GFP_KERNEL); + rx_q->dma_rx = dma_alloc_coherent(priv->device, + DMA_RX_SIZE * sizeof(struct dma_desc), + &rx_q->dma_rx_phy, + GFP_KERNEL); if (!rx_q->dma_rx) goto err_dma; } @@ -1612,21 +1608,17 @@ static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv) goto err_dma; if (priv->extend_desc) { - tx_q->dma_etx = dma_zalloc_coherent(priv->device, - DMA_TX_SIZE * - sizeof(struct - dma_extended_desc), - &tx_q->dma_tx_phy, - GFP_KERNEL); + tx_q->dma_etx = dma_alloc_coherent(priv->device, + DMA_TX_SIZE * sizeof(struct dma_extended_desc), + &tx_q->dma_tx_phy, + GFP_KERNEL); if (!tx_q->dma_etx) goto err_dma; } else { - tx_q->dma_tx = dma_zalloc_coherent(priv->device, - DMA_TX_SIZE * - sizeof(struct - dma_desc), - &tx_q->dma_tx_phy, - GFP_KERNEL); + tx_q->dma_tx = dma_alloc_coherent(priv->device, + DMA_TX_SIZE * sizeof(struct dma_desc), + &tx_q->dma_tx_phy, + GFP_KERNEL); if (!tx_q->dma_tx) goto err_dma; } @@ -3031,10 +3023,22 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) tx_q = &priv->tx_queue[queue]; + if (priv->tx_path_in_lpi_mode) + stmmac_disable_eee_mode(priv); + /* Manage oversized TCP frames for GMAC4 device */ if (skb_is_gso(skb) && priv->tso) { - if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) + if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { + /* + * There is no way to determine the number of TSO + * capable Queues. Let's use always the Queue 0 + * because if TSO is supported then at least this + * one will be capable. + */ + skb_set_queue_mapping(skb, 0); + return stmmac_tso_xmit(skb, dev); + } } if (unlikely(stmmac_tx_avail(priv, queue) < nfrags + 1)) { @@ -3049,9 +3053,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } - if (priv->tx_path_in_lpi_mode) - stmmac_disable_eee_mode(priv); - entry = tx_q->cur_tx; first_entry = entry; WARN_ON(tx_q->tx_skbuff[first_entry]); @@ -3525,27 +3526,28 @@ static int stmmac_napi_poll(struct napi_struct *napi, int budget) struct stmmac_channel *ch = container_of(napi, struct stmmac_channel, napi); struct stmmac_priv *priv = ch->priv_data; - int work_done = 0, work_rem = budget; + int work_done, rx_done = 0, tx_done = 0; u32 chan = ch->index; priv->xstats.napi_poll++; - if (ch->has_tx) { - int done = stmmac_tx_clean(priv, work_rem, chan); + if (ch->has_tx) + tx_done = stmmac_tx_clean(priv, budget, chan); + if (ch->has_rx) + rx_done = stmmac_rx(priv, budget, chan); - work_done += done; - work_rem -= done; - } + work_done = max(rx_done, tx_done); + work_done = min(work_done, budget); - if (ch->has_rx) { - int done = stmmac_rx(priv, work_rem, chan); + if (work_done < budget && napi_complete_done(napi, work_done)) { + int stat; - work_done += done; - work_rem -= done; - } - - if (work_done < budget && napi_complete_done(napi, work_done)) stmmac_enable_dma_irq(priv, priv->ioaddr, chan); + stat = stmmac_dma_interrupt_status(priv, priv->ioaddr, + &priv->xstats, chan); + if (stat && napi_reschedule(napi)) + stmmac_disable_dma_irq(priv, priv->ioaddr, chan); + } return work_done; } @@ -4168,6 +4170,18 @@ static int stmmac_hw_init(struct stmmac_priv *priv) return ret; } + /* Rx Watchdog is available in the COREs newer than the 3.40. + * In some case, for example on bugged HW this feature + * has to be disable and this can be done by passing the + * riwt_off field from the platform. + */ + if (((priv->synopsys_id >= DWMAC_CORE_3_50) || + (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) { + priv->use_riwt = 1; + dev_info(priv->device, + "Enable RX Mitigation via HW Watchdog Timer\n"); + } + return 0; } @@ -4300,18 +4314,6 @@ int stmmac_dvr_probe(struct device *device, if (flow_ctrl) priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */ - /* Rx Watchdog is available in the COREs newer than the 3.40. - * In some case, for example on bugged HW this feature - * has to be disable and this can be done by passing the - * riwt_off field from the platform. - */ - if (((priv->synopsys_id >= DWMAC_CORE_3_50) || - (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) { - priv->use_riwt = 1; - dev_info(priv->device, - "Enable RX Mitigation via HW Watchdog Timer\n"); - } - /* Setup channels NAPI */ maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index c54a50dbd5ac..d819e8eaba12 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -299,7 +299,17 @@ static int stmmac_pci_probe(struct pci_dev *pdev, */ static void stmmac_pci_remove(struct pci_dev *pdev) { + int i; + stmmac_dvr_remove(&pdev->dev); + + for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { + if (pci_resource_len(pdev, i) == 0) + continue; + pcim_iounmap_regions(pdev, BIT(i)); + break; + } + pci_disable_device(pdev); } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c index 531294f4978b..58ea18af9813 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c @@ -301,6 +301,8 @@ static int tc_setup_cbs(struct stmmac_priv *priv, /* Queue 0 is not AVB capable */ if (queue <= 0 || queue >= tx_queues_count) return -EINVAL; + if (!priv->dma_cap.av) + return -EOPNOTSUPP; if (priv->speed != SPEED_100 && priv->speed != SPEED_1000) return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index 9020b084b953..6fc05c106afc 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -1,22 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0+ /* cassini.c: Sun Microsystems Cassini(+) ethernet driver. * * Copyright (C) 2004 Sun Microsystems Inc. * Copyright (C) 2003 Adrian Sun (asun@darksunrising.com) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * * This driver uses the sungem driver (c) David Miller * (davem@redhat.com) as its basis. * @@ -1911,7 +1898,7 @@ static inline void cas_tx_ringN(struct cas *cp, int ring, int limit) cp->net_stats[ring].tx_packets++; cp->net_stats[ring].tx_bytes += skb->len; spin_unlock(&cp->stat_lock[ring]); - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); } cp->tx_old[ring] = entry; diff --git a/drivers/net/ethernet/sun/cassini.h b/drivers/net/ethernet/sun/cassini.h index 13f3860496a8..ae5f05f03f88 100644 --- a/drivers/net/ethernet/sun/cassini.h +++ b/drivers/net/ethernet/sun/cassini.h @@ -1,23 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0+ */ /* $Id: cassini.h,v 1.16 2004/08/17 21:15:16 zaumen Exp $ * cassini.h: Definitions for Sun Microsystems Cassini(+) ethernet driver. * * Copyright (C) 2004 Sun Microsystems Inc. * Copyright (c) 2003 Adrian Sun (asun@darksunrising.com) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * * vendor id: 0x108E (Sun Microsystems, Inc.) * device id: 0xabba (Cassini) * revision ids: 0x01 = Cassini diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c index 720b7ac77f3b..e9b757b03b56 100644 --- a/drivers/net/ethernet/sun/sunbmac.c +++ b/drivers/net/ethernet/sun/sunbmac.c @@ -781,7 +781,7 @@ static void bigmac_tx(struct bigmac *bp) DTX(("skb(%p) ", skb)); bp->tx_skbs[elem] = NULL; - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); elem = NEXT_TX(elem); } diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c index ff641cf30a4e..d007dfeba5c3 100644 --- a/drivers/net/ethernet/sun/sunhme.c +++ b/drivers/net/ethernet/sun/sunhme.c @@ -1962,7 +1962,7 @@ static void happy_meal_tx(struct happy_meal *hp) this = &txbase[elem]; } - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); dev->stats.tx_packets++; } hp->tx_old = elem; diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index dc966ddb6d81..b24c11187017 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -1739,7 +1739,7 @@ static void bdx_tx_cleanup(struct bdx_priv *priv) tx_level -= db->rptr->len; /* '-' koz len is negative */ /* now should come skb pointer - free it */ - dev_kfree_skb_irq(db->rptr->addr.skb); + dev_consume_skb_irq(db->rptr->addr.skb); bdx_tx_db_inc_rptr(db); } diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c index 810dfc7de1f9..e2d47b24a869 100644 --- a/drivers/net/ethernet/ti/cpmac.c +++ b/drivers/net/ethernet/ti/cpmac.c @@ -608,7 +608,7 @@ static void cpmac_end_xmit(struct net_device *dev, int queue) netdev_dbg(dev, "sent 0x%p, len=%d\n", desc->skb, desc->skb->len); - dev_kfree_skb_irq(desc->skb); + dev_consume_skb_irq(desc->skb); desc->skb = NULL; if (__netif_subqueue_stopped(dev, queue)) netif_wake_subqueue(dev, queue); diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 1f612268c998..d847f672a705 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -259,7 +259,7 @@ static int netcp_module_probe(struct netcp_device *netcp_device, const char *name; char node_name[32]; - if (of_property_read_string(node, "label", &name) < 0) { + if (of_property_read_string(child, "label", &name) < 0) { snprintf(node_name, sizeof(node_name), "%pOFn", child); name = node_name; } diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c index edcd1e60b30d..37925a1d58de 100644 --- a/drivers/net/ethernet/tundra/tsi108_eth.c +++ b/drivers/net/ethernet/tundra/tsi108_eth.c @@ -1311,13 +1311,13 @@ static int tsi108_open(struct net_device *dev) data->id, dev->irq, dev->name); } - data->rxring = dma_zalloc_coherent(&data->pdev->dev, rxring_size, - &data->rxdma, GFP_KERNEL); + data->rxring = dma_alloc_coherent(&data->pdev->dev, rxring_size, + &data->rxdma, GFP_KERNEL); if (!data->rxring) return -ENOMEM; - data->txring = dma_zalloc_coherent(&data->pdev->dev, txring_size, - &data->txdma, GFP_KERNEL); + data->txring = dma_alloc_coherent(&data->pdev->dev, txring_size, + &data->txdma, GFP_KERNEL); if (!data->txring) { dma_free_coherent(&data->pdev->dev, rxring_size, data->rxring, data->rxdma); diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index 82412691ee66..27f6cf140845 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -1740,7 +1740,7 @@ static void velocity_free_tx_buf(struct velocity_info *vptr, dma_unmap_single(vptr->dev, tdinfo->skb_dma[i], le16_to_cpu(pktlen), DMA_TO_DEVICE); } - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); tdinfo->skb = NULL; } diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 2241f9897092..15bb058db392 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -243,15 +243,15 @@ static int temac_dma_bd_init(struct net_device *ndev) /* allocate the tx and rx ring buffer descriptors. */ /* returns a virtual address and a physical address. */ - lp->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent, - sizeof(*lp->tx_bd_v) * TX_BD_NUM, - &lp->tx_bd_p, GFP_KERNEL); + lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent, + sizeof(*lp->tx_bd_v) * TX_BD_NUM, + &lp->tx_bd_p, GFP_KERNEL); if (!lp->tx_bd_v) goto out; - lp->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent, - sizeof(*lp->rx_bd_v) * RX_BD_NUM, - &lp->rx_bd_p, GFP_KERNEL); + lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent, + sizeof(*lp->rx_bd_v) * RX_BD_NUM, + &lp->rx_bd_p, GFP_KERNEL); if (!lp->rx_bd_v) goto out; diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 12a14609ec47..0789d8af7d72 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -199,15 +199,15 @@ static int axienet_dma_bd_init(struct net_device *ndev) lp->rx_bd_ci = 0; /* Allocate the Tx and Rx buffer descriptors. */ - lp->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent, - sizeof(*lp->tx_bd_v) * TX_BD_NUM, - &lp->tx_bd_p, GFP_KERNEL); + lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent, + sizeof(*lp->tx_bd_v) * TX_BD_NUM, + &lp->tx_bd_p, GFP_KERNEL); if (!lp->tx_bd_v) goto out; - lp->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent, - sizeof(*lp->rx_bd_v) * RX_BD_NUM, - &lp->rx_bd_p, GFP_KERNEL); + lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent, + sizeof(*lp->rx_bd_v) * RX_BD_NUM, + &lp->rx_bd_p, GFP_KERNEL); if (!lp->rx_bd_v) goto out; diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c index 61fceee73c1b..56b7791911bf 100644 --- a/drivers/net/fddi/defxx.c +++ b/drivers/net/fddi/defxx.c @@ -1139,9 +1139,9 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name, #endif sizeof(PI_CONSUMER_BLOCK) + (PI_ALIGN_K_DESC_BLK - 1); - bp->kmalloced = top_v = dma_zalloc_coherent(bp->bus_dev, alloc_size, - &bp->kmalloced_dma, - GFP_ATOMIC); + bp->kmalloced = top_v = dma_alloc_coherent(bp->bus_dev, alloc_size, + &bp->kmalloced_dma, + GFP_ATOMIC); if (top_v == NULL) return DFX_K_FAILURE; @@ -3512,7 +3512,7 @@ static int dfx_xmt_done(DFX_board_t *bp) bp->descr_block_virt->xmt_data[comp].long_1, p_xmt_drv_descr->p_skb->len, DMA_TO_DEVICE); - dev_kfree_skb_irq(p_xmt_drv_descr->p_skb); + dev_consume_skb_irq(p_xmt_drv_descr->p_skb); /* * Move to start of next packet by updating completion index diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c index 72433f3efc74..5d661f60b101 100644 --- a/drivers/net/fddi/skfp/skfddi.c +++ b/drivers/net/fddi/skfp/skfddi.c @@ -409,10 +409,10 @@ static int skfp_driver_init(struct net_device *dev) if (bp->SharedMemSize > 0) { bp->SharedMemSize += 16; // for descriptor alignment - bp->SharedMemAddr = dma_zalloc_coherent(&bp->pdev.dev, - bp->SharedMemSize, - &bp->SharedMemDMA, - GFP_ATOMIC); + bp->SharedMemAddr = dma_alloc_coherent(&bp->pdev.dev, + bp->SharedMemSize, + &bp->SharedMemDMA, + GFP_ATOMIC); if (!bp->SharedMemAddr) { printk("could not allocate mem for "); printk("hardware module: %ld byte\n", diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 58bbba8582b0..5583d993480d 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -692,15 +692,20 @@ out: static int geneve_open(struct net_device *dev) { struct geneve_dev *geneve = netdev_priv(dev); - bool ipv6 = !!(geneve->info.mode & IP_TUNNEL_INFO_IPV6); bool metadata = geneve->collect_md; + bool ipv4, ipv6; int ret = 0; + ipv6 = geneve->info.mode & IP_TUNNEL_INFO_IPV6 || metadata; + ipv4 = !ipv6 || metadata; #if IS_ENABLED(CONFIG_IPV6) - if (ipv6 || metadata) + if (ipv6) { ret = geneve_sock_add(geneve, true); + if (ret < 0 && ret != -EAFNOSUPPORT) + ipv4 = false; + } #endif - if (!ret && (!ipv6 || metadata)) + if (ipv4) ret = geneve_sock_add(geneve, false); if (ret < 0) geneve_sock_release(geneve); @@ -1512,9 +1517,13 @@ static void geneve_link_config(struct net_device *dev, } #if IS_ENABLED(CONFIG_IPV6) case AF_INET6: { - struct rt6_info *rt = rt6_lookup(geneve->net, - &info->key.u.ipv6.dst, NULL, 0, - NULL, 0); + struct rt6_info *rt; + + if (!__in6_dev_get(dev)) + break; + + rt = rt6_lookup(geneve->net, &info->key.u.ipv6.dst, NULL, 0, + NULL, 0); if (rt && rt->dst.dev) ldev_mtu = rt->dst.dev->mtu - GENEVE_IPV6_HLEN; diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index ef6f766f6389..e859ae2e42d5 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -144,6 +144,8 @@ struct hv_netvsc_packet { u32 total_data_buflen; }; +#define NETVSC_HASH_KEYLEN 40 + struct netvsc_device_info { unsigned char mac_adr[ETH_ALEN]; u32 num_chn; @@ -151,6 +153,8 @@ struct netvsc_device_info { u32 recv_sections; u32 send_section_size; u32 recv_section_size; + + u8 rss_key[NETVSC_HASH_KEYLEN]; }; enum rndis_device_state { @@ -160,8 +164,6 @@ enum rndis_device_state { RNDIS_DEV_DATAINITIALIZED, }; -#define NETVSC_HASH_KEYLEN 40 - struct rndis_device { struct net_device *ndev; @@ -209,7 +211,9 @@ int netvsc_recv_callback(struct net_device *net, void netvsc_channel_cb(void *context); int netvsc_poll(struct napi_struct *napi, int budget); -int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev); +int rndis_set_subchannel(struct net_device *ndev, + struct netvsc_device *nvdev, + struct netvsc_device_info *dev_info); int rndis_filter_open(struct netvsc_device *nvdev); int rndis_filter_close(struct netvsc_device *nvdev); struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, @@ -1177,7 +1181,7 @@ enum ndis_per_pkt_info_type { enum rndis_per_pkt_info_interal_type { RNDIS_PKTINFO_ID = 1, - /* Add more memebers here */ + /* Add more members here */ RNDIS_PKTINFO_MAX }; diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 922054c1d544..813d195bbd57 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -84,7 +84,7 @@ static void netvsc_subchan_work(struct work_struct *w) rdev = nvdev->extension; if (rdev) { - ret = rndis_set_subchannel(rdev->ndev, nvdev); + ret = rndis_set_subchannel(rdev->ndev, nvdev, NULL); if (ret == 0) { netif_device_attach(rdev->ndev); } else { @@ -1331,7 +1331,7 @@ void netvsc_channel_cb(void *context) prefetch(hv_get_ring_buffer(rbi) + rbi->priv_read_index); if (napi_schedule_prep(&nvchan->napi)) { - /* disable interupts from host */ + /* disable interrupts from host */ hv_begin_read(rbi); __napi_schedule_irqoff(&nvchan->napi); diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 91ed15ea5883..cf4897043e83 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -370,7 +370,7 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len, { int j = 0; - /* Deal with compund pages by ignoring unused part + /* Deal with compound pages by ignoring unused part * of the page. */ page += (offset >> PAGE_SHIFT); @@ -744,6 +744,14 @@ void netvsc_linkstatus_callback(struct net_device *net, schedule_delayed_work(&ndev_ctx->dwork, 0); } +static void netvsc_comp_ipcsum(struct sk_buff *skb) +{ + struct iphdr *iph = (struct iphdr *)skb->data; + + iph->check = 0; + iph->check = ip_fast_csum(iph, iph->ihl); +} + static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net, struct netvsc_channel *nvchan) { @@ -770,9 +778,17 @@ static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net, /* skb is already created with CHECKSUM_NONE */ skb_checksum_none_assert(skb); - /* - * In Linux, the IP checksum is always checked. - * Do L4 checksum offload if enabled and present. + /* Incoming packets may have IP header checksum verified by the host. + * They may not have IP header checksum computed after coalescing. + * We compute it here if the flags are set, because on Linux, the IP + * checksum is always checked. + */ + if (csum_info && csum_info->receive.ip_checksum_value_invalid && + csum_info->receive.ip_checksum_succeeded && + skb->protocol == htons(ETH_P_IP)) + netvsc_comp_ipcsum(skb); + + /* Do L4 checksum offload if enabled and present. */ if (csum_info && (net->features & NETIF_F_RXCSUM)) { if (csum_info->receive.tcp_checksum_succeeded || @@ -858,6 +874,39 @@ static void netvsc_get_channels(struct net_device *net, } } +/* Alloc struct netvsc_device_info, and initialize it from either existing + * struct netvsc_device, or from default values. + */ +static struct netvsc_device_info *netvsc_devinfo_get + (struct netvsc_device *nvdev) +{ + struct netvsc_device_info *dev_info; + + dev_info = kzalloc(sizeof(*dev_info), GFP_ATOMIC); + + if (!dev_info) + return NULL; + + if (nvdev) { + dev_info->num_chn = nvdev->num_chn; + dev_info->send_sections = nvdev->send_section_cnt; + dev_info->send_section_size = nvdev->send_section_size; + dev_info->recv_sections = nvdev->recv_section_cnt; + dev_info->recv_section_size = nvdev->recv_section_size; + + memcpy(dev_info->rss_key, nvdev->extension->rss_key, + NETVSC_HASH_KEYLEN); + } else { + dev_info->num_chn = VRSS_CHANNEL_DEFAULT; + dev_info->send_sections = NETVSC_DEFAULT_TX; + dev_info->send_section_size = NETVSC_SEND_SECTION_SIZE; + dev_info->recv_sections = NETVSC_DEFAULT_RX; + dev_info->recv_section_size = NETVSC_RECV_SECTION_SIZE; + } + + return dev_info; +} + static int netvsc_detach(struct net_device *ndev, struct netvsc_device *nvdev) { @@ -909,7 +958,7 @@ static int netvsc_attach(struct net_device *ndev, return PTR_ERR(nvdev); if (nvdev->num_chn > 1) { - ret = rndis_set_subchannel(ndev, nvdev); + ret = rndis_set_subchannel(ndev, nvdev, dev_info); /* if unavailable, just proceed with one queue */ if (ret) { @@ -943,7 +992,7 @@ static int netvsc_set_channels(struct net_device *net, struct net_device_context *net_device_ctx = netdev_priv(net); struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev); unsigned int orig, count = channels->combined_count; - struct netvsc_device_info device_info; + struct netvsc_device_info *device_info; int ret; /* We do not support separate count for rx, tx, or other */ @@ -962,24 +1011,26 @@ static int netvsc_set_channels(struct net_device *net, orig = nvdev->num_chn; - memset(&device_info, 0, sizeof(device_info)); - device_info.num_chn = count; - device_info.send_sections = nvdev->send_section_cnt; - device_info.send_section_size = nvdev->send_section_size; - device_info.recv_sections = nvdev->recv_section_cnt; - device_info.recv_section_size = nvdev->recv_section_size; + device_info = netvsc_devinfo_get(nvdev); + + if (!device_info) + return -ENOMEM; + + device_info->num_chn = count; ret = netvsc_detach(net, nvdev); if (ret) - return ret; + goto out; - ret = netvsc_attach(net, &device_info); + ret = netvsc_attach(net, device_info); if (ret) { - device_info.num_chn = orig; - if (netvsc_attach(net, &device_info)) + device_info->num_chn = orig; + if (netvsc_attach(net, device_info)) netdev_err(net, "restoring channel setting failed\n"); } +out: + kfree(device_info); return ret; } @@ -1048,48 +1099,45 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) struct net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev); struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev); int orig_mtu = ndev->mtu; - struct netvsc_device_info device_info; + struct netvsc_device_info *device_info; int ret = 0; if (!nvdev || nvdev->destroy) return -ENODEV; + device_info = netvsc_devinfo_get(nvdev); + + if (!device_info) + return -ENOMEM; + /* Change MTU of underlying VF netdev first. */ if (vf_netdev) { ret = dev_set_mtu(vf_netdev, mtu); if (ret) - return ret; + goto out; } - memset(&device_info, 0, sizeof(device_info)); - device_info.num_chn = nvdev->num_chn; - device_info.send_sections = nvdev->send_section_cnt; - device_info.send_section_size = nvdev->send_section_size; - device_info.recv_sections = nvdev->recv_section_cnt; - device_info.recv_section_size = nvdev->recv_section_size; - ret = netvsc_detach(ndev, nvdev); if (ret) goto rollback_vf; ndev->mtu = mtu; - ret = netvsc_attach(ndev, &device_info); - if (ret) - goto rollback; - - return 0; + ret = netvsc_attach(ndev, device_info); + if (!ret) + goto out; -rollback: /* Attempt rollback to original MTU */ ndev->mtu = orig_mtu; - if (netvsc_attach(ndev, &device_info)) + if (netvsc_attach(ndev, device_info)) netdev_err(ndev, "restoring mtu failed\n"); rollback_vf: if (vf_netdev) dev_set_mtu(vf_netdev, orig_mtu); +out: + kfree(device_info); return ret; } @@ -1674,7 +1722,7 @@ static int netvsc_set_ringparam(struct net_device *ndev, { struct net_device_context *ndevctx = netdev_priv(ndev); struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev); - struct netvsc_device_info device_info; + struct netvsc_device_info *device_info; struct ethtool_ringparam orig; u32 new_tx, new_rx; int ret = 0; @@ -1694,26 +1742,29 @@ static int netvsc_set_ringparam(struct net_device *ndev, new_rx == orig.rx_pending) return 0; /* no change */ - memset(&device_info, 0, sizeof(device_info)); - device_info.num_chn = nvdev->num_chn; - device_info.send_sections = new_tx; - device_info.send_section_size = nvdev->send_section_size; - device_info.recv_sections = new_rx; - device_info.recv_section_size = nvdev->recv_section_size; + device_info = netvsc_devinfo_get(nvdev); + + if (!device_info) + return -ENOMEM; + + device_info->send_sections = new_tx; + device_info->recv_sections = new_rx; ret = netvsc_detach(ndev, nvdev); if (ret) - return ret; + goto out; - ret = netvsc_attach(ndev, &device_info); + ret = netvsc_attach(ndev, device_info); if (ret) { - device_info.send_sections = orig.tx_pending; - device_info.recv_sections = orig.rx_pending; + device_info->send_sections = orig.tx_pending; + device_info->recv_sections = orig.rx_pending; - if (netvsc_attach(ndev, &device_info)) + if (netvsc_attach(ndev, device_info)) netdev_err(ndev, "restoring ringparam failed"); } +out: + kfree(device_info); return ret; } @@ -2088,7 +2139,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev) if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev)) return NOTIFY_DONE; - /* if syntihetic interface is a different namespace, + /* if synthetic interface is a different namespace, * then move the VF to that namespace; join will be * done again in that context. */ @@ -2167,7 +2218,7 @@ static int netvsc_probe(struct hv_device *dev, { struct net_device *net = NULL; struct net_device_context *net_device_ctx; - struct netvsc_device_info device_info; + struct netvsc_device_info *device_info = NULL; struct netvsc_device *nvdev; int ret = -ENOMEM; @@ -2214,21 +2265,21 @@ static int netvsc_probe(struct hv_device *dev, netif_set_real_num_rx_queues(net, 1); /* Notify the netvsc driver of the new device */ - memset(&device_info, 0, sizeof(device_info)); - device_info.num_chn = VRSS_CHANNEL_DEFAULT; - device_info.send_sections = NETVSC_DEFAULT_TX; - device_info.send_section_size = NETVSC_SEND_SECTION_SIZE; - device_info.recv_sections = NETVSC_DEFAULT_RX; - device_info.recv_section_size = NETVSC_RECV_SECTION_SIZE; - - nvdev = rndis_filter_device_add(dev, &device_info); + device_info = netvsc_devinfo_get(NULL); + + if (!device_info) { + ret = -ENOMEM; + goto devinfo_failed; + } + + nvdev = rndis_filter_device_add(dev, device_info); if (IS_ERR(nvdev)) { ret = PTR_ERR(nvdev); netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); goto rndis_failed; } - memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); + memcpy(net->dev_addr, device_info->mac_adr, ETH_ALEN); /* We must get rtnl lock before scheduling nvdev->subchan_work, * otherwise netvsc_subchan_work() can get rtnl lock first and wait @@ -2236,7 +2287,7 @@ static int netvsc_probe(struct hv_device *dev, * netvsc_probe() can't get rtnl lock and as a result vmbus_onoffer() * -> ... -> device_add() -> ... -> __device_attach() can't get * the device lock, so all the subchannels can't be processed -- - * finally netvsc_subchan_work() hangs for ever. + * finally netvsc_subchan_work() hangs forever. */ rtnl_lock(); @@ -2266,12 +2317,16 @@ static int netvsc_probe(struct hv_device *dev, list_add(&net_device_ctx->list, &netvsc_dev_list); rtnl_unlock(); + + kfree(device_info); return 0; register_failed: rtnl_unlock(); rndis_filter_device_remove(dev, nvdev); rndis_failed: + kfree(device_info); +devinfo_failed: free_percpu(net_device_ctx->vf_stats); no_stats: hv_set_drvdata(dev, NULL); diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 8b537a049c1e..73b60592de06 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -774,8 +774,8 @@ cleanup: return ret; } -int rndis_filter_set_rss_param(struct rndis_device *rdev, - const u8 *rss_key) +static int rndis_set_rss_param_msg(struct rndis_device *rdev, + const u8 *rss_key, u16 flag) { struct net_device *ndev = rdev->ndev; struct rndis_request *request; @@ -804,7 +804,7 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev, rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS; rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2; rssp->hdr.size = sizeof(struct ndis_recv_scale_param); - rssp->flag = 0; + rssp->flag = flag; rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 | NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 | NDIS_HASH_TCP_IPV6; @@ -829,9 +829,12 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev, wait_for_completion(&request->wait_event); set_complete = &request->response_msg.msg.set_complete; - if (set_complete->status == RNDIS_STATUS_SUCCESS) - memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN); - else { + if (set_complete->status == RNDIS_STATUS_SUCCESS) { + if (!(flag & NDIS_RSS_PARAM_FLAG_DISABLE_RSS) && + !(flag & NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED)) + memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN); + + } else { netdev_err(ndev, "Fail to set RSS parameters:0x%x\n", set_complete->status); ret = -EINVAL; @@ -842,6 +845,16 @@ cleanup: return ret; } +int rndis_filter_set_rss_param(struct rndis_device *rdev, + const u8 *rss_key) +{ + /* Disable RSS before change */ + rndis_set_rss_param_msg(rdev, rss_key, + NDIS_RSS_PARAM_FLAG_DISABLE_RSS); + + return rndis_set_rss_param_msg(rdev, rss_key, 0); +} + static int rndis_filter_query_device_link_status(struct rndis_device *dev, struct netvsc_device *net_device) { @@ -1121,7 +1134,9 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) * This breaks overlap of processing the host message for the * new primary channel with the initialization of sub-channels. */ -int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev) +int rndis_set_subchannel(struct net_device *ndev, + struct netvsc_device *nvdev, + struct netvsc_device_info *dev_info) { struct nvsp_message *init_packet = &nvdev->channel_init_pkt; struct net_device_context *ndev_ctx = netdev_priv(ndev); @@ -1161,8 +1176,11 @@ int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev) wait_event(nvdev->subchan_open, atomic_read(&nvdev->open_chn) == nvdev->num_chn); - /* ignore failues from setting rss parameters, still have channels */ - rndis_filter_set_rss_param(rdev, netvsc_hash_key); + /* ignore failures from setting rss parameters, still have channels */ + if (dev_info) + rndis_filter_set_rss_param(rdev, dev_info->rss_key); + else + rndis_filter_set_rss_param(rdev, netvsc_hash_key); netif_set_real_num_tx_queues(ndev, nvdev->num_chn); netif_set_real_num_rx_queues(ndev, nvdev->num_chn); diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c index 44de81e5f140..c589f5ae75bb 100644 --- a/drivers/net/ieee802154/mcr20a.c +++ b/drivers/net/ieee802154/mcr20a.c @@ -905,9 +905,9 @@ mcr20a_irq_clean_complete(void *context) } break; case (DAR_IRQSTS1_RXIRQ | DAR_IRQSTS1_SEQIRQ): - /* rx is starting */ - dev_dbg(printdev(lp), "RX is starting\n"); - mcr20a_handle_rx(lp); + /* rx is starting */ + dev_dbg(printdev(lp), "RX is starting\n"); + mcr20a_handle_rx(lp); break; case (DAR_IRQSTS1_RXIRQ | DAR_IRQSTS1_TXIRQ | DAR_IRQSTS1_SEQIRQ): if (lp->is_tx) { diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 19bdde60680c..07e41c42bcf5 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -100,12 +100,12 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval, err = ipvlan_register_nf_hook(read_pnet(&port->pnet)); if (!err) { mdev->l3mdev_ops = &ipvl_l3mdev_ops; - mdev->priv_flags |= IFF_L3MDEV_MASTER; + mdev->priv_flags |= IFF_L3MDEV_RX_HANDLER; } else goto fail; } else if (port->mode == IPVLAN_MODE_L3S) { /* Old mode was L3S */ - mdev->priv_flags &= ~IFF_L3MDEV_MASTER; + mdev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER; ipvlan_unregister_nf_hook(read_pnet(&port->pnet)); mdev->l3mdev_ops = NULL; } @@ -167,7 +167,7 @@ static void ipvlan_port_destroy(struct net_device *dev) struct sk_buff *skb; if (port->mode == IPVLAN_MODE_L3S) { - dev->priv_flags &= ~IFF_L3MDEV_MASTER; + dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER; ipvlan_unregister_nf_hook(dev_net(dev)); dev->l3mdev_ops = NULL; } @@ -499,6 +499,8 @@ static int ipvlan_nl_changelink(struct net_device *dev, if (!data) return 0; + if (!ns_capable(dev_net(ipvlan->phy_dev)->user_ns, CAP_NET_ADMIN)) + return -EPERM; if (data[IFLA_IPVLAN_MODE]) { u16 nmode = nla_get_u16(data[IFLA_IPVLAN_MODE]); @@ -601,6 +603,8 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev, struct ipvl_dev *tmp = netdev_priv(phy_dev); phy_dev = tmp->phy_dev; + if (!ns_capable(dev_net(phy_dev)->user_ns, CAP_NET_ADMIN)) + return -EPERM; } else if (!netif_is_ipvlan_port(phy_dev)) { /* Exit early if the underlying link is invalid or busy */ if (phy_dev->type != ARPHRD_ETHER || diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index fc726ce4c164..6d067176320f 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -337,7 +337,7 @@ static void macvlan_process_broadcast(struct work_struct *w) if (src) dev_put(src->dev); - kfree_skb(skb); + consume_skb(skb); } } diff --git a/drivers/net/phy/asix.c b/drivers/net/phy/asix.c index 8ebe7f5484ae..f14ba5366b91 100644 --- a/drivers/net/phy/asix.c +++ b/drivers/net/phy/asix.c @@ -1,13 +1,7 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0+ /* Driver for Asix PHYs * * Author: Michael Schmitz <schmitzmic@gmail.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * */ #include <linux/kernel.h> #include <linux/errno.h> diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c index 1b350183bffb..a271239748f2 100644 --- a/drivers/net/phy/bcm87xx.c +++ b/drivers/net/phy/bcm87xx.c @@ -197,6 +197,7 @@ static struct phy_driver bcm87xx_driver[] = { .phy_id = PHY_ID_BCM8706, .phy_id_mask = 0xffffffff, .name = "Broadcom BCM8706", + .features = PHY_10GBIT_FEC_FEATURES, .config_init = bcm87xx_config_init, .config_aneg = bcm87xx_config_aneg, .read_status = bcm87xx_read_status, @@ -208,6 +209,7 @@ static struct phy_driver bcm87xx_driver[] = { .phy_id = PHY_ID_BCM8727, .phy_id_mask = 0xffffffff, .name = "Broadcom BCM8727", + .features = PHY_10GBIT_FEC_FEATURES, .config_init = bcm87xx_config_init, .config_aneg = bcm87xx_config_aneg, .read_status = bcm87xx_read_status, diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c index 8022cd317f62..1a4d04afb7f0 100644 --- a/drivers/net/phy/cortina.c +++ b/drivers/net/phy/cortina.c @@ -88,6 +88,7 @@ static struct phy_driver cortina_driver[] = { .phy_id = PHY_ID_CS4340, .phy_id_mask = 0xffffffff, .name = "Cortina CS4340", + .features = PHY_10GBIT_FEATURES, .config_init = gen10g_config_init, .config_aneg = gen10g_config_aneg, .read_status = cortina_read_status, diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 18b41bc345ab..6e8807212aa3 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -898,14 +898,14 @@ static void decode_txts(struct dp83640_private *dp83640, struct phy_txts *phy_txts) { struct skb_shared_hwtstamps shhwtstamps; + struct dp83640_skb_info *skb_info; struct sk_buff *skb; - u64 ns; u8 overflow; + u64 ns; /* We must already have the skb that triggered this. */ - +again: skb = skb_dequeue(&dp83640->tx_queue); - if (!skb) { pr_debug("have timestamp but tx_queue empty\n"); return; @@ -920,6 +920,11 @@ static void decode_txts(struct dp83640_private *dp83640, } return; } + skb_info = (struct dp83640_skb_info *)skb->cb; + if (time_after(jiffies, skb_info->tmo)) { + kfree_skb(skb); + goto again; + } ns = phy2txts(phy_txts); memset(&shhwtstamps, 0, sizeof(shhwtstamps)); @@ -1472,6 +1477,7 @@ static bool dp83640_rxtstamp(struct phy_device *phydev, static void dp83640_txtstamp(struct phy_device *phydev, struct sk_buff *skb, int type) { + struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb; struct dp83640_private *dp83640 = phydev->priv; switch (dp83640->hwts_tx_en) { @@ -1484,6 +1490,7 @@ static void dp83640_txtstamp(struct phy_device *phydev, /* fall through */ case HWTSTAMP_TX_ON: skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT; skb_queue_tail(&dp83640->tx_queue, skb); break; diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index da6a67d47ce9..56fa3606cb9c 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/phy.h> +#include <linux/delay.h> #include <dt-bindings/net/ti-dp83867.h> @@ -325,6 +326,8 @@ static int dp83867_phy_reset(struct phy_device *phydev) if (err < 0) return err; + usleep_range(10, 20); + return dp83867_config_init(phydev); } diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index a9c7c7f41b0c..abb7876a8776 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -847,7 +847,6 @@ static int m88e1510_config_init(struct phy_device *phydev) /* SGMII-to-Copper mode initialization */ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { - /* Select page 18 */ err = marvell_set_page(phydev, 18); if (err < 0) @@ -870,21 +869,6 @@ static int m88e1510_config_init(struct phy_device *phydev) err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE); if (err < 0) return err; - - /* There appears to be a bug in the 88e1512 when used in - * SGMII to copper mode, where the AN advertisement register - * clears the pause bits each time a negotiation occurs. - * This means we can never be truely sure what was advertised, - * so disable Pause support. - */ - linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, - phydev->supported); - linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, - phydev->supported); - linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, - phydev->advertising); - linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, - phydev->advertising); } return m88e1318_config_init(phydev); @@ -1046,6 +1030,39 @@ static int m88e1145_config_init(struct phy_device *phydev) return 0; } +/* The VOD can be out of specification on link up. Poke an + * undocumented register, in an undocumented page, with a magic value + * to fix this. + */ +static int m88e6390_errata(struct phy_device *phydev) +{ + int err; + + err = phy_write(phydev, MII_BMCR, + BMCR_ANENABLE | BMCR_SPEED1000 | BMCR_FULLDPLX); + if (err) + return err; + + usleep_range(300, 400); + + err = phy_write_paged(phydev, 0xf8, 0x08, 0x36); + if (err) + return err; + + return genphy_soft_reset(phydev); +} + +static int m88e6390_config_aneg(struct phy_device *phydev) +{ + int err; + + err = m88e6390_errata(phydev); + if (err) + return err; + + return m88e1510_config_aneg(phydev); +} + /** * fiber_lpa_mod_linkmode_lpa_t * @advertising: the linkmode advertisement settings @@ -1402,7 +1419,7 @@ static int m88e1318_set_wol(struct phy_device *phydev, * before enabling it if !phy_interrupt_is_valid() */ if (!phy_interrupt_is_valid(phydev)) - phy_read(phydev, MII_M1011_IEVENT); + __phy_read(phydev, MII_M1011_IEVENT); /* Enable the WOL interrupt */ err = __phy_modify(phydev, MII_88E1318S_PHY_CSIER, 0, @@ -2283,7 +2300,7 @@ static struct phy_driver marvell_drivers[] = { .features = PHY_GBIT_FEATURES, .probe = m88e6390_probe, .config_init = &marvell_config_init, - .config_aneg = &m88e1510_config_aneg, + .config_aneg = &m88e6390_config_aneg, .read_status = &marvell_read_status, .ack_interrupt = &marvell_ack_interrupt, .config_intr = &marvell_config_intr, diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 82ab6ed3b74e..6bac602094bd 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -26,6 +26,8 @@ #include <linux/marvell_phy.h> #include <linux/phy.h> +#define MDIO_AN_10GBT_CTRL_ADV_NBT_MASK 0x01e0 + enum { MV_PCS_BASE_T = 0x0000, MV_PCS_BASE_R = 0x1000, @@ -386,8 +388,10 @@ static int mv3310_config_aneg(struct phy_device *phydev) else reg = 0; + /* Make sure we clear unsupported 2.5G/5G advertising */ ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV10G, reg); + MDIO_AN_10GBT_CTRL_ADV10G | + MDIO_AN_10GBT_CTRL_ADV_NBT_MASK, reg); if (ret < 0) return ret; if (ret > 0) diff --git a/drivers/net/phy/mdio-hisi-femac.c b/drivers/net/phy/mdio-hisi-femac.c index b03fedd6c1d8..287f3ccf1da1 100644 --- a/drivers/net/phy/mdio-hisi-femac.c +++ b/drivers/net/phy/mdio-hisi-femac.c @@ -1,20 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Hisilicon Fast Ethernet MDIO Bus Driver * * Copyright (c) 2016 HiSilicon Technologies Co., Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/clk.h> @@ -163,4 +151,4 @@ module_platform_driver(hisi_femac_mdio_driver); MODULE_DESCRIPTION("Hisilicon Fast Ethernet MAC MDIO interface driver"); MODULE_AUTHOR("Dongpo Li <lidongpo@hisilicon.com>"); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 2e59a8419b17..7368616286ae 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -379,7 +379,6 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) err = device_register(&bus->dev); if (err) { pr_err("mii_bus %s failed to register\n", bus->id); - put_device(&bus->dev); return -EINVAL; } @@ -390,6 +389,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) if (IS_ERR(gpiod)) { dev_err(&bus->dev, "mii_bus %s couldn't get reset GPIO\n", bus->id); + device_del(&bus->dev); return PTR_ERR(gpiod); } else if (gpiod) { bus->reset_gpiod = gpiod; diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c index b03bcf2c388a..3ddaf9595697 100644 --- a/drivers/net/phy/meson-gxl.c +++ b/drivers/net/phy/meson-gxl.c @@ -233,6 +233,7 @@ static struct phy_driver meson_gxl_phy[] = { .name = "Meson GXL Internal PHY", .features = PHY_BASIC_FEATURES, .flags = PHY_IS_INTERNAL, + .soft_reset = genphy_soft_reset, .config_init = meson_gxl_config_init, .aneg_done = genphy_aneg_done, .read_status = meson_gxl_read_status, diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index c33384710d26..b7df0295a3ca 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -344,6 +344,17 @@ static int ksz8041_config_aneg(struct phy_device *phydev) return genphy_config_aneg(phydev); } +static int ksz8061_config_init(struct phy_device *phydev) +{ + int ret; + + ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A); + if (ret) + return ret; + + return kszphy_config_init(phydev); +} + static int ksz9021_load_values_from_of(struct phy_device *phydev, const struct device_node *of_node, u16 reg, @@ -1040,7 +1051,7 @@ static struct phy_driver ksphy_driver[] = { .name = "Micrel KSZ8061", .phy_id_mask = MICREL_PHY_ID_MASK, .features = PHY_BASIC_FEATURES, - .config_init = kszphy_config_init, + .config_init = ksz8061_config_init, .ack_interrupt = kszphy_ack_interrupt, .config_intr = kszphy_config_intr, .suspend = genphy_suspend, @@ -1070,6 +1081,7 @@ static struct phy_driver ksphy_driver[] = { .driver_data = &ksz9021_type, .probe = kszphy_probe, .config_init = ksz9031_config_init, + .soft_reset = genphy_soft_reset, .read_status = ksz9031_read_status, .ack_interrupt = kszphy_ack_interrupt, .config_intr = kszphy_config_intr, @@ -1098,6 +1110,7 @@ static struct phy_driver ksphy_driver[] = { .phy_id = PHY_ID_KSZ8873MLL, .phy_id_mask = MICREL_PHY_ID_MASK, .name = "Micrel KSZ8873MLL Switch", + .features = PHY_BASIC_FEATURES, .config_init = kszphy_config_init, .config_aneg = ksz8873mll_config_aneg, .read_status = ksz8873mll_read_status, diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index d33e7b3caf03..c5675df5fc6f 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -543,13 +543,6 @@ int phy_start_aneg(struct phy_device *phydev) mutex_lock(&phydev->lock); - if (!__phy_is_started(phydev)) { - WARN(1, "called from state %s\n", - phy_state_to_str(phydev->state)); - err = -EBUSY; - goto out_unlock; - } - if (AUTONEG_DISABLE == phydev->autoneg) phy_sanitize_settings(phydev); @@ -560,11 +553,13 @@ int phy_start_aneg(struct phy_device *phydev) if (err < 0) goto out_unlock; - if (phydev->autoneg == AUTONEG_ENABLE) { - err = phy_check_link_status(phydev); - } else { - phydev->state = PHY_FORCING; - phydev->link_timeout = PHY_FORCE_TIMEOUT; + if (phy_is_started(phydev)) { + if (phydev->autoneg == AUTONEG_ENABLE) { + err = phy_check_link_status(phydev); + } else { + phydev->state = PHY_FORCING; + phydev->link_timeout = PHY_FORCE_TIMEOUT; + } } out_unlock: @@ -714,7 +709,7 @@ void phy_stop_machine(struct phy_device *phydev) cancel_delayed_work_sync(&phydev->state_queue); mutex_lock(&phydev->lock); - if (__phy_is_started(phydev)) + if (phy_is_started(phydev)) phydev->state = PHY_UP; mutex_unlock(&phydev->lock); } @@ -767,9 +762,6 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat) { struct phy_device *phydev = phy_dat; - if (!phy_is_started(phydev)) - return IRQ_NONE; /* It can't be ours. */ - if (phydev->drv->did_interrupt && !phydev->drv->did_interrupt(phydev)) return IRQ_NONE; @@ -847,15 +839,14 @@ EXPORT_SYMBOL(phy_stop_interrupts); */ void phy_stop(struct phy_device *phydev) { - mutex_lock(&phydev->lock); - - if (!__phy_is_started(phydev)) { + if (!phy_is_started(phydev)) { WARN(1, "called from state %s\n", phy_state_to_str(phydev->state)); - mutex_unlock(&phydev->lock); return; } + mutex_lock(&phydev->lock); + if (phy_interrupt_is_valid(phydev)) phy_disable_interrupts(phydev); @@ -994,8 +985,10 @@ void phy_state_machine(struct work_struct *work) * state machine would be pointless and possibly error prone when * called from phy_disconnect() synchronously. */ + mutex_lock(&phydev->lock); if (phy_polling_mode(phydev) && phy_is_started(phydev)) phy_queue_state_machine(phydev, PHY_STATE_TIME); + mutex_unlock(&phydev->lock); } /** diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 51990002d495..46c86725a693 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -61,6 +61,9 @@ EXPORT_SYMBOL_GPL(phy_gbit_all_ports_features); __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init; EXPORT_SYMBOL_GPL(phy_10gbit_features); +__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init; +EXPORT_SYMBOL_GPL(phy_10gbit_fec_features); + static const int phy_basic_ports_array[] = { ETHTOOL_LINK_MODE_Autoneg_BIT, ETHTOOL_LINK_MODE_TP_BIT, @@ -109,6 +112,11 @@ const int phy_10gbit_features_array[1] = { }; EXPORT_SYMBOL_GPL(phy_10gbit_features_array); +const int phy_10gbit_fec_features_array[1] = { + ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, +}; +EXPORT_SYMBOL_GPL(phy_10gbit_fec_features_array); + __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init; EXPORT_SYMBOL_GPL(phy_10gbit_full_features); @@ -191,6 +199,10 @@ static void features_init(void) linkmode_set_bit_array(phy_10gbit_full_features_array, ARRAY_SIZE(phy_10gbit_full_features_array), phy_10gbit_full_features); + /* 10G FEC only */ + linkmode_set_bit_array(phy_10gbit_fec_features_array, + ARRAY_SIZE(phy_10gbit_fec_features_array), + phy_10gbit_fec_features); } void phy_device_free(struct phy_device *phydev) @@ -2243,6 +2255,11 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner) { int retval; + if (WARN_ON(!new_driver->features)) { + pr_err("%s: Driver features are missing\n", new_driver->name); + return -EINVAL; + } + new_driver->mdiodrv.flags |= MDIO_DEVICE_IS_PHY; new_driver->mdiodrv.driver.name = new_driver->name; new_driver->mdiodrv.driver.bus = &mdio_bus_type; diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index e7becc7379d7..85987aac31c4 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -320,6 +320,10 @@ static int phylink_get_mac_state(struct phylink *pl, struct phylink_link_state * linkmode_zero(state->lp_advertising); state->interface = pl->link_config.interface; state->an_enabled = pl->link_config.an_enabled; + state->speed = SPEED_UNKNOWN; + state->duplex = DUPLEX_UNKNOWN; + state->pause = MLO_PAUSE_NONE; + state->an_complete = 0; state->link = 1; return pl->ops->mac_link_state(ndev, state); @@ -474,6 +478,17 @@ static void phylink_run_resolve(struct phylink *pl) queue_work(system_power_efficient_wq, &pl->resolve); } +static void phylink_run_resolve_and_disable(struct phylink *pl, int bit) +{ + unsigned long state = pl->phylink_disable_state; + + set_bit(bit, &pl->phylink_disable_state); + if (state == 0) { + queue_work(system_power_efficient_wq, &pl->resolve); + flush_work(&pl->resolve); + } +} + static void phylink_fixed_poll(struct timer_list *t) { struct phylink *pl = container_of(t, struct phylink, link_poll); @@ -924,9 +939,7 @@ void phylink_stop(struct phylink *pl) if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio)) del_timer_sync(&pl->link_poll); - set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); - queue_work(system_power_efficient_wq, &pl->resolve); - flush_work(&pl->resolve); + phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED); } EXPORT_SYMBOL_GPL(phylink_stop); @@ -1632,9 +1645,7 @@ static void phylink_sfp_link_down(void *upstream) ASSERT_RTNL(); - set_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state); - queue_work(system_power_efficient_wq, &pl->resolve); - flush_work(&pl->resolve); + phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_LINK); } static void phylink_sfp_link_up(void *upstream) diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index c6010fb1aa0f..cb4a23041a94 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -282,6 +282,13 @@ static struct phy_driver realtek_drvs[] = { .name = "RTL8366RB Gigabit Ethernet", .features = PHY_GBIT_FEATURES, .config_init = &rtl8366rb_config_init, + /* These interrupts are handled by the irq controller + * embedded inside the RTL8366RB, they get unmasked when the + * irq is requested and ACKed by reading the status register, + * which is done by the irqchip code. + */ + .ack_interrupt = genphy_no_ack_interrupt, + .config_intr = genphy_no_config_intr, .suspend = genphy_suspend, .resume = genphy_resume, }, diff --git a/drivers/net/phy/rockchip.c b/drivers/net/phy/rockchip.c index f1da70b9b55f..95abf7072f32 100644 --- a/drivers/net/phy/rockchip.c +++ b/drivers/net/phy/rockchip.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /** * drivers/net/phy/rockchip.c * @@ -6,12 +7,6 @@ * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd * * David Wu <david.wu@rock-chips.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * */ #include <linux/ethtool.h> @@ -229,4 +224,4 @@ MODULE_DEVICE_TABLE(mdio, rockchip_phy_tbl); MODULE_AUTHOR("David Wu <david.wu@rock-chips.com>"); MODULE_DESCRIPTION("Rockchip Ethernet PHY driver"); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c index ad9db652874d..fef701bfad62 100644 --- a/drivers/net/phy/sfp-bus.c +++ b/drivers/net/phy/sfp-bus.c @@ -347,6 +347,7 @@ static int sfp_register_bus(struct sfp_bus *bus) return ret; } } + bus->socket_ops->attach(bus->sfp); if (bus->started) bus->socket_ops->start(bus->sfp); bus->netdev->sfp_bus = bus; @@ -362,6 +363,7 @@ static void sfp_unregister_bus(struct sfp_bus *bus) if (bus->registered) { if (bus->started) bus->socket_ops->stop(bus->sfp); + bus->socket_ops->detach(bus->sfp); if (bus->phydev && ops && ops->disconnect_phy) ops->disconnect_phy(bus->upstream); } diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index fd8bb998ae52..68c8fbf099f8 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -184,6 +184,7 @@ struct sfp { struct gpio_desc *gpio[GPIO_MAX]; + bool attached; unsigned int state; struct delayed_work poll; struct delayed_work timeout; @@ -1475,7 +1476,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event) */ switch (sfp->sm_mod_state) { default: - if (event == SFP_E_INSERT) { + if (event == SFP_E_INSERT && sfp->attached) { sfp_module_tx_disable(sfp); sfp_sm_ins_next(sfp, SFP_MOD_PROBE, T_PROBE_INIT); } @@ -1607,6 +1608,19 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event) mutex_unlock(&sfp->sm_mutex); } +static void sfp_attach(struct sfp *sfp) +{ + sfp->attached = true; + if (sfp->state & SFP_F_PRESENT) + sfp_sm_event(sfp, SFP_E_INSERT); +} + +static void sfp_detach(struct sfp *sfp) +{ + sfp->attached = false; + sfp_sm_event(sfp, SFP_E_REMOVE); +} + static void sfp_start(struct sfp *sfp) { sfp_sm_event(sfp, SFP_E_DEV_UP); @@ -1667,6 +1681,8 @@ static int sfp_module_eeprom(struct sfp *sfp, struct ethtool_eeprom *ee, } static const struct sfp_socket_ops sfp_module_ops = { + .attach = sfp_attach, + .detach = sfp_detach, .start = sfp_start, .stop = sfp_stop, .module_info = sfp_module_info, @@ -1834,10 +1850,6 @@ static int sfp_probe(struct platform_device *pdev) dev_info(sfp->dev, "Host maximum power %u.%uW\n", sfp->max_power_mW / 1000, (sfp->max_power_mW / 100) % 10); - sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops); - if (!sfp->sfp_bus) - return -ENOMEM; - /* Get the initial state, and always signal TX disable, * since the network interface will not be up. */ @@ -1848,10 +1860,6 @@ static int sfp_probe(struct platform_device *pdev) sfp->state |= SFP_F_RATE_SELECT; sfp_set_state(sfp, sfp->state); sfp_module_tx_disable(sfp); - rtnl_lock(); - if (sfp->state & SFP_F_PRESENT) - sfp_sm_event(sfp, SFP_E_INSERT); - rtnl_unlock(); for (i = 0; i < GPIO_MAX; i++) { if (gpio_flags[i] != GPIOD_IN || !sfp->gpio[i]) @@ -1884,6 +1892,10 @@ static int sfp_probe(struct platform_device *pdev) dev_warn(sfp->dev, "No tx_disable pin: SFP modules will always be emitting.\n"); + sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops); + if (!sfp->sfp_bus) + return -ENOMEM; + return 0; } diff --git a/drivers/net/phy/sfp.h b/drivers/net/phy/sfp.h index 31b0acf337e2..64f54b0bbd8c 100644 --- a/drivers/net/phy/sfp.h +++ b/drivers/net/phy/sfp.h @@ -7,6 +7,8 @@ struct sfp; struct sfp_socket_ops { + void (*attach)(struct sfp *sfp); + void (*detach)(struct sfp *sfp); void (*start)(struct sfp *sfp); void (*stop)(struct sfp *sfp); int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo); diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c index 22f3bdd8206c..91247182bc52 100644 --- a/drivers/net/phy/teranetics.c +++ b/drivers/net/phy/teranetics.c @@ -80,6 +80,7 @@ static struct phy_driver teranetics_driver[] = { .phy_id = PHY_ID_TN2020, .phy_id_mask = 0xffffffff, .name = "Teranetics TN2020", + .features = PHY_10GBIT_FEATURES, .soft_reset = gen10g_no_soft_reset, .aneg_done = teranetics_aneg_done, .config_init = gen10g_config_init, diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c index 74a8782313cf..bd6084e315de 100644 --- a/drivers/net/phy/xilinx_gmii2rgmii.c +++ b/drivers/net/phy/xilinx_gmii2rgmii.c @@ -44,7 +44,10 @@ static int xgmiitorgmii_read_status(struct phy_device *phydev) u16 val = 0; int err; - err = priv->phy_drv->read_status(phydev); + if (priv->phy_drv->read_status) + err = priv->phy_drv->read_status(phydev); + else + err = genphy_read_status(phydev); if (err < 0) return err; diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index 62dc564b251d..f22639f0116a 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -445,6 +445,7 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev, if (pskb_trim_rcsum(skb, len)) goto drop; + ph = pppoe_hdr(skb); pn = pppoe_pernet(dev_net(dev)); /* Note that get_item does a sock_hold(), so sk_pppox(po) diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index afd9d25d1992..6ce3f666d142 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -256,17 +256,6 @@ static void __team_option_inst_mark_removed_port(struct team *team, } } -static bool __team_option_inst_tmp_find(const struct list_head *opts, - const struct team_option_inst *needle) -{ - struct team_option_inst *opt_inst; - - list_for_each_entry(opt_inst, opts, tmp_list) - if (opt_inst == needle) - return true; - return false; -} - static int __team_options_register(struct team *team, const struct team_option *option, size_t option_count) @@ -1267,7 +1256,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev, list_add_tail_rcu(&port->list, &team->port_list); team_port_enable(team, port); __team_compute_features(team); - __team_port_change_port_added(port, !!netif_carrier_ok(port_dev)); + __team_port_change_port_added(port, !!netif_oper_up(port_dev)); __team_options_change_check(team); netdev_info(dev, "Port device %s added\n", portname); @@ -2460,7 +2449,6 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) int err = 0; int i; struct nlattr *nl_option; - LIST_HEAD(opt_inst_list); rtnl_lock(); @@ -2480,6 +2468,7 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) struct nlattr *opt_attrs[TEAM_ATTR_OPTION_MAX + 1]; struct nlattr *attr; struct nlattr *attr_data; + LIST_HEAD(opt_inst_list); enum team_option_type opt_type; int opt_port_ifindex = 0; /* != 0 for per-port options */ u32 opt_array_index = 0; @@ -2584,23 +2573,17 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) if (err) goto team_put; opt_inst->changed = true; - - /* dumb/evil user-space can send us duplicate opt, - * keep only the last one - */ - if (__team_option_inst_tmp_find(&opt_inst_list, - opt_inst)) - continue; - list_add(&opt_inst->tmp_list, &opt_inst_list); } if (!opt_found) { err = -ENOENT; goto team_put; } - } - err = team_nl_send_event_options_get(team, &opt_inst_list); + err = team_nl_send_event_options_get(team, &opt_inst_list); + if (err) + break; + } team_put: team_nl_team_put(team); @@ -2932,7 +2915,7 @@ static int team_device_event(struct notifier_block *unused, switch (event) { case NETDEV_UP: - if (netif_carrier_ok(dev)) + if (netif_oper_up(dev)) team_port_change_check(port, true); break; case NETDEV_DOWN: diff --git a/drivers/net/tun.c b/drivers/net/tun.c index a4fdad475594..53f4f37b0ffd 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -856,10 +856,6 @@ static int tun_attach(struct tun_struct *tun, struct file *file, err = 0; } - rcu_assign_pointer(tfile->tun, tun); - rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile); - tun->numqueues++; - if (tfile->detached) { tun_enable_queue(tfile); } else { @@ -870,12 +866,18 @@ static int tun_attach(struct tun_struct *tun, struct file *file, if (rtnl_dereference(tun->xdp_prog)) sock_set_flag(&tfile->sk, SOCK_XDP); - tun_set_real_num_queues(tun); - /* device is allowed to go away first, so no need to hold extra * refcnt. */ + /* Publish tfile->tun and tun->tfiles only after we've fully + * initialized tfile; otherwise we risk using half-initialized + * object. + */ + rcu_assign_pointer(tfile->tun, tun); + rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile); + tun->numqueues++; + tun_set_real_num_queues(tun); out: return err; } @@ -2165,9 +2167,9 @@ static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err) } add_wait_queue(&tfile->wq.wait, &wait); - current->state = TASK_INTERRUPTIBLE; while (1) { + set_current_state(TASK_INTERRUPTIBLE); ptr = ptr_ring_consume(&tfile->tx_ring); if (ptr) break; @@ -2183,7 +2185,7 @@ static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err) schedule(); } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&tfile->wq.wait, &wait); out: diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c index 57f1c94fca0b..820a2fe7d027 100644 --- a/drivers/net/usb/aqc111.c +++ b/drivers/net/usb/aqc111.c @@ -1287,6 +1287,20 @@ static const struct driver_info asix112_info = { #undef ASIX112_DESC +static const struct driver_info trendnet_info = { + .description = "USB-C 3.1 to 5GBASE-T Ethernet Adapter", + .bind = aqc111_bind, + .unbind = aqc111_unbind, + .status = aqc111_status, + .link_reset = aqc111_link_reset, + .reset = aqc111_reset, + .stop = aqc111_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | + FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET, + .rx_fixup = aqc111_rx_fixup, + .tx_fixup = aqc111_tx_fixup, +}; + static int aqc111_suspend(struct usb_interface *intf, pm_message_t message) { struct usbnet *dev = usb_get_intfdata(intf); @@ -1440,6 +1454,7 @@ static const struct usb_device_id products[] = { {AQC111_USB_ETH_DEV(0x2eca, 0xc101, aqc111_info)}, {AQC111_USB_ETH_DEV(0x0b95, 0x2790, asix111_info)}, {AQC111_USB_ETH_DEV(0x0b95, 0x2791, asix112_info)}, + {AQC111_USB_ETH_DEV(0x20f4, 0xe05a, trendnet_info)}, { },/* END */ }; MODULE_DEVICE_TABLE(usb, products); diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index b654f05b2ccd..3d93993e74da 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -739,8 +739,13 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0); chipcode &= AX_CHIPCODE_MASK; - (chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) : - ax88772a_hw_reset(dev, 0); + ret = (chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) : + ax88772a_hw_reset(dev, 0); + + if (ret < 0) { + netdev_dbg(dev->net, "Failed to reset AX88772: %d\n", ret); + return ret; + } /* Read PHYID register *AFTER* the PHY was reset properly */ phyid = asix_get_phyid(dev); diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index b3b3c05903a1..5512a1038721 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -179,10 +179,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) * probed with) and a slave/data interface; union * descriptors sort this all out. */ - info->control = usb_ifnum_to_if(dev->udev, - info->u->bMasterInterface0); - info->data = usb_ifnum_to_if(dev->udev, - info->u->bSlaveInterface0); + info->control = usb_ifnum_to_if(dev->udev, info->u->bMasterInterface0); + info->data = usb_ifnum_to_if(dev->udev, info->u->bSlaveInterface0); if (!info->control || !info->data) { dev_dbg(&intf->dev, "master #%u/%p slave #%u/%p\n", @@ -216,18 +214,16 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) /* a data interface altsetting does the real i/o */ d = &info->data->cur_altsetting->desc; if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { - dev_dbg(&intf->dev, "slave class %u\n", - d->bInterfaceClass); + dev_dbg(&intf->dev, "slave class %u\n", d->bInterfaceClass); goto bad_desc; } skip: - if ( rndis && - header.usb_cdc_acm_descriptor && - header.usb_cdc_acm_descriptor->bmCapabilities) { - dev_dbg(&intf->dev, - "ACM capabilities %02x, not really RNDIS?\n", - header.usb_cdc_acm_descriptor->bmCapabilities); - goto bad_desc; + if (rndis && header.usb_cdc_acm_descriptor && + header.usb_cdc_acm_descriptor->bmCapabilities) { + dev_dbg(&intf->dev, + "ACM capabilities %02x, not really RNDIS?\n", + header.usb_cdc_acm_descriptor->bmCapabilities); + goto bad_desc; } if (header.usb_cdc_ether_desc && info->ether->wMaxSegmentSize) { @@ -238,7 +234,7 @@ skip: } if (header.usb_cdc_mdlm_desc && - memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) { + memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) { dev_dbg(&intf->dev, "GUID doesn't match\n"); goto bad_desc; } @@ -302,7 +298,7 @@ skip: if (info->control->cur_altsetting->desc.bNumEndpoints == 1) { struct usb_endpoint_descriptor *desc; - dev->status = &info->control->cur_altsetting->endpoint [0]; + dev->status = &info->control->cur_altsetting->endpoint[0]; desc = &dev->status->desc; if (!usb_endpoint_is_int_in(desc) || (le16_to_cpu(desc->wMaxPacketSize) @@ -847,6 +843,14 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* USB-C 3.1 to 5GBASE-T Ethernet Adapter (based on AQC111U) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0xe05a, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* WHITELIST!!! * * CDC Ether uses two interfaces, not necessarily consecutive. diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 774e1ff01c9a..18af2f8eee96 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -123,6 +123,7 @@ static void qmimux_setup(struct net_device *dev) dev->addr_len = 0; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; dev->netdev_ops = &qmimux_netdev_ops; + dev->mtu = 1500; dev->needs_free_netdev = true; } @@ -1200,8 +1201,8 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ - {QMI_FIXED_INTF(0x1199, 0x68c0, 8)}, /* Sierra Wireless MC7304/MC7354 */ - {QMI_FIXED_INTF(0x1199, 0x68c0, 10)}, /* Sierra Wireless MC7304/MC7354 */ + {QMI_QUIRK_SET_DTR(0x1199, 0x68c0, 8)}, /* Sierra Wireless MC7304/MC7354, WP76xx */ + {QMI_QUIRK_SET_DTR(0x1199, 0x68c0, 10)},/* Sierra Wireless MC7304/MC7354 */ {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ {QMI_FIXED_INTF(0x1199, 0x901f, 8)}, /* Sierra Wireless EM7355 */ {QMI_FIXED_INTF(0x1199, 0x9041, 8)}, /* Sierra Wireless MC7305/MC7355 */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 60dd1ec1665f..86c8c64fbb0f 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -557,6 +557,7 @@ enum spd_duplex { /* MAC PASSTHRU */ #define AD_MASK 0xfee0 #define BND_MASK 0x0004 +#define BD_MASK 0x0001 #define EFUSE 0xcfdb #define PASS_THRU_MASK 0x1 @@ -1176,9 +1177,9 @@ static int vendor_mac_passthru_addr_read(struct r8152 *tp, struct sockaddr *sa) return -ENODEV; } } else { - /* test for RTL8153-BND */ + /* test for RTL8153-BND and RTL8153-BD */ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_1); - if ((ocp_data & BND_MASK) == 0) { + if ((ocp_data & BND_MASK) == 0 && (ocp_data & BD_MASK) == 0) { netif_dbg(tp, probe, tp->netdev, "Invalid variant for MAC pass through\n"); return -ENODEV; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 023725086046..4cfceb789eea 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -57,6 +57,8 @@ module_param(napi_tx, bool, 0644); #define VIRTIO_XDP_TX BIT(0) #define VIRTIO_XDP_REDIR BIT(1) +#define VIRTIO_XDP_FLAG BIT(0) + /* RX packet size EWMA. The average packet size is used to determine the packet * buffer size when refilling RX rings. As the entire RX ring may be refilled * at once, the weight is chosen so that the EWMA will be insensitive to short- @@ -252,6 +254,21 @@ struct padded_vnet_hdr { char padding[4]; }; +static bool is_xdp_frame(void *ptr) +{ + return (unsigned long)ptr & VIRTIO_XDP_FLAG; +} + +static void *xdp_to_ptr(struct xdp_frame *ptr) +{ + return (void *)((unsigned long)ptr | VIRTIO_XDP_FLAG); +} + +static struct xdp_frame *ptr_to_xdp(void *ptr) +{ + return (struct xdp_frame *)((unsigned long)ptr & ~VIRTIO_XDP_FLAG); +} + /* Converting between virtqueue no. and kernel tx/rx queue no. * 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq */ @@ -462,7 +479,8 @@ static int __virtnet_xdp_xmit_one(struct virtnet_info *vi, sg_init_one(sq->sg, xdpf->data, xdpf->len); - err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdpf, GFP_ATOMIC); + err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdp_to_ptr(xdpf), + GFP_ATOMIC); if (unlikely(err)) return -ENOSPC; /* Caller handle free/refcnt */ @@ -482,36 +500,47 @@ static int virtnet_xdp_xmit(struct net_device *dev, { struct virtnet_info *vi = netdev_priv(dev); struct receive_queue *rq = vi->rq; - struct xdp_frame *xdpf_sent; struct bpf_prog *xdp_prog; struct send_queue *sq; unsigned int len; + int packets = 0; + int bytes = 0; int drops = 0; int kicks = 0; int ret, err; + void *ptr; int i; - sq = virtnet_xdp_sq(vi); - - if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) { - ret = -EINVAL; - drops = n; - goto out; - } - /* Only allow ndo_xdp_xmit if XDP is loaded on dev, as this * indicate XDP resources have been successfully allocated. */ xdp_prog = rcu_dereference(rq->xdp_prog); - if (!xdp_prog) { - ret = -ENXIO; + if (!xdp_prog) + return -ENXIO; + + sq = virtnet_xdp_sq(vi); + + if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) { + ret = -EINVAL; drops = n; goto out; } /* Free up any pending old buffers before queueing new ones. */ - while ((xdpf_sent = virtqueue_get_buf(sq->vq, &len)) != NULL) - xdp_return_frame(xdpf_sent); + while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) { + if (likely(is_xdp_frame(ptr))) { + struct xdp_frame *frame = ptr_to_xdp(ptr); + + bytes += frame->len; + xdp_return_frame(frame); + } else { + struct sk_buff *skb = ptr; + + bytes += skb->len; + napi_consume_skb(skb, false); + } + packets++; + } for (i = 0; i < n; i++) { struct xdp_frame *xdpf = frames[i]; @@ -530,6 +559,8 @@ static int virtnet_xdp_xmit(struct net_device *dev, } out: u64_stats_update_begin(&sq->stats.syncp); + sq->stats.bytes += bytes; + sq->stats.packets += packets; sq->stats.xdp_tx += n; sq->stats.xdp_tx_drops += drops; sq->stats.kicks += kicks; @@ -1330,20 +1361,28 @@ static int virtnet_receive(struct receive_queue *rq, int budget, return stats.packets; } -static void free_old_xmit_skbs(struct send_queue *sq) +static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi) { - struct sk_buff *skb; unsigned int len; unsigned int packets = 0; unsigned int bytes = 0; + void *ptr; - while ((skb = virtqueue_get_buf(sq->vq, &len)) != NULL) { - pr_debug("Sent skb %p\n", skb); + while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) { + if (likely(!is_xdp_frame(ptr))) { + struct sk_buff *skb = ptr; - bytes += skb->len; - packets++; + pr_debug("Sent skb %p\n", skb); + + bytes += skb->len; + napi_consume_skb(skb, in_napi); + } else { + struct xdp_frame *frame = ptr_to_xdp(ptr); - dev_consume_skb_any(skb); + bytes += frame->len; + xdp_return_frame(frame); + } + packets++; } /* Avoid overhead when no packets have been processed @@ -1358,6 +1397,16 @@ static void free_old_xmit_skbs(struct send_queue *sq) u64_stats_update_end(&sq->stats.syncp); } +static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q) +{ + if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs)) + return false; + else if (q < vi->curr_queue_pairs) + return true; + else + return false; +} + static void virtnet_poll_cleantx(struct receive_queue *rq) { struct virtnet_info *vi = rq->vq->vdev->priv; @@ -1365,11 +1414,11 @@ static void virtnet_poll_cleantx(struct receive_queue *rq) struct send_queue *sq = &vi->sq[index]; struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, index); - if (!sq->napi.weight) + if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index)) return; if (__netif_tx_trylock(txq)) { - free_old_xmit_skbs(sq); + free_old_xmit_skbs(sq, true); __netif_tx_unlock(txq); } @@ -1442,10 +1491,18 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget) { struct send_queue *sq = container_of(napi, struct send_queue, napi); struct virtnet_info *vi = sq->vq->vdev->priv; - struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, vq2txq(sq->vq)); + unsigned int index = vq2txq(sq->vq); + struct netdev_queue *txq; + if (unlikely(is_xdp_raw_buffer_queue(vi, index))) { + /* We don't need to enable cb for XDP */ + napi_complete_done(napi, 0); + return 0; + } + + txq = netdev_get_tx_queue(vi->dev, index); __netif_tx_lock(txq, raw_smp_processor_id()); - free_old_xmit_skbs(sq); + free_old_xmit_skbs(sq, true); __netif_tx_unlock(txq); virtqueue_napi_complete(napi, sq->vq, 0); @@ -1514,7 +1571,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) bool use_napi = sq->napi.weight; /* Free up any pending old buffers before queueing new ones. */ - free_old_xmit_skbs(sq); + free_old_xmit_skbs(sq, false); if (use_napi && kick) virtqueue_enable_cb_delayed(sq->vq); @@ -1557,7 +1614,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) if (!use_napi && unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { /* More just got used, free them then recheck. */ - free_old_xmit_skbs(sq); + free_old_xmit_skbs(sq, false); if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) { netif_start_subqueue(dev, qnum); virtqueue_disable_cb(sq->vq); @@ -2395,6 +2452,10 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog, return -ENOMEM; } + old_prog = rtnl_dereference(vi->rq[0].xdp_prog); + if (!prog && !old_prog) + return 0; + if (prog) { prog = bpf_prog_add(prog, vi->max_queue_pairs - 1); if (IS_ERR(prog)) @@ -2402,36 +2463,62 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog, } /* Make sure NAPI is not using any XDP TX queues for RX. */ - if (netif_running(dev)) - for (i = 0; i < vi->max_queue_pairs; i++) + if (netif_running(dev)) { + for (i = 0; i < vi->max_queue_pairs; i++) { napi_disable(&vi->rq[i].napi); + virtnet_napi_tx_disable(&vi->sq[i].napi); + } + } + + if (!prog) { + for (i = 0; i < vi->max_queue_pairs; i++) { + rcu_assign_pointer(vi->rq[i].xdp_prog, prog); + if (i == 0) + virtnet_restore_guest_offloads(vi); + } + synchronize_net(); + } - netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp); err = _virtnet_set_queues(vi, curr_qp + xdp_qp); if (err) goto err; + netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp); vi->xdp_queue_pairs = xdp_qp; - for (i = 0; i < vi->max_queue_pairs; i++) { - old_prog = rtnl_dereference(vi->rq[i].xdp_prog); - rcu_assign_pointer(vi->rq[i].xdp_prog, prog); - if (i == 0) { - if (!old_prog) + if (prog) { + for (i = 0; i < vi->max_queue_pairs; i++) { + rcu_assign_pointer(vi->rq[i].xdp_prog, prog); + if (i == 0 && !old_prog) virtnet_clear_guest_offloads(vi); - if (!prog) - virtnet_restore_guest_offloads(vi); } + } + + for (i = 0; i < vi->max_queue_pairs; i++) { if (old_prog) bpf_prog_put(old_prog); - if (netif_running(dev)) + if (netif_running(dev)) { virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi); + virtnet_napi_tx_enable(vi, vi->sq[i].vq, + &vi->sq[i].napi); + } } return 0; err: - for (i = 0; i < vi->max_queue_pairs; i++) - virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi); + if (!prog) { + virtnet_clear_guest_offloads(vi); + for (i = 0; i < vi->max_queue_pairs; i++) + rcu_assign_pointer(vi->rq[i].xdp_prog, old_prog); + } + + if (netif_running(dev)) { + for (i = 0; i < vi->max_queue_pairs; i++) { + virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi); + virtnet_napi_tx_enable(vi, vi->sq[i].vq, + &vi->sq[i].napi); + } + } if (prog) bpf_prog_sub(prog, vi->max_queue_pairs - 1); return err; @@ -2613,16 +2700,6 @@ static void free_receive_page_frags(struct virtnet_info *vi) put_page(vi->rq[i].alloc_frag.page); } -static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q) -{ - if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs)) - return false; - else if (q < vi->curr_queue_pairs) - return true; - else - return false; -} - static void free_unused_bufs(struct virtnet_info *vi) { void *buf; @@ -2631,10 +2708,10 @@ static void free_unused_bufs(struct virtnet_info *vi) for (i = 0; i < vi->max_queue_pairs; i++) { struct virtqueue *vq = vi->sq[i].vq; while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) { - if (!is_xdp_raw_buffer_queue(vi, i)) + if (!is_xdp_frame(buf)) dev_kfree_skb(buf); else - put_page(virt_to_head_page(buf)); + xdp_return_frame(ptr_to_xdp(buf)); } } diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index e454dfc9ad8f..89984fcab01e 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -535,8 +535,8 @@ vmxnet3_tq_create(struct vmxnet3_tx_queue *tq, } sz = tq->tx_ring.size * sizeof(tq->buf_info[0]); - tq->buf_info = dma_zalloc_coherent(&adapter->pdev->dev, sz, - &tq->buf_info_pa, GFP_KERNEL); + tq->buf_info = dma_alloc_coherent(&adapter->pdev->dev, sz, + &tq->buf_info_pa, GFP_KERNEL); if (!tq->buf_info) goto err; @@ -1815,8 +1815,8 @@ vmxnet3_rq_create(struct vmxnet3_rx_queue *rq, struct vmxnet3_adapter *adapter) sz = sizeof(struct vmxnet3_rx_buf_info) * (rq->rx_ring[0].size + rq->rx_ring[1].size); - bi = dma_zalloc_coherent(&adapter->pdev->dev, sz, &rq->buf_info_pa, - GFP_KERNEL); + bi = dma_alloc_coherent(&adapter->pdev->dev, sz, &rq->buf_info_pa, + GFP_KERNEL); if (!bi) goto err; diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 95909e262ba4..7c1430ed0244 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -1273,6 +1273,9 @@ static void vrf_setup(struct net_device *dev) /* default to no qdisc; user can add if desired */ dev->priv_flags |= IFF_NO_QUEUE; + + dev->min_mtu = 0; + dev->max_mtu = 0; } static int vrf_validate(struct nlattr *tb[], struct nlattr *data[], diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 5209ee9aac47..2aae11feff0c 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2219,7 +2219,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, struct pcpu_sw_netstats *tx_stats, *rx_stats; union vxlan_addr loopback; union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip; - struct net_device *dev = skb->dev; + struct net_device *dev; int len = skb->len; tx_stats = this_cpu_ptr(src_vxlan->dev->tstats); @@ -2239,9 +2239,15 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, #endif } + rcu_read_lock(); + dev = skb->dev; + if (unlikely(!(dev->flags & IFF_UP))) { + kfree_skb(skb); + goto drop; + } + if (dst_vxlan->cfg.flags & VXLAN_F_LEARN) - vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source, 0, - vni); + vxlan_snoop(dev, &loopback, eth_hdr(skb)->h_source, 0, vni); u64_stats_update_begin(&tx_stats->syncp); tx_stats->tx_packets++; @@ -2254,8 +2260,10 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, rx_stats->rx_bytes += len; u64_stats_update_end(&rx_stats->syncp); } else { +drop: dev->stats.rx_dropped++; } + rcu_read_unlock(); } static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev, diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index c0b0f525c87c..27decf8ae840 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -1575,7 +1575,7 @@ try: dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; } - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); dpriv->tx_skbuff[cur] = NULL; ++dpriv->tx_dirty; } else { diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index 839fa7715709..a08f04c3f644 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -279,10 +279,9 @@ static int uhdlc_init(struct ucc_hdlc_private *priv) iowrite16be(DEFAULT_HDLC_ADDR, &priv->ucc_pram->haddr4); /* Get BD buffer */ - bd_buffer = dma_zalloc_coherent(priv->dev, - (RX_BD_RING_LEN + TX_BD_RING_LEN) * - MAX_RX_BUF_LENGTH, - &bd_dma_addr, GFP_KERNEL); + bd_buffer = dma_alloc_coherent(priv->dev, + (RX_BD_RING_LEN + TX_BD_RING_LEN) * MAX_RX_BUF_LENGTH, + &bd_dma_addr, GFP_KERNEL); if (!bd_buffer) { dev_err(priv->dev, "Could not allocate buffer descriptors\n"); @@ -483,7 +482,7 @@ static int hdlc_tx_done(struct ucc_hdlc_private *priv) memset(priv->tx_buffer + (be32_to_cpu(bd->buf) - priv->dma_tx_addr), 0, skb->len); - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); priv->tx_skbuff[priv->skb_dirtytx] = NULL; priv->skb_dirtytx = @@ -1057,6 +1056,54 @@ static const struct net_device_ops uhdlc_ops = { .ndo_tx_timeout = uhdlc_tx_timeout, }; +static int hdlc_map_iomem(char *name, int init_flag, void __iomem **ptr) +{ + struct device_node *np; + struct platform_device *pdev; + struct resource *res; + static int siram_init_flag; + int ret = 0; + + np = of_find_compatible_node(NULL, NULL, name); + if (!np) + return -EINVAL; + + pdev = of_find_device_by_node(np); + if (!pdev) { + pr_err("%pOFn: failed to lookup pdev\n", np); + of_node_put(np); + return -EINVAL; + } + + of_node_put(np); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -EINVAL; + goto error_put_device; + } + *ptr = ioremap(res->start, resource_size(res)); + if (!*ptr) { + ret = -ENOMEM; + goto error_put_device; + } + + /* We've remapped the addresses, and we don't need the device any + * more, so we should release it. + */ + put_device(&pdev->dev); + + if (init_flag && siram_init_flag == 0) { + memset_io(*ptr, 0, resource_size(res)); + siram_init_flag = 1; + } + return 0; + +error_put_device: + put_device(&pdev->dev); + + return ret; +} + static int ucc_hdlc_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1151,6 +1198,15 @@ static int ucc_hdlc_probe(struct platform_device *pdev) ret = ucc_of_parse_tdm(np, utdm, ut_info); if (ret) goto free_utdm; + + ret = hdlc_map_iomem("fsl,t1040-qe-si", 0, + (void __iomem **)&utdm->si_regs); + if (ret) + goto free_utdm; + ret = hdlc_map_iomem("fsl,t1040-qe-siram", 1, + (void __iomem **)&utdm->siram); + if (ret) + goto unmap_si_regs; } if (of_property_read_u16(np, "fsl,hmask", &uhdlc_priv->hmask)) @@ -1159,7 +1215,7 @@ static int ucc_hdlc_probe(struct platform_device *pdev) ret = uhdlc_init(uhdlc_priv); if (ret) { dev_err(&pdev->dev, "Failed to init uhdlc\n"); - goto free_utdm; + goto undo_uhdlc_init; } dev = alloc_hdlcdev(uhdlc_priv); @@ -1188,6 +1244,9 @@ static int ucc_hdlc_probe(struct platform_device *pdev) free_dev: free_netdev(dev); undo_uhdlc_init: + iounmap(utdm->siram); +unmap_si_regs: + iounmap(utdm->si_regs); free_utdm: if (uhdlc_priv->tsa) kfree(utdm); diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index f6d3ecbdd3a3..2a5668b4f6bc 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1553,10 +1553,9 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id, * coherent DMA are unsupported */ dest_ring->base_addr_owner_space_unaligned = - dma_zalloc_coherent(ar->dev, - (nentries * sizeof(struct ce_desc) + - CE_DESC_RING_ALIGN), - &base_addr, GFP_KERNEL); + dma_alloc_coherent(ar->dev, + (nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN), + &base_addr, GFP_KERNEL); if (!dest_ring->base_addr_owner_space_unaligned) { kfree(dest_ring); return ERR_PTR(-ENOMEM); diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 399b501f3c3c..e8891f5fc83a 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -548,7 +548,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { { .id = WCN3990_HW_1_0_DEV_VERSION, .dev_id = 0, - .bus = ATH10K_BUS_PCI, + .bus = ATH10K_BUS_SNOC, .name = "wcn3990 hw1.0", .continuous_frag_desc = true, .tx_chain_mask = 0x7, diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index e49b36752ba2..49758490eaba 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -5169,10 +5169,10 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, if (vif->type == NL80211_IFTYPE_ADHOC || vif->type == NL80211_IFTYPE_MESH_POINT || vif->type == NL80211_IFTYPE_AP) { - arvif->beacon_buf = dma_zalloc_coherent(ar->dev, - IEEE80211_MAX_FRAME_LEN, - &arvif->beacon_paddr, - GFP_ATOMIC); + arvif->beacon_buf = dma_alloc_coherent(ar->dev, + IEEE80211_MAX_FRAME_LEN, + &arvif->beacon_paddr, + GFP_ATOMIC); if (!arvif->beacon_buf) { ret = -ENOMEM; ath10k_warn(ar, "failed to allocate beacon buffer: %d\n", diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 01b4edb00e9e..39e0b1cc2a12 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -936,8 +936,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, */ alloc_nbytes = min_t(unsigned int, nbytes, DIAG_TRANSFER_LIMIT); - data_buf = (unsigned char *)dma_zalloc_coherent(ar->dev, - alloc_nbytes, + data_buf = (unsigned char *)dma_alloc_coherent(ar->dev, alloc_nbytes, &ce_data_base, GFP_ATOMIC); diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index ba837403e266..8e236d158ca6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -5193,7 +5193,7 @@ static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id, void *vaddr; pool_size = num_units * round_up(unit_len, 4); - vaddr = dma_zalloc_coherent(ar->dev, pool_size, &paddr, GFP_KERNEL); + vaddr = dma_alloc_coherent(ar->dev, pool_size, &paddr, GFP_KERNEL); if (!vaddr) return -ENOMEM; diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index 5ab3e31c9ffa..bab30f7a443c 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -174,9 +174,8 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn int i; size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc); - wcn_ch->cpu_addr = dma_zalloc_coherent(dev, size, - &wcn_ch->dma_addr, - GFP_KERNEL); + wcn_ch->cpu_addr = dma_alloc_coherent(dev, size, &wcn_ch->dma_addr, + GFP_KERNEL); if (!wcn_ch->cpu_addr) return -ENOMEM; @@ -627,9 +626,9 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) 16 - (WCN36XX_BD_CHUNK_SIZE % 8); s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H; - cpu_addr = dma_zalloc_coherent(wcn->dev, s, - &wcn->mgmt_mem_pool.phy_addr, - GFP_KERNEL); + cpu_addr = dma_alloc_coherent(wcn->dev, s, + &wcn->mgmt_mem_pool.phy_addr, + GFP_KERNEL); if (!cpu_addr) goto out_err; @@ -642,9 +641,9 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) 16 - (WCN36XX_BD_CHUNK_SIZE % 8); s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L; - cpu_addr = dma_zalloc_coherent(wcn->dev, s, - &wcn->data_mem_pool.phy_addr, - GFP_KERNEL); + cpu_addr = dma_alloc_coherent(wcn->dev, s, + &wcn->data_mem_pool.phy_addr, + GFP_KERNEL); if (!cpu_addr) goto out_err; diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index 05a8348bd7b9..3380aaef456c 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c @@ -99,7 +99,7 @@ static int wil_sring_alloc(struct wil6210_priv *wil, /* Status messages are allocated and initialized to 0. This is necessary * since DR bit should be initialized to 0. */ - sring->va = dma_zalloc_coherent(dev, sz, &sring->pa, GFP_KERNEL); + sring->va = dma_alloc_coherent(dev, sz, &sring->pa, GFP_KERNEL); if (!sring->va) return -ENOMEM; @@ -381,15 +381,15 @@ static int wil_ring_alloc_desc_ring(struct wil6210_priv *wil, if (!ring->ctx) goto err; - ring->va = dma_zalloc_coherent(dev, sz, &ring->pa, GFP_KERNEL); + ring->va = dma_alloc_coherent(dev, sz, &ring->pa, GFP_KERNEL); if (!ring->va) goto err_free_ctx; if (ring->is_rx) { sz = sizeof(*ring->edma_rx_swtail.va); ring->edma_rx_swtail.va = - dma_zalloc_coherent(dev, sz, &ring->edma_rx_swtail.pa, - GFP_KERNEL); + dma_alloc_coherent(dev, sz, &ring->edma_rx_swtail.pa, + GFP_KERNEL); if (!ring->edma_rx_swtail.va) goto err_free_va; } diff --git a/drivers/net/wireless/broadcom/b43/dma.c b/drivers/net/wireless/broadcom/b43/dma.c index dfc4c34298d4..b34e51933257 100644 --- a/drivers/net/wireless/broadcom/b43/dma.c +++ b/drivers/net/wireless/broadcom/b43/dma.c @@ -431,9 +431,9 @@ static int alloc_ringmemory(struct b43_dmaring *ring) u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ? B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE; - ring->descbase = dma_zalloc_coherent(ring->dev->dev->dma_dev, - ring_mem_size, &(ring->dmabase), - GFP_KERNEL); + ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, + ring_mem_size, &(ring->dmabase), + GFP_KERNEL); if (!ring->descbase) return -ENOMEM; diff --git a/drivers/net/wireless/broadcom/b43legacy/dma.c b/drivers/net/wireless/broadcom/b43legacy/dma.c index 1b1da7d83652..2ce1537d983c 100644 --- a/drivers/net/wireless/broadcom/b43legacy/dma.c +++ b/drivers/net/wireless/broadcom/b43legacy/dma.c @@ -331,9 +331,9 @@ void free_descriptor_buffer(struct b43legacy_dmaring *ring, static int alloc_ringmemory(struct b43legacy_dmaring *ring) { /* GFP flags must match the flags in free_ringmemory()! */ - ring->descbase = dma_zalloc_coherent(ring->dev->dev->dma_dev, - B43legacy_DMA_RINGMEMSIZE, - &(ring->dmabase), GFP_KERNEL); + ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, + B43legacy_DMA_RINGMEMSIZE, + &(ring->dmabase), GFP_KERNEL); if (!ring->descbase) return -ENOMEM; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 16d7dda965d8..0f69b3fa296e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -1281,10 +1281,10 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo) u32 addr; devinfo->shared.scratch = - dma_zalloc_coherent(&devinfo->pdev->dev, - BRCMF_DMA_D2H_SCRATCH_BUF_LEN, - &devinfo->shared.scratch_dmahandle, - GFP_KERNEL); + dma_alloc_coherent(&devinfo->pdev->dev, + BRCMF_DMA_D2H_SCRATCH_BUF_LEN, + &devinfo->shared.scratch_dmahandle, + GFP_KERNEL); if (!devinfo->shared.scratch) goto fail; @@ -1298,10 +1298,10 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo) brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_SCRATCH_BUF_LEN); devinfo->shared.ringupd = - dma_zalloc_coherent(&devinfo->pdev->dev, - BRCMF_DMA_D2H_RINGUPD_BUF_LEN, - &devinfo->shared.ringupd_dmahandle, - GFP_KERNEL); + dma_alloc_coherent(&devinfo->pdev->dev, + BRCMF_DMA_D2H_RINGUPD_BUF_LEN, + &devinfo->shared.ringupd_dmahandle, + GFP_KERNEL); if (!devinfo->shared.ringupd) goto fail; diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig index 491ca3c8b43c..83d5bceea08f 100644 --- a/drivers/net/wireless/intel/iwlwifi/Kconfig +++ b/drivers/net/wireless/intel/iwlwifi/Kconfig @@ -1,6 +1,6 @@ config IWLWIFI tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) " - depends on PCI && HAS_IOMEM + depends on PCI && HAS_IOMEM && CFG80211 select FW_LOADER ---help--- Select to build the driver supporting the: @@ -47,6 +47,7 @@ if IWLWIFI config IWLWIFI_LEDS bool depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI + depends on IWLMVM || IWLDVM select LEDS_TRIGGERS select MAC80211_LEDS default y diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index e965cc588850..9e850c25877b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -711,30 +711,24 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans, * Allocate the circular buffer of Read Buffer Descriptors * (RBDs) */ - rxq->bd = dma_zalloc_coherent(dev, - free_size * rxq->queue_size, - &rxq->bd_dma, GFP_KERNEL); + rxq->bd = dma_alloc_coherent(dev, free_size * rxq->queue_size, + &rxq->bd_dma, GFP_KERNEL); if (!rxq->bd) goto err; if (trans->cfg->mq_rx_supported) { - rxq->used_bd = dma_zalloc_coherent(dev, - (use_rx_td ? - sizeof(*rxq->cd) : - sizeof(__le32)) * - rxq->queue_size, - &rxq->used_bd_dma, - GFP_KERNEL); + rxq->used_bd = dma_alloc_coherent(dev, + (use_rx_td ? sizeof(*rxq->cd) : sizeof(__le32)) * rxq->queue_size, + &rxq->used_bd_dma, + GFP_KERNEL); if (!rxq->used_bd) goto err; } /* Allocate the driver's pointer to receive buffer status */ - rxq->rb_stts = dma_zalloc_coherent(dev, use_rx_td ? - sizeof(__le16) : - sizeof(struct iwl_rb_status), - &rxq->rb_stts_dma, - GFP_KERNEL); + rxq->rb_stts = dma_alloc_coherent(dev, + use_rx_td ? sizeof(__le16) : sizeof(struct iwl_rb_status), + &rxq->rb_stts_dma, GFP_KERNEL); if (!rxq->rb_stts) goto err; @@ -742,16 +736,14 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans, return 0; /* Allocate the driver's pointer to TR tail */ - rxq->tr_tail = dma_zalloc_coherent(dev, sizeof(__le16), - &rxq->tr_tail_dma, - GFP_KERNEL); + rxq->tr_tail = dma_alloc_coherent(dev, sizeof(__le16), + &rxq->tr_tail_dma, GFP_KERNEL); if (!rxq->tr_tail) goto err; /* Allocate the driver's pointer to CR tail */ - rxq->cr_tail = dma_zalloc_coherent(dev, sizeof(__le16), - &rxq->cr_tail_dma, - GFP_KERNEL); + rxq->cr_tail = dma_alloc_coherent(dev, sizeof(__le16), + &rxq->cr_tail_dma, GFP_KERNEL); if (!rxq->cr_tail) goto err; /* @@ -1947,9 +1939,8 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); trans_pcie->ict_tbl = - dma_zalloc_coherent(trans->dev, ICT_SIZE, - &trans_pcie->ict_tbl_dma, - GFP_KERNEL); + dma_alloc_coherent(trans->dev, ICT_SIZE, + &trans_pcie->ict_tbl_dma, GFP_KERNEL); if (!trans_pcie->ict_tbl) return -ENOMEM; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 3a4b8786f7ea..6359053bd0c7 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2761,6 +2761,11 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, BIT(NL80211_CHAN_WIDTH_160); } + if (!n_limits) { + err = -EINVAL; + goto failed_hw; + } + data->if_combination.n_limits = n_limits; data->if_combination.max_interfaces = 2048; data->if_combination.limits = data->if_limits; @@ -3549,7 +3554,7 @@ static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info) goto out_err; } - genlmsg_reply(skb, info); + res = genlmsg_reply(skb, info); break; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c index 497e762978cc..b2cabce1d74d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c @@ -212,24 +212,24 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev) mt76x02_add_rate_power_offset(t, delta); } -void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info) +void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp) { struct mt76x0_chan_map { u8 chan; u8 offset; } chan_map[] = { - { 2, 0 }, { 4, 1 }, { 6, 2 }, { 8, 3 }, - { 10, 4 }, { 12, 5 }, { 14, 6 }, { 38, 0 }, - { 44, 1 }, { 48, 2 }, { 54, 3 }, { 60, 4 }, - { 64, 5 }, { 102, 6 }, { 108, 7 }, { 112, 8 }, - { 118, 9 }, { 124, 10 }, { 128, 11 }, { 134, 12 }, - { 140, 13 }, { 151, 14 }, { 157, 15 }, { 161, 16 }, - { 167, 17 }, { 171, 18 }, { 173, 19 }, + { 2, 0 }, { 4, 2 }, { 6, 4 }, { 8, 6 }, + { 10, 8 }, { 12, 10 }, { 14, 12 }, { 38, 0 }, + { 44, 2 }, { 48, 4 }, { 54, 6 }, { 60, 8 }, + { 64, 10 }, { 102, 12 }, { 108, 14 }, { 112, 16 }, + { 118, 18 }, { 124, 20 }, { 128, 22 }, { 134, 24 }, + { 140, 26 }, { 151, 28 }, { 157, 30 }, { 161, 32 }, + { 167, 34 }, { 171, 36 }, { 175, 38 }, }; struct ieee80211_channel *chan = dev->mt76.chandef.chan; u8 offset, addr; + int i, idx = 0; u16 data; - int i; if (mt76x0_tssi_enabled(dev)) { s8 target_power; @@ -239,14 +239,14 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info) else data = mt76x02_eeprom_get(dev, MT_EE_2G_TARGET_POWER); target_power = (data & 0xff) - dev->mt76.rate_power.ofdm[7]; - info[0] = target_power + mt76x0_get_delta(dev); - info[1] = 0; + *tp = target_power + mt76x0_get_delta(dev); return; } for (i = 0; i < ARRAY_SIZE(chan_map); i++) { - if (chan_map[i].chan <= chan->hw_value) { + if (chan->hw_value <= chan_map[i].chan) { + idx = (chan->hw_value == chan_map[i].chan); offset = chan_map[i].offset; break; } @@ -258,13 +258,16 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info) addr = MT_EE_TX_POWER_DELTA_BW80 + offset; } else { switch (chan->hw_value) { + case 42: + offset = 2; + break; case 58: offset = 8; break; case 106: offset = 14; break; - case 112: + case 122: offset = 20; break; case 155: @@ -277,14 +280,9 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info) } data = mt76x02_eeprom_get(dev, addr); - - info[0] = data; - if (!info[0] || info[0] > 0x3f) - info[0] = 5; - - info[1] = data >> 8; - if (!info[1] || info[1] > 0x3f) - info[1] = 5; + *tp = data >> (8 * idx); + if (*tp < 0 || *tp > 0x3f) + *tp = 5; } static int mt76x0_check_eeprom(struct mt76x02_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h index ee9ade9f3c8b..42b259f90b6d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h @@ -26,7 +26,7 @@ struct mt76x02_dev; int mt76x0_eeprom_init(struct mt76x02_dev *dev); void mt76x0_read_rx_gain(struct mt76x02_dev *dev); void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev); -void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info); +void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp); static inline s8 s6_to_s8(u32 val) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 1eb1a802ed20..b6166703ad76 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -845,17 +845,17 @@ static void mt76x0_phy_tssi_calibrate(struct mt76x02_dev *dev) void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) { struct mt76_rate_power *t = &dev->mt76.rate_power; - u8 info[2]; + s8 info; mt76x0_get_tx_power_per_rate(dev); - mt76x0_get_power_info(dev, info); + mt76x0_get_power_info(dev, &info); - mt76x02_add_rate_power_offset(t, info[0]); + mt76x02_add_rate_power_offset(t, info); mt76x02_limit_rate_power(t, dev->mt76.txpower_conf); dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t); - mt76x02_add_rate_power_offset(t, -info[0]); + mt76x02_add_rate_power_offset(t, -info); - mt76x02_phy_set_txpower(dev, info[0], info[1]); + mt76x02_phy_set_txpower(dev, info, info); } void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 0e6b43bb4678..a5ea3ba495a4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -158,39 +158,49 @@ static const struct ieee80211_ops mt76x0u_ops = { .get_txpower = mt76x02_get_txpower, }; -static int mt76x0u_register_device(struct mt76x02_dev *dev) +static int mt76x0u_init_hardware(struct mt76x02_dev *dev) { - struct ieee80211_hw *hw = dev->mt76.hw; int err; - err = mt76u_alloc_queues(&dev->mt76); - if (err < 0) - goto out_err; - - err = mt76u_mcu_init_rx(&dev->mt76); - if (err < 0) - goto out_err; - mt76x0_chip_onoff(dev, true, true); - if (!mt76x02_wait_for_mac(&dev->mt76)) { - err = -ETIMEDOUT; - goto out_err; - } + + if (!mt76x02_wait_for_mac(&dev->mt76)) + return -ETIMEDOUT; err = mt76x0u_mcu_init(dev); if (err < 0) - goto out_err; + return err; mt76x0_init_usb_dma(dev); err = mt76x0_init_hardware(dev); if (err < 0) - goto out_err; + return err; mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e); mt76_wr(dev, MT_TXOP_CTRL_CFG, FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) | FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58)); + return 0; +} + +static int mt76x0u_register_device(struct mt76x02_dev *dev) +{ + struct ieee80211_hw *hw = dev->mt76.hw; + int err; + + err = mt76u_alloc_queues(&dev->mt76); + if (err < 0) + goto out_err; + + err = mt76u_mcu_init_rx(&dev->mt76); + if (err < 0) + goto out_err; + + err = mt76x0u_init_hardware(dev); + if (err < 0) + goto out_err; + err = mt76x0_register_device(dev); if (err < 0) goto out_err; @@ -301,6 +311,8 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf, mt76u_stop_queues(&dev->mt76); mt76x0u_mac_stop(dev); + clear_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); + mt76x0_chip_onoff(dev, false, false); usb_kill_urb(usb->mcu.res.urb); return 0; @@ -328,7 +340,7 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf) tasklet_enable(&usb->rx_tasklet); tasklet_enable(&usb->tx_tasklet); - ret = mt76x0_init_hardware(dev); + ret = mt76x0u_init_hardware(dev); if (ret) goto err; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c index 528cb0401df1..4956a54151cb 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c @@ -119,9 +119,9 @@ static int rt2x00mmio_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, /* * Allocate DMA memory for descriptor and buffer. */ - addr = dma_zalloc_coherent(rt2x00dev->dev, - queue->limit * queue->desc_size, &dma, - GFP_KERNEL); + addr = dma_alloc_coherent(rt2x00dev->dev, + queue->limit * queue->desc_size, &dma, + GFP_KERNEL); if (!addr) return -ENOMEM; diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index bd10165d7eec..4d4b07701149 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -164,6 +164,12 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) } sdio_claim_host(func); + /* + * To guarantee that the SDIO card is power cycled, as required to make + * the FW programming to succeed, let's do a brute force HW reset. + */ + mmc_hw_reset(card->host); + sdio_enable_func(func); sdio_release_host(func); @@ -174,20 +180,13 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue) { struct sdio_func *func = dev_to_sdio_func(glue->dev); struct mmc_card *card = func->card; - int error; sdio_claim_host(func); sdio_disable_func(func); sdio_release_host(func); /* Let runtime PM know the card is powered off */ - error = pm_runtime_put(&card->dev); - if (error < 0 && error != -EBUSY) { - dev_err(&card->dev, "%s failed: %i\n", __func__, error); - - return error; - } - + pm_runtime_put(&card->dev); return 0; } diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c index 64b218699656..3a93e4d9828b 100644 --- a/drivers/net/wireless/virt_wifi.c +++ b/drivers/net/wireless/virt_wifi.c @@ -530,8 +530,10 @@ static int virt_wifi_newlink(struct net *src_net, struct net_device *dev, SET_NETDEV_DEV(dev, &priv->lowerdev->dev); dev->ieee80211_ptr = kzalloc(sizeof(*dev->ieee80211_ptr), GFP_KERNEL); - if (!dev->ieee80211_ptr) + if (!dev->ieee80211_ptr) { + err = -ENOMEM; goto remove_handler; + } dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; dev->ieee80211_ptr->wiphy = common_wiphy; diff --git a/drivers/net/xen-netback/hash.c b/drivers/net/xen-netback/hash.c index 0ccb021f1e78..10d580c3dea3 100644 --- a/drivers/net/xen-netback/hash.c +++ b/drivers/net/xen-netback/hash.c @@ -454,6 +454,8 @@ void xenvif_init_hash(struct xenvif *vif) if (xenvif_hash_cache_size == 0) return; + BUG_ON(vif->hash.cache.count); + spin_lock_init(&vif->hash.cache.lock); INIT_LIST_HEAD(&vif->hash.cache.list); } diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 182d6770f102..6da12518e693 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -153,6 +153,13 @@ static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb, { struct xenvif *vif = netdev_priv(dev); unsigned int size = vif->hash.size; + unsigned int num_queues; + + /* If queues are not set up internally - always return 0 + * as the packet going to be dropped anyway */ + num_queues = READ_ONCE(vif->num_queues); + if (num_queues < 1) + return 0; if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE) return fallback(dev, skb, NULL) % dev->real_num_tx_queues; diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 80aae3a32c2a..f09948b009dd 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1072,11 +1072,6 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s skb_frag_size_set(&frags[i], len); } - /* Copied all the bits from the frag list -- free it. */ - skb_frag_list_init(skb); - xenvif_skb_zerocopy_prepare(queue, nskb); - kfree_skb(nskb); - /* Release all the original (foreign) frags. */ for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) skb_frag_unref(skb, f); @@ -1145,6 +1140,8 @@ static int xenvif_tx_submit(struct xenvif_queue *queue) xenvif_fill_frags(queue, skb); if (unlikely(skb_has_frag_list(skb))) { + struct sk_buff *nskb = skb_shinfo(skb)->frag_list; + xenvif_skb_zerocopy_prepare(queue, nskb); if (xenvif_handle_frag_list(queue, skb)) { if (net_ratelimit()) netdev_err(queue->vif->dev, @@ -1153,6 +1150,9 @@ static int xenvif_tx_submit(struct xenvif_queue *queue) kfree_skb(skb); continue; } + /* Copied all the bits from the frag list -- free it. */ + skb_frag_list_init(skb); + kfree_skb(nskb); } skb->dev = queue->vif->dev; diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c index 5ee5f40b4dfc..f1eaa3c4d46a 100644 --- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c +++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c @@ -1339,10 +1339,10 @@ static int switchtec_ntb_init_shared_mw(struct switchtec_ntb *sndev) int rc; sndev->nr_rsvd_luts++; - sndev->self_shared = dma_zalloc_coherent(&sndev->stdev->pdev->dev, - LUT_SIZE, - &sndev->self_shared_dma, - GFP_KERNEL); + sndev->self_shared = dma_alloc_coherent(&sndev->stdev->pdev->dev, + LUT_SIZE, + &sndev->self_shared_dma, + GFP_KERNEL); if (!sndev->self_shared) { dev_err(&sndev->stdev->dev, "unable to allocate memory for shared mw\n"); diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c index 0cf58cabc9ed..3cf50274fadb 100644 --- a/drivers/nvdimm/dimm.c +++ b/drivers/nvdimm/dimm.c @@ -26,6 +26,12 @@ static int nvdimm_probe(struct device *dev) struct nvdimm_drvdata *ndd; int rc; + rc = nvdimm_security_setup_events(dev); + if (rc < 0) { + dev_err(dev, "security event setup failed: %d\n", rc); + return rc; + } + rc = nvdimm_check_config_data(dev); if (rc) { /* not required for non-aliased nvdimm, ex. NVDIMM-N */ diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index 4890310df874..efe412a6b5b9 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c @@ -578,13 +578,25 @@ struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus, } EXPORT_SYMBOL_GPL(__nvdimm_create); -int nvdimm_security_setup_events(struct nvdimm *nvdimm) +static void shutdown_security_notify(void *data) { - nvdimm->sec.overwrite_state = sysfs_get_dirent(nvdimm->dev.kobj.sd, - "security"); + struct nvdimm *nvdimm = data; + + sysfs_put(nvdimm->sec.overwrite_state); +} + +int nvdimm_security_setup_events(struct device *dev) +{ + struct nvdimm *nvdimm = to_nvdimm(dev); + + if (nvdimm->sec.state < 0 || !nvdimm->sec.ops + || !nvdimm->sec.ops->overwrite) + return 0; + nvdimm->sec.overwrite_state = sysfs_get_dirent(dev->kobj.sd, "security"); if (!nvdimm->sec.overwrite_state) - return -ENODEV; - return 0; + return -ENOMEM; + + return devm_add_action_or_reset(dev, shutdown_security_notify, nvdimm); } EXPORT_SYMBOL_GPL(nvdimm_security_setup_events); diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h index 2b2cf4e554d3..e5ffd5733540 100644 --- a/drivers/nvdimm/nd-core.h +++ b/drivers/nvdimm/nd-core.h @@ -54,12 +54,12 @@ struct nvdimm { }; static inline enum nvdimm_security_state nvdimm_security_state( - struct nvdimm *nvdimm, bool master) + struct nvdimm *nvdimm, enum nvdimm_passphrase_type ptype) { if (!nvdimm->sec.ops) return -ENXIO; - return nvdimm->sec.ops->state(nvdimm, master); + return nvdimm->sec.ops->state(nvdimm, ptype); } int nvdimm_security_freeze(struct nvdimm *nvdimm); #if IS_ENABLED(CONFIG_NVDIMM_KEYS) diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index cfde992684e7..379bf4305e61 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -250,6 +250,7 @@ long nvdimm_clear_poison(struct device *dev, phys_addr_t phys, void nvdimm_set_aliasing(struct device *dev); void nvdimm_set_locked(struct device *dev); void nvdimm_clear_locked(struct device *dev); +int nvdimm_security_setup_events(struct device *dev); #if IS_ENABLED(CONFIG_NVDIMM_KEYS) int nvdimm_security_unlock(struct device *dev); #else diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 08f2c92602f4..6a9dd68c0f4f 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1253,6 +1253,7 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, * effects say only one namespace is affected. */ if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) { + mutex_lock(&ctrl->scan_lock); nvme_start_freeze(ctrl); nvme_wait_freeze(ctrl); } @@ -1281,8 +1282,10 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects) */ if (effects & NVME_CMD_EFFECTS_LBCC) nvme_update_formats(ctrl); - if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) + if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) { nvme_unfreeze(ctrl); + mutex_unlock(&ctrl->scan_lock); + } if (effects & NVME_CMD_EFFECTS_CCC) nvme_init_identify(ctrl); if (effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC)) @@ -2173,18 +2176,20 @@ static void nvme_init_subnqn(struct nvme_subsystem *subsys, struct nvme_ctrl *ct size_t nqnlen; int off; - nqnlen = strnlen(id->subnqn, NVMF_NQN_SIZE); - if (nqnlen > 0 && nqnlen < NVMF_NQN_SIZE) { - strlcpy(subsys->subnqn, id->subnqn, NVMF_NQN_SIZE); - return; - } + if(!(ctrl->quirks & NVME_QUIRK_IGNORE_DEV_SUBNQN)) { + nqnlen = strnlen(id->subnqn, NVMF_NQN_SIZE); + if (nqnlen > 0 && nqnlen < NVMF_NQN_SIZE) { + strlcpy(subsys->subnqn, id->subnqn, NVMF_NQN_SIZE); + return; + } - if (ctrl->vs >= NVME_VS(1, 2, 1)) - dev_warn(ctrl->device, "missing or invalid SUBNQN field.\n"); + if (ctrl->vs >= NVME_VS(1, 2, 1)) + dev_warn(ctrl->device, "missing or invalid SUBNQN field.\n"); + } /* Generate a "fake" NQN per Figure 254 in NVMe 1.3 + ECN 001 */ off = snprintf(subsys->subnqn, NVMF_NQN_SIZE, - "nqn.2014.08.org.nvmexpress:%4x%4x", + "nqn.2014.08.org.nvmexpress:%04x%04x", le16_to_cpu(id->vid), le16_to_cpu(id->ssvid)); memcpy(subsys->subnqn + off, id->sn, sizeof(id->sn)); off += sizeof(id->sn); @@ -2500,7 +2505,6 @@ int nvme_init_identify(struct nvme_ctrl *ctrl) ctrl->oaes = le32_to_cpu(id->oaes); atomic_set(&ctrl->abort_limit, id->acl + 1); ctrl->vwc = id->vwc; - ctrl->cntlid = le16_to_cpup(&id->cntlid); if (id->mdts) max_hw_sectors = 1 << (id->mdts + page_shift - 9); else @@ -3400,6 +3404,7 @@ static void nvme_scan_work(struct work_struct *work) if (nvme_identify_ctrl(ctrl, &id)) return; + mutex_lock(&ctrl->scan_lock); nn = le32_to_cpu(id->nn); if (ctrl->vs >= NVME_VS(1, 1, 0) && !(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)) { @@ -3408,6 +3413,7 @@ static void nvme_scan_work(struct work_struct *work) } nvme_scan_ns_sequential(ctrl, nn); out_free_id: + mutex_unlock(&ctrl->scan_lock); kfree(id); down_write(&ctrl->namespaces_rwsem); list_sort(NULL, &ctrl->namespaces, ns_cmp); @@ -3651,6 +3657,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, ctrl->state = NVME_CTRL_NEW; spin_lock_init(&ctrl->lock); + mutex_init(&ctrl->scan_lock); INIT_LIST_HEAD(&ctrl->namespaces); init_rwsem(&ctrl->namespaces_rwsem); ctrl->dev = dev; diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c index b2ab213f43de..3eb908c50e1a 100644 --- a/drivers/nvme/host/fabrics.c +++ b/drivers/nvme/host/fabrics.c @@ -874,6 +874,8 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, if (opts->discovery_nqn) { opts->kato = 0; opts->nr_io_queues = 0; + opts->nr_write_queues = 0; + opts->nr_poll_queues = 0; opts->duplicate_connect = true; } if (ctrl_loss_tmo < 0) diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 183ec17ba067..b9fff3b8ed1b 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -545,8 +545,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) timer_setup(&ctrl->anatt_timer, nvme_anatt_timeout, 0); ctrl->ana_log_size = sizeof(struct nvme_ana_rsp_hdr) + ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc); - if (!(ctrl->anacap & (1 << 6))) - ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32); + ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32); if (ctrl->ana_log_size > ctrl->max_hw_sectors << SECTOR_SHIFT) { dev_err(ctrl->device, @@ -570,6 +569,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) return 0; out_free_ana_log_buf: kfree(ctrl->ana_log_buf); + ctrl->ana_log_buf = NULL; out: return error; } @@ -577,5 +577,6 @@ out: void nvme_mpath_uninit(struct nvme_ctrl *ctrl) { kfree(ctrl->ana_log_buf); + ctrl->ana_log_buf = NULL; } diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 2b36ac922596..c4a1bb41abf0 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -90,6 +90,11 @@ enum nvme_quirks { * Set MEDIUM priority on SQ creation */ NVME_QUIRK_MEDIUM_PRIO_SQ = (1 << 7), + + /* + * Ignore device provided subnqn. + */ + NVME_QUIRK_IGNORE_DEV_SUBNQN = (1 << 8), }; /* @@ -149,6 +154,7 @@ struct nvme_ctrl { enum nvme_ctrl_state state; bool identified; spinlock_t lock; + struct mutex scan_lock; const struct nvme_ctrl_ops *ops; struct request_queue *admin_q; struct request_queue *connect_q; diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 5a0bf6a24d50..7fee665ec45e 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -95,6 +95,7 @@ struct nvme_dev; struct nvme_queue; static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown); +static bool __nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode); /* * Represents an NVM Express device. Each nvme_dev is a PCI function. @@ -1019,9 +1020,11 @@ static void nvme_complete_cqes(struct nvme_queue *nvmeq, u16 start, u16 end) static inline void nvme_update_cq_head(struct nvme_queue *nvmeq) { - if (++nvmeq->cq_head == nvmeq->q_depth) { + if (nvmeq->cq_head == nvmeq->q_depth - 1) { nvmeq->cq_head = 0; nvmeq->cq_phase = !nvmeq->cq_phase; + } else { + nvmeq->cq_head++; } } @@ -1420,6 +1423,14 @@ static int nvme_suspend_queue(struct nvme_queue *nvmeq) return 0; } +static void nvme_suspend_io_queues(struct nvme_dev *dev) +{ + int i; + + for (i = dev->ctrl.queue_count - 1; i > 0; i--) + nvme_suspend_queue(&dev->queues[i]); +} + static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown) { struct nvme_queue *nvmeq = &dev->queues[0]; @@ -1485,8 +1496,8 @@ static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth) if (dev->ctrl.queue_count > qid) return 0; - nvmeq->cqes = dma_zalloc_coherent(dev->dev, CQ_SIZE(depth), - &nvmeq->cq_dma_addr, GFP_KERNEL); + nvmeq->cqes = dma_alloc_coherent(dev->dev, CQ_SIZE(depth), + &nvmeq->cq_dma_addr, GFP_KERNEL); if (!nvmeq->cqes) goto free_nvmeq; @@ -1885,8 +1896,9 @@ static void nvme_free_host_mem(struct nvme_dev *dev) struct nvme_host_mem_buf_desc *desc = &dev->host_mem_descs[i]; size_t size = le32_to_cpu(desc->size) * dev->ctrl.page_size; - dma_free_coherent(dev->dev, size, dev->host_mem_desc_bufs[i], - le64_to_cpu(desc->addr)); + dma_free_attrs(dev->dev, size, dev->host_mem_desc_bufs[i], + le64_to_cpu(desc->addr), + DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN); } kfree(dev->host_mem_desc_bufs); @@ -1915,8 +1927,8 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred, if (dev->ctrl.hmmaxd && dev->ctrl.hmmaxd < max_entries) max_entries = dev->ctrl.hmmaxd; - descs = dma_zalloc_coherent(dev->dev, max_entries * sizeof(*descs), - &descs_dma, GFP_KERNEL); + descs = dma_alloc_coherent(dev->dev, max_entries * sizeof(*descs), + &descs_dma, GFP_KERNEL); if (!descs) goto out; @@ -1952,8 +1964,9 @@ out_free_bufs: while (--i >= 0) { size_t size = le32_to_cpu(descs[i].size) * dev->ctrl.page_size; - dma_free_coherent(dev->dev, size, bufs[i], - le64_to_cpu(descs[i].addr)); + dma_free_attrs(dev->dev, size, bufs[i], + le64_to_cpu(descs[i].addr), + DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN); } kfree(bufs); @@ -2028,14 +2041,18 @@ static int nvme_setup_host_mem(struct nvme_dev *dev) return ret; } +/* irq_queues covers admin queue */ static void nvme_calc_io_queues(struct nvme_dev *dev, unsigned int irq_queues) { unsigned int this_w_queues = write_queues; + WARN_ON(!irq_queues); + /* - * Setup read/write queue split + * Setup read/write queue split, assign admin queue one independent + * irq vector if irq_queues is > 1. */ - if (irq_queues == 1) { + if (irq_queues <= 2) { dev->io_queues[HCTX_TYPE_DEFAULT] = 1; dev->io_queues[HCTX_TYPE_READ] = 0; return; @@ -2043,21 +2060,21 @@ static void nvme_calc_io_queues(struct nvme_dev *dev, unsigned int irq_queues) /* * If 'write_queues' is set, ensure it leaves room for at least - * one read queue + * one read queue and one admin queue */ if (this_w_queues >= irq_queues) - this_w_queues = irq_queues - 1; + this_w_queues = irq_queues - 2; /* * If 'write_queues' is set to zero, reads and writes will share * a queue set. */ if (!this_w_queues) { - dev->io_queues[HCTX_TYPE_DEFAULT] = irq_queues; + dev->io_queues[HCTX_TYPE_DEFAULT] = irq_queues - 1; dev->io_queues[HCTX_TYPE_READ] = 0; } else { dev->io_queues[HCTX_TYPE_DEFAULT] = this_w_queues; - dev->io_queues[HCTX_TYPE_READ] = irq_queues - this_w_queues; + dev->io_queues[HCTX_TYPE_READ] = irq_queues - this_w_queues - 1; } } @@ -2082,7 +2099,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues) this_p_queues = nr_io_queues - 1; irq_queues = 1; } else { - irq_queues = nr_io_queues - this_p_queues; + irq_queues = nr_io_queues - this_p_queues + 1; } dev->io_queues[HCTX_TYPE_POLL] = this_p_queues; @@ -2102,8 +2119,9 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues) * If we got a failure and we're down to asking for just * 1 + 1 queues, just ask for a single vector. We'll share * that between the single IO queue and the admin queue. + * Otherwise, we assign one independent vector to admin queue. */ - if (result >= 0 && irq_queues > 1) + if (irq_queues > 1) irq_queues = irq_sets[0] + irq_sets[1] + 1; result = pci_alloc_irq_vectors_affinity(pdev, irq_queues, @@ -2132,6 +2150,12 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues) return result; } +static void nvme_disable_io_queues(struct nvme_dev *dev) +{ + if (__nvme_disable_io_queues(dev, nvme_admin_delete_sq)) + __nvme_disable_io_queues(dev, nvme_admin_delete_cq); +} + static int nvme_setup_io_queues(struct nvme_dev *dev) { struct nvme_queue *adminq = &dev->queues[0]; @@ -2168,6 +2192,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) } while (1); adminq->q_db = dev->dbs; + retry: /* Deregister the admin queue's interrupt */ pci_free_irq(pdev, 0, adminq); @@ -2185,25 +2210,34 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) result = max(result - 1, 1); dev->max_qid = result + dev->io_queues[HCTX_TYPE_POLL]; - dev_info(dev->ctrl.device, "%d/%d/%d default/read/poll queues\n", - dev->io_queues[HCTX_TYPE_DEFAULT], - dev->io_queues[HCTX_TYPE_READ], - dev->io_queues[HCTX_TYPE_POLL]); - /* * Should investigate if there's a performance win from allocating * more queues than interrupt vectors; it might allow the submission * path to scale better, even if the receive path is limited by the * number of interrupts. */ - result = queue_request_irq(adminq); if (result) { adminq->cq_vector = -1; return result; } set_bit(NVMEQ_ENABLED, &adminq->flags); - return nvme_create_io_queues(dev); + + result = nvme_create_io_queues(dev); + if (result || dev->online_queues < 2) + return result; + + if (dev->online_queues - 1 < dev->max_qid) { + nr_io_queues = dev->online_queues - 1; + nvme_disable_io_queues(dev); + nvme_suspend_io_queues(dev); + goto retry; + } + dev_info(dev->ctrl.device, "%d/%d/%d default/read/poll queues\n", + dev->io_queues[HCTX_TYPE_DEFAULT], + dev->io_queues[HCTX_TYPE_READ], + dev->io_queues[HCTX_TYPE_POLL]); + return 0; } static void nvme_del_queue_end(struct request *req, blk_status_t error) @@ -2248,7 +2282,7 @@ static int nvme_delete_queue(struct nvme_queue *nvmeq, u8 opcode) return 0; } -static bool nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode) +static bool __nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode) { int nr_queues = dev->online_queues - 1, sent = 0; unsigned long timeout; @@ -2294,7 +2328,6 @@ static int nvme_dev_add(struct nvme_dev *dev) dev->tagset.nr_maps = 2; /* default + read */ if (dev->io_queues[HCTX_TYPE_POLL]) dev->tagset.nr_maps++; - dev->tagset.nr_maps = HCTX_MAX_TYPES; dev->tagset.timeout = NVME_IO_TIMEOUT; dev->tagset.numa_node = dev_to_node(dev->dev); dev->tagset.queue_depth = @@ -2410,7 +2443,6 @@ static void nvme_pci_disable(struct nvme_dev *dev) static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) { - int i; bool dead = true; struct pci_dev *pdev = to_pci_dev(dev->dev); @@ -2437,13 +2469,11 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) nvme_stop_queues(&dev->ctrl); if (!dead && dev->ctrl.queue_count > 0) { - if (nvme_disable_io_queues(dev, nvme_admin_delete_sq)) - nvme_disable_io_queues(dev, nvme_admin_delete_cq); + nvme_disable_io_queues(dev); nvme_disable_admin_queue(dev, shutdown); } - for (i = dev->ctrl.queue_count - 1; i >= 0; i--) - nvme_suspend_queue(&dev->queues[i]); - + nvme_suspend_io_queues(dev); + nvme_suspend_queue(&dev->queues[0]); nvme_pci_disable(dev); blk_mq_tagset_busy_iter(&dev->tagset, nvme_cancel_request, &dev->ctrl); @@ -2527,27 +2557,18 @@ static void nvme_reset_work(struct work_struct *work) if (dev->ctrl.ctrl_config & NVME_CC_ENABLE) nvme_dev_disable(dev, false); - /* - * Introduce CONNECTING state from nvme-fc/rdma transports to mark the - * initializing procedure here. - */ - if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_CONNECTING)) { - dev_warn(dev->ctrl.device, - "failed to mark controller CONNECTING\n"); - goto out; - } - + mutex_lock(&dev->shutdown_lock); result = nvme_pci_enable(dev); if (result) - goto out; + goto out_unlock; result = nvme_pci_configure_admin_queue(dev); if (result) - goto out; + goto out_unlock; result = nvme_alloc_admin_tags(dev); if (result) - goto out; + goto out_unlock; /* * Limit the max command size to prevent iod->sg allocations going @@ -2555,6 +2576,17 @@ static void nvme_reset_work(struct work_struct *work) */ dev->ctrl.max_hw_sectors = NVME_MAX_KB_SZ << 1; dev->ctrl.max_segments = NVME_MAX_SEGS; + mutex_unlock(&dev->shutdown_lock); + + /* + * Introduce CONNECTING state from nvme-fc/rdma transports to mark the + * initializing procedure here. + */ + if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_CONNECTING)) { + dev_warn(dev->ctrl.device, + "failed to mark controller CONNECTING\n"); + goto out; + } result = nvme_init_identify(&dev->ctrl); if (result) @@ -2619,6 +2651,8 @@ static void nvme_reset_work(struct work_struct *work) nvme_start_ctrl(&dev->ctrl); return; + out_unlock: + mutex_unlock(&dev->shutdown_lock); out: nvme_remove_dead_ctrl(dev, result); } @@ -2946,6 +2980,8 @@ static const struct pci_device_id nvme_id_table[] = { { PCI_VDEVICE(INTEL, 0xf1a5), /* Intel 600P/P3100 */ .driver_data = NVME_QUIRK_NO_DEEPEST_PS | NVME_QUIRK_MEDIUM_PRIO_SQ }, + { PCI_VDEVICE(INTEL, 0xf1a6), /* Intel 760p/Pro 7600p */ + .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, }, { PCI_VDEVICE(INTEL, 0x5845), /* Qemu emulated controller */ .driver_data = NVME_QUIRK_IDENTIFY_CNS, }, { PCI_DEVICE(0x1bb1, 0x0100), /* Seagate Nytro Flash Storage */ diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 0a2fd2949ad7..52abc3a6de12 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -119,6 +119,7 @@ struct nvme_rdma_ctrl { struct nvme_ctrl ctrl; bool use_inline_data; + u32 io_queues[HCTX_MAX_TYPES]; }; static inline struct nvme_rdma_ctrl *to_rdma_ctrl(struct nvme_ctrl *ctrl) @@ -165,8 +166,8 @@ static inline int nvme_rdma_queue_idx(struct nvme_rdma_queue *queue) static bool nvme_rdma_poll_queue(struct nvme_rdma_queue *queue) { return nvme_rdma_queue_idx(queue) > - queue->ctrl->ctrl.opts->nr_io_queues + - queue->ctrl->ctrl.opts->nr_write_queues; + queue->ctrl->io_queues[HCTX_TYPE_DEFAULT] + + queue->ctrl->io_queues[HCTX_TYPE_READ]; } static inline size_t nvme_rdma_inline_data_size(struct nvme_rdma_queue *queue) @@ -661,8 +662,21 @@ static int nvme_rdma_alloc_io_queues(struct nvme_rdma_ctrl *ctrl) nr_io_queues = min_t(unsigned int, nr_io_queues, ibdev->num_comp_vectors); - nr_io_queues += min(opts->nr_write_queues, num_online_cpus()); - nr_io_queues += min(opts->nr_poll_queues, num_online_cpus()); + if (opts->nr_write_queues) { + ctrl->io_queues[HCTX_TYPE_DEFAULT] = + min(opts->nr_write_queues, nr_io_queues); + nr_io_queues += ctrl->io_queues[HCTX_TYPE_DEFAULT]; + } else { + ctrl->io_queues[HCTX_TYPE_DEFAULT] = nr_io_queues; + } + + ctrl->io_queues[HCTX_TYPE_READ] = nr_io_queues; + + if (opts->nr_poll_queues) { + ctrl->io_queues[HCTX_TYPE_POLL] = + min(opts->nr_poll_queues, num_online_cpus()); + nr_io_queues += ctrl->io_queues[HCTX_TYPE_POLL]; + } ret = nvme_set_queue_count(&ctrl->ctrl, &nr_io_queues); if (ret) @@ -1689,18 +1703,28 @@ static enum blk_eh_timer_return nvme_rdma_timeout(struct request *rq, bool reserved) { struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq); + struct nvme_rdma_queue *queue = req->queue; + struct nvme_rdma_ctrl *ctrl = queue->ctrl; - dev_warn(req->queue->ctrl->ctrl.device, - "I/O %d QID %d timeout, reset controller\n", - rq->tag, nvme_rdma_queue_idx(req->queue)); + dev_warn(ctrl->ctrl.device, "I/O %d QID %d timeout\n", + rq->tag, nvme_rdma_queue_idx(queue)); - /* queue error recovery */ - nvme_rdma_error_recovery(req->queue->ctrl); + if (ctrl->ctrl.state != NVME_CTRL_LIVE) { + /* + * Teardown immediately if controller times out while starting + * or we are already started error recovery. all outstanding + * requests are completed on shutdown, so we return BLK_EH_DONE. + */ + flush_work(&ctrl->err_work); + nvme_rdma_teardown_io_queues(ctrl, false); + nvme_rdma_teardown_admin_queue(ctrl, false); + return BLK_EH_DONE; + } - /* fail with DNR on cmd timeout */ - nvme_req(rq)->status = NVME_SC_ABORT_REQ | NVME_SC_DNR; + dev_warn(ctrl->ctrl.device, "starting error recovery\n"); + nvme_rdma_error_recovery(ctrl); - return BLK_EH_DONE; + return BLK_EH_RESET_TIMER; } static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx, @@ -1779,17 +1803,15 @@ static int nvme_rdma_map_queues(struct blk_mq_tag_set *set) struct nvme_rdma_ctrl *ctrl = set->driver_data; set->map[HCTX_TYPE_DEFAULT].queue_offset = 0; - set->map[HCTX_TYPE_READ].nr_queues = ctrl->ctrl.opts->nr_io_queues; + set->map[HCTX_TYPE_DEFAULT].nr_queues = + ctrl->io_queues[HCTX_TYPE_DEFAULT]; + set->map[HCTX_TYPE_READ].nr_queues = ctrl->io_queues[HCTX_TYPE_READ]; if (ctrl->ctrl.opts->nr_write_queues) { /* separate read/write queues */ - set->map[HCTX_TYPE_DEFAULT].nr_queues = - ctrl->ctrl.opts->nr_write_queues; set->map[HCTX_TYPE_READ].queue_offset = - ctrl->ctrl.opts->nr_write_queues; + ctrl->io_queues[HCTX_TYPE_DEFAULT]; } else { /* mixed read/write queues */ - set->map[HCTX_TYPE_DEFAULT].nr_queues = - ctrl->ctrl.opts->nr_io_queues; set->map[HCTX_TYPE_READ].queue_offset = 0; } blk_mq_rdma_map_queues(&set->map[HCTX_TYPE_DEFAULT], @@ -1799,12 +1821,12 @@ static int nvme_rdma_map_queues(struct blk_mq_tag_set *set) if (ctrl->ctrl.opts->nr_poll_queues) { set->map[HCTX_TYPE_POLL].nr_queues = - ctrl->ctrl.opts->nr_poll_queues; + ctrl->io_queues[HCTX_TYPE_POLL]; set->map[HCTX_TYPE_POLL].queue_offset = - ctrl->ctrl.opts->nr_io_queues; + ctrl->io_queues[HCTX_TYPE_DEFAULT]; if (ctrl->ctrl.opts->nr_write_queues) set->map[HCTX_TYPE_POLL].queue_offset += - ctrl->ctrl.opts->nr_write_queues; + ctrl->io_queues[HCTX_TYPE_READ]; blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]); } return 0; diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index de174912445e..5f0a00425242 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -1565,8 +1565,7 @@ static void nvme_tcp_destroy_io_queues(struct nvme_ctrl *ctrl, bool remove) { nvme_tcp_stop_io_queues(ctrl); if (remove) { - if (ctrl->ops->flags & NVME_F_FABRICS) - blk_cleanup_queue(ctrl->connect_q); + blk_cleanup_queue(ctrl->connect_q); blk_mq_free_tag_set(ctrl->tagset); } nvme_tcp_free_io_queues(ctrl); @@ -1587,12 +1586,10 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new) goto out_free_io_queues; } - if (ctrl->ops->flags & NVME_F_FABRICS) { - ctrl->connect_q = blk_mq_init_queue(ctrl->tagset); - if (IS_ERR(ctrl->connect_q)) { - ret = PTR_ERR(ctrl->connect_q); - goto out_free_tag_set; - } + ctrl->connect_q = blk_mq_init_queue(ctrl->tagset); + if (IS_ERR(ctrl->connect_q)) { + ret = PTR_ERR(ctrl->connect_q); + goto out_free_tag_set; } } else { blk_mq_update_nr_hw_queues(ctrl->tagset, @@ -1606,7 +1603,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new) return 0; out_cleanup_connect_q: - if (new && (ctrl->ops->flags & NVME_F_FABRICS)) + if (new) blk_cleanup_queue(ctrl->connect_q); out_free_tag_set: if (new) @@ -1620,7 +1617,6 @@ static void nvme_tcp_destroy_admin_queue(struct nvme_ctrl *ctrl, bool remove) { nvme_tcp_stop_queue(ctrl, 0); if (remove) { - free_opal_dev(ctrl->opal_dev); blk_cleanup_queue(ctrl->admin_q); blk_mq_free_tag_set(ctrl->admin_tagset); } @@ -1952,20 +1948,23 @@ nvme_tcp_timeout(struct request *rq, bool reserved) struct nvme_tcp_ctrl *ctrl = req->queue->ctrl; struct nvme_tcp_cmd_pdu *pdu = req->pdu; - dev_dbg(ctrl->ctrl.device, + dev_warn(ctrl->ctrl.device, "queue %d: timeout request %#x type %d\n", - nvme_tcp_queue_id(req->queue), rq->tag, - pdu->hdr.type); + nvme_tcp_queue_id(req->queue), rq->tag, pdu->hdr.type); if (ctrl->ctrl.state != NVME_CTRL_LIVE) { - union nvme_result res = {}; - - nvme_req(rq)->flags |= NVME_REQ_CANCELLED; - nvme_end_request(rq, cpu_to_le16(NVME_SC_ABORT_REQ), res); + /* + * Teardown immediately if controller times out while starting + * or we are already started error recovery. all outstanding + * requests are completed on shutdown, so we return BLK_EH_DONE. + */ + flush_work(&ctrl->err_work); + nvme_tcp_teardown_io_queues(&ctrl->ctrl, false); + nvme_tcp_teardown_admin_queue(&ctrl->ctrl, false); return BLK_EH_DONE; } - /* queue error recovery */ + dev_warn(ctrl->ctrl.device, "starting error recovery\n"); nvme_tcp_error_recovery(&ctrl->ctrl); return BLK_EH_RESET_TIMER; diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c index a8d23eb80192..a884e3a0e8af 100644 --- a/drivers/nvme/target/rdma.c +++ b/drivers/nvme/target/rdma.c @@ -139,6 +139,10 @@ static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc); static void nvmet_rdma_read_data_done(struct ib_cq *cq, struct ib_wc *wc); static void nvmet_rdma_qp_event(struct ib_event *event, void *priv); static void nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue); +static void nvmet_rdma_free_rsp(struct nvmet_rdma_device *ndev, + struct nvmet_rdma_rsp *r); +static int nvmet_rdma_alloc_rsp(struct nvmet_rdma_device *ndev, + struct nvmet_rdma_rsp *r); static const struct nvmet_fabrics_ops nvmet_rdma_ops; @@ -182,9 +186,17 @@ nvmet_rdma_get_rsp(struct nvmet_rdma_queue *queue) spin_unlock_irqrestore(&queue->rsps_lock, flags); if (unlikely(!rsp)) { - rsp = kmalloc(sizeof(*rsp), GFP_KERNEL); + int ret; + + rsp = kzalloc(sizeof(*rsp), GFP_KERNEL); if (unlikely(!rsp)) return NULL; + ret = nvmet_rdma_alloc_rsp(queue->dev, rsp); + if (unlikely(ret)) { + kfree(rsp); + return NULL; + } + rsp->allocated = true; } @@ -197,6 +209,7 @@ nvmet_rdma_put_rsp(struct nvmet_rdma_rsp *rsp) unsigned long flags; if (unlikely(rsp->allocated)) { + nvmet_rdma_free_rsp(rsp->queue->dev, rsp); kfree(rsp); return; } diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index 44b37b202e39..ad0df786fe93 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -1089,7 +1089,7 @@ out: static int nvmet_tcp_try_recv_one(struct nvmet_tcp_queue *queue) { - int result; + int result = 0; if (unlikely(queue->rcv_state == NVMET_TCP_RECV_ERR)) return 0; diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index a09c1c3cf831..49b16f76d78e 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -207,11 +207,8 @@ static void __of_attach_node(struct device_node *np) if (!of_node_check_flag(np, OF_OVERLAY)) { np->name = __of_get_property(np, "name", NULL); - np->type = __of_get_property(np, "device_type", NULL); if (!np->name) np->name = "<NULL>"; - if (!np->type) - np->type = "<NULL>"; phandle = __of_get_property(np, "phandle", &sz); if (!phandle) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 7099c652c6a5..9cc1461aac7d 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -314,12 +314,8 @@ static bool populate_node(const void *blob, populate_properties(blob, offset, mem, np, pathp, dryrun); if (!dryrun) { np->name = of_get_property(np, "name", NULL); - np->type = of_get_property(np, "device_type", NULL); - if (!np->name) np->name = "<NULL>"; - if (!np->type) - np->type = "<NULL>"; } *pnp = np; diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 2b5ac43a5690..c423e94baf0f 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -423,12 +423,9 @@ static int add_changeset_node(struct overlay_changeset *ovcs, tchild->parent = target->np; tchild->name = __of_get_property(node, "name", NULL); - tchild->type = __of_get_property(node, "device_type", NULL); if (!tchild->name) tchild->name = "<NULL>"; - if (!tchild->type) - tchild->type = "<NULL>"; /* ignore obsolete "linux,phandle" */ phandle = __of_get_property(node, "phandle", &size); diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c index d3185063d369..7eda43c66c91 100644 --- a/drivers/of/pdt.c +++ b/drivers/of/pdt.c @@ -155,7 +155,6 @@ static struct device_node * __init of_pdt_create_node(phandle node, dp->parent = parent; dp->name = of_pdt_get_one_property(node, "name"); - dp->type = of_pdt_get_one_property(node, "device_type"); dp->phandle = node; dp->properties = of_pdt_build_prop_list(node); diff --git a/drivers/of/property.c b/drivers/of/property.c index 08430031bd28..8631efa1daa1 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -806,6 +806,7 @@ struct device_node *of_graph_get_remote_node(const struct device_node *node, if (!of_device_is_available(remote)) { pr_debug("not available for remote node\n"); + of_node_put(remote); return NULL; } diff --git a/drivers/opp/core.c b/drivers/opp/core.c index e5507add8f04..18f1639dbc4a 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -988,11 +988,9 @@ void _opp_free(struct dev_pm_opp *opp) kfree(opp); } -static void _opp_kref_release(struct kref *kref) +static void _opp_kref_release(struct dev_pm_opp *opp, + struct opp_table *opp_table) { - struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref); - struct opp_table *opp_table = opp->opp_table; - /* * Notify the changes in the availability of the operable * frequency/voltage list. @@ -1002,7 +1000,22 @@ static void _opp_kref_release(struct kref *kref) opp_debug_remove_one(opp); list_del(&opp->node); kfree(opp); +} +static void _opp_kref_release_unlocked(struct kref *kref) +{ + struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref); + struct opp_table *opp_table = opp->opp_table; + + _opp_kref_release(opp, opp_table); +} + +static void _opp_kref_release_locked(struct kref *kref) +{ + struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref); + struct opp_table *opp_table = opp->opp_table; + + _opp_kref_release(opp, opp_table); mutex_unlock(&opp_table->lock); } @@ -1013,10 +1026,16 @@ void dev_pm_opp_get(struct dev_pm_opp *opp) void dev_pm_opp_put(struct dev_pm_opp *opp) { - kref_put_mutex(&opp->kref, _opp_kref_release, &opp->opp_table->lock); + kref_put_mutex(&opp->kref, _opp_kref_release_locked, + &opp->opp_table->lock); } EXPORT_SYMBOL_GPL(dev_pm_opp_put); +static void dev_pm_opp_put_unlocked(struct dev_pm_opp *opp) +{ + kref_put(&opp->kref, _opp_kref_release_unlocked); +} + /** * dev_pm_opp_remove() - Remove an OPP from OPP table * @dev: device for which we do this operation @@ -1060,6 +1079,40 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq) } EXPORT_SYMBOL_GPL(dev_pm_opp_remove); +/** + * dev_pm_opp_remove_all_dynamic() - Remove all dynamically created OPPs + * @dev: device for which we do this operation + * + * This function removes all dynamically created OPPs from the opp table. + */ +void dev_pm_opp_remove_all_dynamic(struct device *dev) +{ + struct opp_table *opp_table; + struct dev_pm_opp *opp, *temp; + int count = 0; + + opp_table = _find_opp_table(dev); + if (IS_ERR(opp_table)) + return; + + mutex_lock(&opp_table->lock); + list_for_each_entry_safe(opp, temp, &opp_table->opp_list, node) { + if (opp->dynamic) { + dev_pm_opp_put_unlocked(opp); + count++; + } + } + mutex_unlock(&opp_table->lock); + + /* Drop the references taken by dev_pm_opp_add() */ + while (count--) + dev_pm_opp_put_opp_table(opp_table); + + /* Drop the reference taken by _find_opp_table() */ + dev_pm_opp_put_opp_table(opp_table); +} +EXPORT_SYMBOL_GPL(dev_pm_opp_remove_all_dynamic); + struct dev_pm_opp *_opp_allocate(struct opp_table *table) { struct dev_pm_opp *opp; diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 4310c7a4212e..2ab92409210a 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -21,13 +21,14 @@ menuconfig PCI support for PCI-X and the foundations for PCI Express support. Say 'Y' here unless you know what you are doing. +if PCI + config PCI_DOMAINS bool depends on PCI config PCI_DOMAINS_GENERIC bool - depends on PCI select PCI_DOMAINS config PCI_SYSCALL @@ -37,7 +38,6 @@ source "drivers/pci/pcie/Kconfig" config PCI_MSI bool "Message Signaled Interrupts (MSI and MSI-X)" - depends on PCI select GENERIC_MSI_IRQ help This allows device drivers to enable MSI (Message Signaled @@ -59,7 +59,6 @@ config PCI_MSI_IRQ_DOMAIN config PCI_QUIRKS default y bool "Enable PCI quirk workarounds" if EXPERT - depends on PCI help This enables workarounds for various PCI chipset bugs/quirks. Disable this only if your target machine is unaffected by PCI @@ -67,7 +66,7 @@ config PCI_QUIRKS config PCI_DEBUG bool "PCI Debugging" - depends on PCI && DEBUG_KERNEL + depends on DEBUG_KERNEL help Say Y here if you want the PCI core to produce a bunch of debug messages to the system log. Select this if you are having a @@ -77,7 +76,6 @@ config PCI_DEBUG config PCI_REALLOC_ENABLE_AUTO bool "Enable PCI resource re-allocation detection" - depends on PCI depends on PCI_IOV help Say Y here if you want the PCI core to detect if PCI resource @@ -90,7 +88,6 @@ config PCI_REALLOC_ENABLE_AUTO config PCI_STUB tristate "PCI Stub driver" - depends on PCI help Say Y or M here if you want be able to reserve a PCI device when it is going to be assigned to a guest operating system. @@ -99,7 +96,6 @@ config PCI_STUB config PCI_PF_STUB tristate "PCI PF Stub driver" - depends on PCI depends on PCI_IOV help Say Y or M here if you want to enable support for devices that @@ -111,7 +107,7 @@ config PCI_PF_STUB config XEN_PCIDEV_FRONTEND tristate "Xen PCI Frontend" - depends on PCI && X86 && XEN + depends on X86 && XEN select PCI_XEN select XEN_XENBUS_FRONTEND default y @@ -133,7 +129,6 @@ config PCI_BRIDGE_EMUL config PCI_IOV bool "PCI IOV support" - depends on PCI select PCI_ATS help I/O Virtualization is a PCI feature supported by some devices @@ -144,7 +139,6 @@ config PCI_IOV config PCI_PRI bool "PCI PRI support" - depends on PCI select PCI_ATS help PRI is the PCI Page Request Interface. It allows PCI devices that are @@ -154,7 +148,6 @@ config PCI_PRI config PCI_PASID bool "PCI PASID support" - depends on PCI select PCI_ATS help Process Address Space Identifiers (PASIDs) can be used by PCI devices @@ -167,7 +160,7 @@ config PCI_PASID config PCI_P2PDMA bool "PCI peer-to-peer transfer support" - depends on PCI && ZONE_DEVICE + depends on ZONE_DEVICE select GENERIC_ALLOCATOR help EnableÑ• drivers to do PCI peer-to-peer transactions to and from @@ -184,12 +177,11 @@ config PCI_P2PDMA config PCI_LABEL def_bool y if (DMI || ACPI) - depends on PCI select NLS config PCI_HYPERV tristate "Hyper-V PCI Frontend" - depends on PCI && X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64 + depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64 help The PCI device frontend driver allows the kernel to import arbitrary PCI devices from a PCI backend to support PCI driver domains. @@ -198,3 +190,5 @@ source "drivers/pci/hotplug/Kconfig" source "drivers/pci/controller/Kconfig" source "drivers/pci/endpoint/Kconfig" source "drivers/pci/switch/Kconfig" + +endif diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 52e47dac028f..80f843030e36 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -310,6 +310,9 @@ static int imx6_pcie_attach_pd(struct device *dev) imx6_pcie->pd_pcie = dev_pm_domain_attach_by_name(dev, "pcie"); if (IS_ERR(imx6_pcie->pd_pcie)) return PTR_ERR(imx6_pcie->pd_pcie); + /* Do nothing when power domain missing */ + if (!imx6_pcie->pd_pcie) + return 0; link = device_link_add(dev, imx6_pcie->pd_pcie, DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME | @@ -323,13 +326,13 @@ static int imx6_pcie_attach_pd(struct device *dev) if (IS_ERR(imx6_pcie->pd_pcie_phy)) return PTR_ERR(imx6_pcie->pd_pcie_phy); - device_link_add(dev, imx6_pcie->pd_pcie_phy, + link = device_link_add(dev, imx6_pcie->pd_pcie_phy, DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE); - if (IS_ERR(link)) { - dev_err(dev, "Failed to add device_link to pcie_phy pd: %ld\n", PTR_ERR(link)); - return PTR_ERR(link); + if (!link) { + dev_err(dev, "Failed to add device_link to pcie_phy pd.\n"); + return -EINVAL; } return 0; diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c index 241ebe0c4505..e35e9eaa50ee 100644 --- a/drivers/pci/controller/dwc/pci-meson.c +++ b/drivers/pci/controller/dwc/pci-meson.c @@ -8,6 +8,7 @@ #include <linux/clk.h> #include <linux/delay.h> +#include <linux/gpio/consumer.h> #include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/pci.h> diff --git a/drivers/pci/controller/dwc/pcie-armada8k.c b/drivers/pci/controller/dwc/pcie-armada8k.c index b171b6bc15c8..0c389a30ef5d 100644 --- a/drivers/pci/controller/dwc/pcie-armada8k.c +++ b/drivers/pci/controller/dwc/pcie-armada8k.c @@ -22,7 +22,6 @@ #include <linux/resource.h> #include <linux/of_pci.h> #include <linux/of_irq.h> -#include <linux/gpio/consumer.h> #include "pcie-designware.h" @@ -30,7 +29,6 @@ struct armada8k_pcie { struct dw_pcie *pci; struct clk *clk; struct clk *clk_reg; - struct gpio_desc *reset_gpio; }; #define PCIE_VENDOR_REGS_OFFSET 0x8000 @@ -139,12 +137,6 @@ static int armada8k_pcie_host_init(struct pcie_port *pp) struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct armada8k_pcie *pcie = to_armada8k_pcie(pci); - if (pcie->reset_gpio) { - /* assert and then deassert the reset signal */ - gpiod_set_value_cansleep(pcie->reset_gpio, 1); - msleep(100); - gpiod_set_value_cansleep(pcie->reset_gpio, 0); - } dw_pcie_setup_rc(pp); armada8k_pcie_establish_link(pcie); @@ -257,14 +249,6 @@ static int armada8k_pcie_probe(struct platform_device *pdev) goto fail_clkreg; } - /* Get reset gpio signal and hold asserted (logically high) */ - pcie->reset_gpio = devm_gpiod_get_optional(dev, "reset", - GPIOD_OUT_HIGH); - if (IS_ERR(pcie->reset_gpio)) { - ret = PTR_ERR(pcie->reset_gpio); - goto fail_clkreg; - } - platform_set_drvdata(pdev, pcie); ret = armada8k_add_pcie_port(pcie, pdev); diff --git a/drivers/pci/controller/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c index 9deb56989d72..cb3401a931f8 100644 --- a/drivers/pci/controller/pcie-iproc-msi.c +++ b/drivers/pci/controller/pcie-iproc-msi.c @@ -602,9 +602,9 @@ int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node) } /* Reserve memory for event queue and make sure memories are zeroed */ - msi->eq_cpu = dma_zalloc_coherent(pcie->dev, - msi->nr_eq_region * EQ_MEM_REGION_SIZE, - &msi->eq_dma, GFP_KERNEL); + msi->eq_cpu = dma_alloc_coherent(pcie->dev, + msi->nr_eq_region * EQ_MEM_REGION_SIZE, + &msi->eq_dma, GFP_KERNEL); if (!msi->eq_cpu) { ret = -ENOMEM; goto free_irqs; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 7a1c8a09efa5..4c0b47867258 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -1168,7 +1168,8 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs, const struct irq_affinity *affd) { static const struct irq_affinity msi_default_affd; - int vecs = -ENOSPC; + int msix_vecs = -ENOSPC; + int msi_vecs = -ENOSPC; if (flags & PCI_IRQ_AFFINITY) { if (!affd) @@ -1179,16 +1180,17 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs, } if (flags & PCI_IRQ_MSIX) { - vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs, - affd); - if (vecs > 0) - return vecs; + msix_vecs = __pci_enable_msix_range(dev, NULL, min_vecs, + max_vecs, affd); + if (msix_vecs > 0) + return msix_vecs; } if (flags & PCI_IRQ_MSI) { - vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, affd); - if (vecs > 0) - return vecs; + msi_vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, + affd); + if (msi_vecs > 0) + return msi_vecs; } /* use legacy irq if allowed */ @@ -1199,7 +1201,9 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs, } } - return vecs; + if (msix_vecs == -ENOSPC) + return -ENOSPC; + return msi_vecs; } EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index c9d8e3c837de..c25acace7d91 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -6195,7 +6195,8 @@ static int __init pci_setup(char *str) } else if (!strncmp(str, "pcie_scan_all", 13)) { pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS); } else if (!strncmp(str, "disable_acs_redir=", 18)) { - disable_acs_redir_param = str + 18; + disable_acs_redir_param = + kstrdup(str + 18, GFP_KERNEL); } else { printk(KERN_ERR "PCI: Unknown option `%s'\n", str); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index b0a413f3f7ca..e2a879e93d86 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -639,8 +639,9 @@ static void quirk_synopsys_haps(struct pci_dev *pdev) break; } } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, PCI_ANY_ID, - quirk_synopsys_haps); +DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, PCI_ANY_ID, + PCI_CLASS_SERIAL_USB_XHCI, 0, + quirk_synopsys_haps); /* * Let's make the southbridge information explicit instead of having to diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c index 6c5536d3d42a..e22766c79fe9 100644 --- a/drivers/pci/switch/switchtec.c +++ b/drivers/pci/switch/switchtec.c @@ -1373,10 +1373,10 @@ static int switchtec_init_pci(struct switchtec_dev *stdev, if (ioread32(&stdev->mmio_mrpc->dma_ver) == 0) return 0; - stdev->dma_mrpc = dma_zalloc_coherent(&stdev->pdev->dev, - sizeof(*stdev->dma_mrpc), - &stdev->dma_mrpc_dma_addr, - GFP_KERNEL); + stdev->dma_mrpc = dma_alloc_coherent(&stdev->pdev->dev, + sizeof(*stdev->dma_mrpc), + &stdev->dma_mrpc_dma_addr, + GFP_KERNEL); if (stdev->dma_mrpc == NULL) return -ENOMEM; diff --git a/drivers/phy/marvell/phy-berlin-sata.c b/drivers/phy/marvell/phy-berlin-sata.c index a91fc67fc4e0..d70ba9bc42d9 100644 --- a/drivers/phy/marvell/phy-berlin-sata.c +++ b/drivers/phy/marvell/phy-berlin-sata.c @@ -32,7 +32,7 @@ /* register 0x01 */ #define REF_FREF_SEL_25 BIT(0) -#define PHY_MODE_SATA (0x0 << 5) +#define PHY_BERLIN_MODE_SATA (0x0 << 5) /* register 0x02 */ #define USE_MAX_PLL_RATE BIT(12) @@ -102,7 +102,8 @@ static int phy_berlin_sata_power_on(struct phy *phy) /* set PHY mode and ref freq to 25 MHz */ phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x01, - 0x00ff, REF_FREF_SEL_25 | PHY_MODE_SATA); + 0x00ff, + REF_FREF_SEL_25 | PHY_BERLIN_MODE_SATA); /* set PHY up to 6 Gbps */ phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x25, diff --git a/drivers/phy/qualcomm/phy-ath79-usb.c b/drivers/phy/qualcomm/phy-ath79-usb.c index 6fd6e07ab345..09a77e556ece 100644 --- a/drivers/phy/qualcomm/phy-ath79-usb.c +++ b/drivers/phy/qualcomm/phy-ath79-usb.c @@ -31,7 +31,7 @@ static int ath79_usb_phy_power_on(struct phy *phy) err = reset_control_deassert(priv->reset); if (err && priv->no_suspend_override) - reset_control_assert(priv->no_suspend_override); + reset_control_deassert(priv->no_suspend_override); return err; } @@ -69,7 +69,7 @@ static int ath79_usb_phy_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - priv->reset = devm_reset_control_get(&pdev->dev, "usb-phy"); + priv->reset = devm_reset_control_get(&pdev->dev, "phy"); if (IS_ERR(priv->reset)) return PTR_ERR(priv->reset); diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig index f137e0107764..c4709ed7fb0e 100644 --- a/drivers/phy/ti/Kconfig +++ b/drivers/phy/ti/Kconfig @@ -82,6 +82,7 @@ config PHY_TI_GMII_SEL default y if TI_CPSW=y depends on TI_CPSW || COMPILE_TEST select GENERIC_PHY + select REGMAP default m help This driver supports configuring of the TI CPSW Port mode depending on diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c index 77fdaa551977..a52c5bb35033 100644 --- a/drivers/phy/ti/phy-gmii-sel.c +++ b/drivers/phy/ti/phy-gmii-sel.c @@ -204,11 +204,11 @@ static struct phy *phy_gmii_sel_of_xlate(struct device *dev, if (args->args_count < 1) return ERR_PTR(-EINVAL); + if (!priv || !priv->if_phys) + return ERR_PTR(-ENODEV); if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) && args->args_count < 2) return ERR_PTR(-EINVAL); - if (!priv || !priv->if_phys) - return ERR_PTR(-ENODEV); if (phy_id > priv->soc_data->num_ports) return ERR_PTR(-EINVAL); if (phy_id != priv->if_phys[phy_id - 1].id) diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 05044e323ea5..03ec7a5d9d0b 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1513,7 +1513,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"), - DMI_MATCH(DMI_BOARD_VERSION, "1.0"), + DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"), }, }, { @@ -1521,7 +1521,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "HP"), DMI_MATCH(DMI_PRODUCT_NAME, "Setzer"), - DMI_MATCH(DMI_BOARD_VERSION, "1.0"), + DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"), }, }, { @@ -1529,7 +1529,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"), - DMI_MATCH(DMI_BOARD_VERSION, "1.0"), + DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"), }, }, { @@ -1537,7 +1537,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), DMI_MATCH(DMI_PRODUCT_NAME, "Celes"), - DMI_MATCH(DMI_BOARD_VERSION, "1.0"), + DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"), }, }, {} diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig index 1817786ab6aa..a005cbccb4f7 100644 --- a/drivers/pinctrl/mediatek/Kconfig +++ b/drivers/pinctrl/mediatek/Kconfig @@ -45,12 +45,14 @@ config PINCTRL_MT2701 config PINCTRL_MT7623 bool "Mediatek MT7623 pin control with generic binding" depends on MACH_MT7623 || COMPILE_TEST + depends on OF default MACH_MT7623 select PINCTRL_MTK_MOORE config PINCTRL_MT7629 bool "Mediatek MT7629 pin control" depends on MACH_MT7629 || COMPILE_TEST + depends on OF default MACH_MT7629 select PINCTRL_MTK_MOORE @@ -92,6 +94,7 @@ config PINCTRL_MT6797 config PINCTRL_MT7622 bool "MediaTek MT7622 pin control" + depends on OF depends on ARM64 || COMPILE_TEST default ARM64 && ARCH_MEDIATEK select PINCTRL_MTK_MOORE diff --git a/drivers/pinctrl/meson/pinctrl-meson8b.c b/drivers/pinctrl/meson/pinctrl-meson8b.c index c69ca95b1ad5..0f140a802137 100644 --- a/drivers/pinctrl/meson/pinctrl-meson8b.c +++ b/drivers/pinctrl/meson/pinctrl-meson8b.c @@ -693,7 +693,7 @@ static const char * const sd_a_groups[] = { static const char * const sdxc_a_groups[] = { "sdxc_d0_0_a", "sdxc_d13_0_a", "sdxc_d47_a", "sdxc_clk_a", - "sdxc_cmd_a", "sdxc_d0_1_a", "sdxc_d0_13_1_a" + "sdxc_cmd_a", "sdxc_d0_1_a", "sdxc_d13_1_a" }; static const char * const pcm_a_groups[] = { diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c index b03481ef99a1..98905d4a79ca 100644 --- a/drivers/pinctrl/pinctrl-mcp23s08.c +++ b/drivers/pinctrl/pinctrl-mcp23s08.c @@ -832,8 +832,13 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, break; case MCP_TYPE_S18: + one_regmap_config = + devm_kmemdup(dev, &mcp23x17_regmap, + sizeof(struct regmap_config), GFP_KERNEL); + if (!one_regmap_config) + return -ENOMEM; mcp->regmap = devm_regmap_init(dev, &mcp23sxx_spi_regmap, mcp, - &mcp23x17_regmap); + one_regmap_config); mcp->reg_shift = 1; mcp->chip.ngpio = 16; mcp->chip.label = "mcp23s18"; diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c index 7aae52a09ff0..4ffd56ff809e 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs404.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c @@ -79,7 +79,7 @@ enum { .intr_cfg_reg = 0, \ .intr_status_reg = 0, \ .intr_target_reg = 0, \ - .tile = NORTH, \ + .tile = SOUTH, \ .mux_bit = -1, \ .pull_bit = pull, \ .drv_bit = drv, \ diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c index aa8b58125568..ef4268cc6227 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c @@ -588,7 +588,7 @@ static const unsigned int h6_irq_bank_map[] = { 1, 5, 6, 7 }; static const struct sunxi_pinctrl_desc h6_pinctrl_data = { .pins = h6_pins, .npins = ARRAY_SIZE(h6_pins), - .irq_banks = 3, + .irq_banks = 4, .irq_bank_map = h6_irq_bank_map, .irq_read_needs_mux = true, }; diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 5d9184d18c16..0e7fa69e93df 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -698,26 +698,24 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset) { struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); unsigned short bank = offset / PINS_PER_BANK; - struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank]; - struct regulator *reg; + unsigned short bank_offset = bank - pctl->desc->pin_base / + PINS_PER_BANK; + struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset]; + struct regulator *reg = s_reg->regulator; + char supply[16]; int ret; - reg = s_reg->regulator; - if (!reg) { - char supply[16]; - - snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank); - reg = regulator_get(pctl->dev, supply); - if (IS_ERR(reg)) { - dev_err(pctl->dev, "Couldn't get bank P%c regulator\n", - 'A' + bank); - return PTR_ERR(reg); - } - - s_reg->regulator = reg; - refcount_set(&s_reg->refcount, 1); - } else { + if (reg) { refcount_inc(&s_reg->refcount); + return 0; + } + + snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank); + reg = regulator_get(pctl->dev, supply); + if (IS_ERR(reg)) { + dev_err(pctl->dev, "Couldn't get bank P%c regulator\n", + 'A' + bank); + return PTR_ERR(reg); } ret = regulator_enable(reg); @@ -727,13 +725,13 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset) goto out; } + s_reg->regulator = reg; + refcount_set(&s_reg->refcount, 1); + return 0; out: - if (refcount_dec_and_test(&s_reg->refcount)) { - regulator_put(s_reg->regulator); - s_reg->regulator = NULL; - } + regulator_put(s_reg->regulator); return ret; } @@ -742,7 +740,9 @@ static int sunxi_pmx_free(struct pinctrl_dev *pctldev, unsigned offset) { struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); unsigned short bank = offset / PINS_PER_BANK; - struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank]; + unsigned short bank_offset = bank - pctl->desc->pin_base / + PINS_PER_BANK; + struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset]; if (!refcount_dec_and_test(&s_reg->refcount)) return 0; diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h index e340d2a24b44..034c0317c8d6 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h @@ -136,7 +136,7 @@ struct sunxi_pinctrl { struct gpio_chip *chip; const struct sunxi_pinctrl_desc *desc; struct device *dev; - struct sunxi_pinctrl_regulator regulators[12]; + struct sunxi_pinctrl_regulator regulators[9]; struct irq_domain *domain; struct sunxi_pinctrl_function *functions; unsigned nfunctions; diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index e3b62c2ee8d1..b5e9db85e881 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -905,6 +905,7 @@ config TOSHIBA_WMI config ACPI_CMPC tristate "CMPC Laptop Extras" depends on ACPI && INPUT + depends on BACKLIGHT_LCD_SUPPORT depends on RFKILL || RFKILL=n select BACKLIGHT_CLASS_DEVICE help @@ -1009,7 +1010,7 @@ config INTEL_MFLD_THERMAL config INTEL_IPS tristate "Intel Intelligent Power Sharing" - depends on ACPI + depends on ACPI && PCI ---help--- Intel Calpella platforms support dynamic power sharing between the CPU and GPU, maximizing performance in a given TDP. This driver, @@ -1128,6 +1129,7 @@ config INTEL_OAKTRAIL config SAMSUNG_Q10 tristate "Samsung Q10 Extras" depends on ACPI + depends on BACKLIGHT_LCD_SUPPORT select BACKLIGHT_CLASS_DEVICE ---help--- This driver provides support for backlight control on Samsung Q10 @@ -1135,7 +1137,7 @@ config SAMSUNG_Q10 config APPLE_GMUX tristate "Apple Gmux Driver" - depends on ACPI + depends on ACPI && PCI depends on PNP depends on BACKLIGHT_CLASS_DEVICE depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE @@ -1174,7 +1176,7 @@ config INTEL_SMARTCONNECT config INTEL_PMC_IPC tristate "Intel PMC IPC Driver" - depends on ACPI + depends on ACPI && PCI ---help--- This driver provides support for PMC control on some Intel platforms. The PMC is an ARC processor which defines IPC commands for communication diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c index 797fab33bb98..7cbea796652a 100644 --- a/drivers/ptp/ptp_chardev.c +++ b/drivers/ptp/ptp_chardev.c @@ -224,7 +224,8 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg) extoff = NULL; break; } - if (extoff->n_samples > PTP_MAX_SAMPLES) { + if (extoff->n_samples > PTP_MAX_SAMPLES + || extoff->rsv[0] || extoff->rsv[1] || extoff->rsv[2]) { err = -EINVAL; break; } diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index bb655854713d..b64c56c33c3b 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -1382,9 +1382,9 @@ static int tsi721_doorbell_init(struct tsi721_device *priv) INIT_WORK(&priv->idb_work, tsi721_db_dpc); /* Allocate buffer for inbound doorbells queue */ - priv->idb_base = dma_zalloc_coherent(&priv->pdev->dev, - IDB_QSIZE * TSI721_IDB_ENTRY_SIZE, - &priv->idb_dma, GFP_KERNEL); + priv->idb_base = dma_alloc_coherent(&priv->pdev->dev, + IDB_QSIZE * TSI721_IDB_ENTRY_SIZE, + &priv->idb_dma, GFP_KERNEL); if (!priv->idb_base) return -ENOMEM; @@ -1447,9 +1447,9 @@ static int tsi721_bdma_maint_init(struct tsi721_device *priv) regs = priv->regs + TSI721_DMAC_BASE(TSI721_DMACH_MAINT); /* Allocate space for DMA descriptors */ - bd_ptr = dma_zalloc_coherent(&priv->pdev->dev, - bd_num * sizeof(struct tsi721_dma_desc), - &bd_phys, GFP_KERNEL); + bd_ptr = dma_alloc_coherent(&priv->pdev->dev, + bd_num * sizeof(struct tsi721_dma_desc), + &bd_phys, GFP_KERNEL); if (!bd_ptr) return -ENOMEM; @@ -1464,7 +1464,7 @@ static int tsi721_bdma_maint_init(struct tsi721_device *priv) sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ? bd_num : TSI721_DMA_MINSTSSZ; sts_size = roundup_pow_of_two(sts_size); - sts_ptr = dma_zalloc_coherent(&priv->pdev->dev, + sts_ptr = dma_alloc_coherent(&priv->pdev->dev, sts_size * sizeof(struct tsi721_dma_sts), &sts_phys, GFP_KERNEL); if (!sts_ptr) { @@ -1939,10 +1939,10 @@ static int tsi721_open_outb_mbox(struct rio_mport *mport, void *dev_id, /* Outbound message descriptor status FIFO allocation */ priv->omsg_ring[mbox].sts_size = roundup_pow_of_two(entries + 1); - priv->omsg_ring[mbox].sts_base = dma_zalloc_coherent(&priv->pdev->dev, - priv->omsg_ring[mbox].sts_size * - sizeof(struct tsi721_dma_sts), - &priv->omsg_ring[mbox].sts_phys, GFP_KERNEL); + priv->omsg_ring[mbox].sts_base = dma_alloc_coherent(&priv->pdev->dev, + priv->omsg_ring[mbox].sts_size * sizeof(struct tsi721_dma_sts), + &priv->omsg_ring[mbox].sts_phys, + GFP_KERNEL); if (priv->omsg_ring[mbox].sts_base == NULL) { tsi_debug(OMSG, &priv->pdev->dev, "ENOMEM for OB_MSG_%d status FIFO", mbox); diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c index 006ea5a45020..7f5d4436f594 100644 --- a/drivers/rapidio/devices/tsi721_dma.c +++ b/drivers/rapidio/devices/tsi721_dma.c @@ -90,9 +90,9 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan, int bd_num) * Allocate space for DMA descriptors * (add an extra element for link descriptor) */ - bd_ptr = dma_zalloc_coherent(dev, - (bd_num + 1) * sizeof(struct tsi721_dma_desc), - &bd_phys, GFP_ATOMIC); + bd_ptr = dma_alloc_coherent(dev, + (bd_num + 1) * sizeof(struct tsi721_dma_desc), + &bd_phys, GFP_ATOMIC); if (!bd_ptr) return -ENOMEM; @@ -108,7 +108,7 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan, int bd_num) sts_size = ((bd_num + 1) >= TSI721_DMA_MINSTSSZ) ? (bd_num + 1) : TSI721_DMA_MINSTSSZ; sts_size = roundup_pow_of_two(sts_size); - sts_ptr = dma_zalloc_coherent(dev, + sts_ptr = dma_alloc_coherent(dev, sts_size * sizeof(struct tsi721_dma_sts), &sts_phys, GFP_ATOMIC); if (!sts_ptr) { diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 28f55248eb90..753a6a1b30c3 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/i2c.h> #include <linux/of.h> #include <linux/regulator/of_regulator.h> #include <linux/platform_device.h> @@ -22,12 +21,7 @@ struct pm8607_regulator_info { struct regulator_desc desc; - struct pm860x_chip *chip; - struct regulator_dev *regulator; - struct i2c_client *i2c; - struct i2c_client *i2c_8606; - unsigned int *vol_table; unsigned int *vol_suspend; int slope_double; @@ -210,13 +204,15 @@ static const unsigned int LDO14_suspend_table[] = { static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) { struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); - int ret = -EINVAL; + int ret; + + ret = regulator_list_voltage_table(rdev, index); + if (ret < 0) + return ret; + + if (info->slope_double) + ret <<= 1; - if (info->vol_table && (index < rdev->desc->n_voltages)) { - ret = info->vol_table[index]; - if (info->slope_double) - ret <<= 1; - } return ret; } @@ -257,6 +253,7 @@ static const struct regulator_ops pm8606_preg_ops = { .type = REGULATOR_VOLTAGE, \ .id = PM8607_ID_##vreg, \ .owner = THIS_MODULE, \ + .volt_table = vreg##_table, \ .n_voltages = ARRAY_SIZE(vreg##_table), \ .vsel_reg = PM8607_##vreg, \ .vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \ @@ -266,7 +263,6 @@ static const struct regulator_ops pm8606_preg_ops = { .enable_mask = 1 << (ebit), \ }, \ .slope_double = (0), \ - .vol_table = (unsigned int *)&vreg##_table, \ .vol_suspend = (unsigned int *)&vreg##_suspend_table, \ } @@ -278,6 +274,7 @@ static const struct regulator_ops pm8606_preg_ops = { .type = REGULATOR_VOLTAGE, \ .id = PM8607_ID_LDO##_id, \ .owner = THIS_MODULE, \ + .volt_table = LDO##_id##_table, \ .n_voltages = ARRAY_SIZE(LDO##_id##_table), \ .vsel_reg = PM8607_##vreg, \ .vsel_mask = (ARRAY_SIZE(LDO##_id##_table) - 1) << (shift), \ @@ -285,7 +282,6 @@ static const struct regulator_ops pm8606_preg_ops = { .enable_mask = 1 << (ebit), \ }, \ .slope_double = (0), \ - .vol_table = (unsigned int *)&LDO##_id##_table, \ .vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \ } @@ -349,6 +345,7 @@ static int pm8607_regulator_probe(struct platform_device *pdev) struct pm8607_regulator_info *info = NULL; struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev); struct regulator_config config = { }; + struct regulator_dev *rdev; struct resource *res; int i; @@ -371,13 +368,9 @@ static int pm8607_regulator_probe(struct platform_device *pdev) /* i is used to check regulator ID */ i = -1; } - info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; - info->i2c_8606 = (chip->id == CHIP_PM8607) ? chip->companion : - chip->client; - info->chip = chip; /* check DVC ramp slope double */ - if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double) + if ((i == PM8607_ID_BUCK3) && chip->buck3_double) info->slope_double = 1; config.dev = &pdev->dev; @@ -392,12 +385,11 @@ static int pm8607_regulator_probe(struct platform_device *pdev) else config.regmap = chip->regmap_companion; - info->regulator = devm_regulator_register(&pdev->dev, &info->desc, - &config); - if (IS_ERR(info->regulator)) { + rdev = devm_regulator_register(&pdev->dev, &info->desc, &config); + if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", info->desc.name); - return PTR_ERR(info->regulator); + return PTR_ERR(rdev); } platform_set_drvdata(pdev, info); diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index ee60a222f5eb..b7f249ee5e68 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -180,6 +180,17 @@ config REGULATOR_BCM590XX BCM590xx PMUs. This will enable support for the software controllable LDO/Switching regulators. +config REGULATOR_BD70528 + tristate "ROHM BD70528 Power Regulator" + depends on MFD_ROHM_BD70528 + help + This driver supports voltage regulators on ROHM BD70528 PMIC. + This will enable support for the software controllable buck + and LDO regulators. + + This driver can also be built as a module. If so, the module + will be called bd70528-regulator. + config REGULATOR_BD718XX tristate "ROHM BD71837 Power Regulator" depends on MFD_ROHM_BD718XX @@ -457,6 +468,14 @@ config REGULATOR_MAX77620 chip to control Step-Down DC-DC and LDOs. Say Y here to enable the regulator driver. +config REGULATOR_MAX77650 + tristate "Maxim MAX77650/77651 regulator support" + depends on MFD_MAX77650 + help + Regulator driver for MAX77650/77651 PMIC from Maxim + Semiconductor. This device has a SIMO with three independent + power rails and an LDO. + config REGULATOR_MAX8649 tristate "Maxim 8649 voltage regulator" depends on I2C @@ -484,7 +503,7 @@ config REGULATOR_MAX8925 tristate "Maxim MAX8925 Power Management IC" depends on MFD_MAX8925 help - Say y here to support the voltage regulaltor of Maxim MAX8925 PMIC. + Say y here to support the voltage regulator of Maxim MAX8925 PMIC. config REGULATOR_MAX8952 tristate "Maxim MAX8952 Power Management IC" @@ -501,7 +520,7 @@ config REGULATOR_MAX8973 select REGMAP_I2C help The MAXIM MAX8973 high-efficiency. three phase, DC-DC step-down - switching regulator delievers up to 9A of output current. Each + switching regulator delivers up to 9A of output current. Each phase operates at a 2MHz fixed frequency with a 120 deg shift from the adjacent phase, allowing the use of small magnetic component. @@ -646,7 +665,7 @@ config REGULATOR_PCF50633 tristate "NXP PCF50633 regulator driver" depends on MFD_PCF50633 help - Say Y here to support the voltage regulators and convertors + Say Y here to support the voltage regulators and converters on PCF50633 config REGULATOR_PFUZE100 @@ -924,7 +943,7 @@ config REGULATOR_TPS65132 select REGMAP_I2C help This driver supports TPS65132 single inductor - dual output - power supply specifcally designed for display panels. + power supply specifically designed for display panels. config REGULATOR_TPS65217 tristate "TI TPS65217 Power regulators" diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index b12e1c9b2118..1169f8a27d91 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o +obj-$(CONFIG_REGULATOR_BD70528) += bd70528-regulator.o obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o @@ -60,6 +61,7 @@ obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o +obj-$(CONFIG_REGULATOR_MAX77650) += max77650-regulator.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 21e20483bd91..e0239cf3f56d 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -131,7 +131,7 @@ * ACT8865 voltage number */ #define ACT8865_VOLTAGE_NUM 64 -#define ACT8600_SUDCDC_VOLTAGE_NUM 255 +#define ACT8600_SUDCDC_VOLTAGE_NUM 256 struct act8865 { struct regmap *regmap; @@ -222,7 +222,8 @@ static const struct regulator_linear_range act8600_sudcdc_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(3000000, 0, 63, 0), REGULATOR_LINEAR_RANGE(3000000, 64, 159, 100000), REGULATOR_LINEAR_RANGE(12600000, 160, 191, 200000), - REGULATOR_LINEAR_RANGE(19000000, 191, 255, 400000), + REGULATOR_LINEAR_RANGE(19000000, 192, 247, 400000), + REGULATOR_LINEAR_RANGE(41400000, 248, 255, 0), }; static struct regulator_ops act8865_ops = { diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c index 603db77723b6..caa61d306a69 100644 --- a/drivers/regulator/act8945a-regulator.c +++ b/drivers/regulator/act8945a-regulator.c @@ -87,7 +87,8 @@ static const struct regulator_linear_range act8945a_voltage_ranges[] = { static int act8945a_set_suspend_state(struct regulator_dev *rdev, bool enable) { struct regmap *regmap = rdev->regmap; - int id = rdev->desc->id, reg, val; + int id = rdev_get_id(rdev); + int reg, val; switch (id) { case ACT8945A_ID_DCDC1: @@ -159,7 +160,7 @@ static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct act8945a_pmic *act8945a = rdev_get_drvdata(rdev); struct regmap *regmap = rdev->regmap; - int id = rdev->desc->id; + int id = rdev_get_id(rdev); int reg, ret, val = 0; switch (id) { @@ -190,11 +191,11 @@ static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode) switch (mode) { case REGULATOR_MODE_STANDBY: - if (rdev->desc->id > ACT8945A_ID_DCDC3) + if (id > ACT8945A_ID_DCDC3) val = BIT(5); break; case REGULATOR_MODE_NORMAL: - if (rdev->desc->id <= ACT8945A_ID_DCDC3) + if (id <= ACT8945A_ID_DCDC3) val = BIT(5); break; default: @@ -213,7 +214,7 @@ static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode) static unsigned int act8945a_get_mode(struct regulator_dev *rdev) { struct act8945a_pmic *act8945a = rdev_get_drvdata(rdev); - int id = rdev->desc->id; + int id = rdev_get_id(rdev); if (id < ACT8945A_ID_DCDC1 || id >= ACT8945A_ID_MAX) return -EINVAL; diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index b9a93049e41e..bf3ab405eed1 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -40,35 +40,10 @@ struct arizona_ldo1 { struct gpio_desc *ena_gpiod; }; -static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev, - unsigned int selector) -{ - if (selector >= rdev->desc->n_voltages) - return -EINVAL; - - if (selector == rdev->desc->n_voltages - 1) - return 1800000; - else - return rdev->desc->min_uV + (rdev->desc->uV_step * selector); -} - -static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - int sel; - - sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); - if (sel >= rdev->desc->n_voltages) - sel = rdev->desc->n_voltages - 1; - - return sel; -} - static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev, unsigned sel) { - struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); - struct regmap *regmap = ldo->regmap; + struct regmap *regmap = rdev_get_regmap(rdev); unsigned int val; int ret; @@ -85,16 +60,12 @@ static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev, if (val) return 0; - val = sel << ARIZONA_LDO1_VSEL_SHIFT; - - return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1, - ARIZONA_LDO1_VSEL_MASK, val); + return regulator_set_voltage_sel_regmap(rdev, sel); } static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev) { - struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); - struct regmap *regmap = ldo->regmap; + struct regmap *regmap = rdev_get_regmap(rdev); unsigned int val; int ret; @@ -105,32 +76,35 @@ static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev) if (val & ARIZONA_LDO1_HI_PWR) return rdev->desc->n_voltages - 1; - ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val); - if (ret != 0) - return ret; - - return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT; + return regulator_get_voltage_sel_regmap(rdev); } static const struct regulator_ops arizona_ldo1_hc_ops = { - .list_voltage = arizona_ldo1_hc_list_voltage, - .map_voltage = arizona_ldo1_hc_map_voltage, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = arizona_ldo1_hc_get_voltage_sel, .set_voltage_sel = arizona_ldo1_hc_set_voltage_sel, .get_bypass = regulator_get_bypass_regmap, .set_bypass = regulator_set_bypass_regmap, }; +static const struct regulator_linear_range arizona_ldo1_hc_ranges[] = { + REGULATOR_LINEAR_RANGE(900000, 0, 0x6, 50000), + REGULATOR_LINEAR_RANGE(1800000, 0x7, 0x7, 0), +}; + static const struct regulator_desc arizona_ldo1_hc = { .name = "LDO1", .supply_name = "LDOVDD", .type = REGULATOR_VOLTAGE, .ops = &arizona_ldo1_hc_ops, + .vsel_reg = ARIZONA_LDO1_CONTROL_1, + .vsel_mask = ARIZONA_LDO1_VSEL_MASK, .bypass_reg = ARIZONA_LDO1_CONTROL_1, .bypass_mask = ARIZONA_LDO1_BYPASS, - .min_uV = 900000, - .uV_step = 50000, + .linear_ranges = arizona_ldo1_hc_ranges, + .n_linear_ranges = ARRAY_SIZE(arizona_ldo1_hc_ranges), .n_voltages = 8, .enable_time = 1500, .ramp_delay = 24000, diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c index 66337e12719b..e5fed289b52d 100644 --- a/drivers/regulator/as3722-regulator.c +++ b/drivers/regulator/as3722-regulator.c @@ -886,7 +886,7 @@ static int as3722_regulator_probe(struct platform_device *pdev) as3722_regs->desc[id].min_uV = 410000; } else { as3722_regs->desc[id].n_voltages = - AS3722_SD0_VSEL_MAX + 1, + AS3722_SD0_VSEL_MAX + 1; as3722_regs->desc[id].min_uV = 610000; } as3722_regs->desc[id].uV_step = 10000; diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 48af859fd053..fba8f58ab769 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -367,13 +367,12 @@ static const int axp209_dcdc2_ldo3_slew_rates[] = { static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp) { struct axp20x_dev *axp20x = rdev_get_drvdata(rdev); - const struct regulator_desc *desc = rdev->desc; + const struct regulator_desc *desc; u8 reg, mask, enable, cfg = 0xff; const int *slew_rates; int rate_count = 0; - if (!rdev) - return -EINVAL; + desc = rdev->desc; switch (axp20x->variant) { case AXP209_ID: @@ -436,11 +435,13 @@ static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp) static int axp20x_regulator_enable_regmap(struct regulator_dev *rdev) { struct axp20x_dev *axp20x = rdev_get_drvdata(rdev); - const struct regulator_desc *desc = rdev->desc; + const struct regulator_desc *desc; if (!rdev) return -EINVAL; + desc = rdev->desc; + switch (axp20x->variant) { case AXP209_ID: if ((desc->id == AXP20X_LDO3) && @@ -573,7 +574,7 @@ static const struct regulator_desc axp22x_regulators[] = { AXP22X_DCDC3_V_OUT, AXP22X_DCDC3_V_OUT_MASK, AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC3_MASK), AXP_DESC(AXP22X, DCDC4, "dcdc4", "vin4", 600, 1540, 20, - AXP22X_DCDC4_V_OUT, AXP22X_DCDC4_V_OUT, + AXP22X_DCDC4_V_OUT, AXP22X_DCDC4_V_OUT_MASK, AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC4_MASK), AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50, AXP22X_DCDC5_V_OUT, AXP22X_DCDC5_V_OUT_MASK, @@ -719,7 +720,7 @@ static const struct regulator_desc axp803_regulators[] = { AXP22X_ALDO1_V_OUT, AXP22X_ALDO1_V_OUT_MASK, AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO1_MASK), AXP_DESC(AXP803, ALDO2, "aldo2", "aldoin", 700, 3300, 100, - AXP22X_ALDO2_V_OUT, AXP22X_ALDO2_V_OUT, + AXP22X_ALDO2_V_OUT, AXP22X_ALDO2_V_OUT_MASK, AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO2_MASK), AXP_DESC(AXP803, ALDO3, "aldo3", "aldoin", 700, 3300, 100, AXP22X_ALDO3_V_OUT, AXP22X_ALDO3_V_OUT_MASK, @@ -729,7 +730,7 @@ static const struct regulator_desc axp803_regulators[] = { AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO1_MASK), AXP_DESC_RANGES(AXP803, DLDO2, "dldo2", "dldoin", axp803_dldo2_ranges, AXP803_DLDO2_NUM_VOLTAGES, - AXP22X_DLDO2_V_OUT, AXP22X_DLDO2_V_OUT, + AXP22X_DLDO2_V_OUT, AXP22X_DLDO2_V_OUT_MASK, AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO2_MASK), AXP_DESC(AXP803, DLDO3, "dldo3", "dldoin", 700, 3300, 100, AXP22X_DLDO3_V_OUT, AXP22X_DLDO3_V_OUT_MASK, @@ -744,7 +745,7 @@ static const struct regulator_desc axp803_regulators[] = { AXP22X_ELDO2_V_OUT, AXP22X_ELDO2_V_OUT_MASK, AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO2_MASK), AXP_DESC(AXP803, ELDO3, "eldo3", "eldoin", 700, 1900, 50, - AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT, + AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT_MASK, AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO3_MASK), AXP_DESC(AXP803, FLDO1, "fldo1", "fldoin", 700, 1450, 50, AXP803_FLDO1_V_OUT, AXP803_FLDO1_V_OUT_MASK, @@ -791,7 +792,7 @@ static const struct regulator_desc axp806_regulators[] = { AXP806_DCDCA_V_CTRL, AXP806_DCDCA_V_CTRL_MASK, AXP806_PWR_OUT_CTRL1, AXP806_PWR_OUT_DCDCA_MASK), AXP_DESC(AXP806, DCDCB, "dcdcb", "vinb", 1000, 2550, 50, - AXP806_DCDCB_V_CTRL, AXP806_DCDCB_V_CTRL, + AXP806_DCDCB_V_CTRL, AXP806_DCDCB_V_CTRL_MASK, AXP806_PWR_OUT_CTRL1, AXP806_PWR_OUT_DCDCB_MASK), AXP_DESC_RANGES(AXP806, DCDCC, "dcdcc", "vinc", axp806_dcdca_ranges, AXP806_DCDCA_NUM_VOLTAGES, @@ -817,7 +818,7 @@ static const struct regulator_desc axp806_regulators[] = { AXP806_BLDO1_V_CTRL, AXP806_BLDO1_V_CTRL_MASK, AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_BLDO1_MASK), AXP_DESC(AXP806, BLDO2, "bldo2", "bldoin", 700, 1900, 100, - AXP806_BLDO2_V_CTRL, AXP806_BLDO2_V_CTRL, + AXP806_BLDO2_V_CTRL, AXP806_BLDO2_V_CTRL_MASK, AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_BLDO2_MASK), AXP_DESC(AXP806, BLDO3, "bldo3", "bldoin", 700, 1900, 100, AXP806_BLDO3_V_CTRL, AXP806_BLDO3_V_CTRL_MASK, @@ -952,7 +953,7 @@ static const struct regulator_desc axp813_regulators[] = { AXP22X_ALDO1_V_OUT, AXP22X_ALDO1_V_OUT_MASK, AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO1_MASK), AXP_DESC(AXP813, ALDO2, "aldo2", "aldoin", 700, 3300, 100, - AXP22X_ALDO2_V_OUT, AXP22X_ALDO2_V_OUT, + AXP22X_ALDO2_V_OUT, AXP22X_ALDO2_V_OUT_MASK, AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO2_MASK), AXP_DESC(AXP813, ALDO3, "aldo3", "aldoin", 700, 3300, 100, AXP22X_ALDO3_V_OUT, AXP22X_ALDO3_V_OUT_MASK, @@ -962,7 +963,7 @@ static const struct regulator_desc axp813_regulators[] = { AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO1_MASK), AXP_DESC_RANGES(AXP813, DLDO2, "dldo2", "dldoin", axp803_dldo2_ranges, AXP803_DLDO2_NUM_VOLTAGES, - AXP22X_DLDO2_V_OUT, AXP22X_DLDO2_V_OUT, + AXP22X_DLDO2_V_OUT, AXP22X_DLDO2_V_OUT_MASK, AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO2_MASK), AXP_DESC(AXP813, DLDO3, "dldo3", "dldoin", 700, 3300, 100, AXP22X_DLDO3_V_OUT, AXP22X_DLDO3_V_OUT_MASK, @@ -977,7 +978,7 @@ static const struct regulator_desc axp813_regulators[] = { AXP22X_ELDO2_V_OUT, AXP22X_ELDO2_V_OUT_MASK, AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO2_MASK), AXP_DESC(AXP813, ELDO3, "eldo3", "eldoin", 700, 1900, 50, - AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT, + AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT_MASK, AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO3_MASK), /* to do / check ... */ AXP_DESC(AXP813, FLDO1, "fldo1", "fldoin", 700, 1450, 50, diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c index 92d6d7b10cf7..e49c0a7d5dd5 100644 --- a/drivers/regulator/bcm590xx-regulator.c +++ b/drivers/regulator/bcm590xx-regulator.c @@ -242,8 +242,12 @@ static int bcm590xx_get_enable_register(int id) case BCM590XX_REG_SDSR2: reg = BCM590XX_SDSR2PMCTRL1; break; + case BCM590XX_REG_VSR: + reg = BCM590XX_VSRPMCTRL1; + break; case BCM590XX_REG_VBUS: reg = BCM590XX_OTG_CTRL; + break; } diff --git a/drivers/regulator/bd70528-regulator.c b/drivers/regulator/bd70528-regulator.c new file mode 100644 index 000000000000..30e3ed430a8a --- /dev/null +++ b/drivers/regulator/bd70528-regulator.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 ROHM Semiconductors +// bd70528-regulator.c ROHM BD70528MWV regulator driver + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/mfd/rohm-bd70528.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/slab.h> + +#define BUCK_RAMPRATE_250MV 0 +#define BUCK_RAMPRATE_125MV 1 +#define BUCK_RAMP_MAX 250 + +static const struct regulator_linear_range bd70528_buck1_volts[] = { + REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 600000), + REGULATOR_LINEAR_RANGE(2750000, 0x2, 0xf, 50000), +}; +static const struct regulator_linear_range bd70528_buck2_volts[] = { + REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 300000), + REGULATOR_LINEAR_RANGE(1550000, 0x2, 0xd, 50000), + REGULATOR_LINEAR_RANGE(3000000, 0xe, 0xf, 300000), +}; +static const struct regulator_linear_range bd70528_buck3_volts[] = { + REGULATOR_LINEAR_RANGE(800000, 0x00, 0xd, 50000), + REGULATOR_LINEAR_RANGE(1800000, 0xe, 0xf, 0), +}; + +/* All LDOs have same voltage ranges */ +static const struct regulator_linear_range bd70528_ldo_volts[] = { + REGULATOR_LINEAR_RANGE(1650000, 0x0, 0x07, 50000), + REGULATOR_LINEAR_RANGE(2100000, 0x8, 0x0f, 100000), + REGULATOR_LINEAR_RANGE(2850000, 0x10, 0x19, 50000), + REGULATOR_LINEAR_RANGE(3300000, 0x19, 0x1f, 0), +}; + +/* Also both LEDs support same voltages */ +static const unsigned int led_volts[] = { + 20000, 30000 +}; + +static int bd70528_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + if (ramp_delay > 0 && ramp_delay <= BUCK_RAMP_MAX) { + unsigned int ramp_value = BUCK_RAMPRATE_250MV; + + if (ramp_delay <= 125) + ramp_value = BUCK_RAMPRATE_125MV; + + return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, + BD70528_MASK_BUCK_RAMP, + ramp_value << BD70528_SIFT_BUCK_RAMP); + } + dev_err(&rdev->dev, "%s: ramp_delay: %d not supported\n", + rdev->desc->name, ramp_delay); + return -EINVAL; +} + +static int bd70528_led_set_voltage_sel(struct regulator_dev *rdev, + unsigned int sel) +{ + int ret; + + ret = regulator_is_enabled_regmap(rdev); + if (ret < 0) + return ret; + + if (ret == 0) + return regulator_set_voltage_sel_regmap(rdev, sel); + + dev_err(&rdev->dev, + "LED voltage change not allowed when led is enabled\n"); + + return -EBUSY; +} + +static const struct regulator_ops bd70528_buck_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = bd70528_set_ramp_delay, +}; + +static const struct regulator_ops bd70528_ldo_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = bd70528_set_ramp_delay, +}; + +static const struct regulator_ops bd70528_led_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_table, + .set_voltage_sel = bd70528_led_set_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static const struct regulator_desc bd70528_desc[] = { + { + .name = "buck1", + .of_match = of_match_ptr("BUCK1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_BUCK1, + .ops = &bd70528_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd70528_buck1_volts, + .n_linear_ranges = ARRAY_SIZE(bd70528_buck1_volts), + .n_voltages = BD70528_BUCK_VOLTS, + .enable_reg = BD70528_REG_BUCK1_EN, + .enable_mask = BD70528_MASK_RUN_EN, + .vsel_reg = BD70528_REG_BUCK1_VOLT, + .vsel_mask = BD70528_MASK_BUCK_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "buck2", + .of_match = of_match_ptr("BUCK2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_BUCK2, + .ops = &bd70528_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd70528_buck2_volts, + .n_linear_ranges = ARRAY_SIZE(bd70528_buck2_volts), + .n_voltages = BD70528_BUCK_VOLTS, + .enable_reg = BD70528_REG_BUCK2_EN, + .enable_mask = BD70528_MASK_RUN_EN, + .vsel_reg = BD70528_REG_BUCK2_VOLT, + .vsel_mask = BD70528_MASK_BUCK_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "buck3", + .of_match = of_match_ptr("BUCK3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_BUCK3, + .ops = &bd70528_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd70528_buck3_volts, + .n_linear_ranges = ARRAY_SIZE(bd70528_buck3_volts), + .n_voltages = BD70528_BUCK_VOLTS, + .enable_reg = BD70528_REG_BUCK3_EN, + .enable_mask = BD70528_MASK_RUN_EN, + .vsel_reg = BD70528_REG_BUCK3_VOLT, + .vsel_mask = BD70528_MASK_BUCK_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "ldo1", + .of_match = of_match_ptr("LDO1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_LDO1, + .ops = &bd70528_ldo_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd70528_ldo_volts, + .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts), + .n_voltages = BD70528_LDO_VOLTS, + .enable_reg = BD70528_REG_LDO1_EN, + .enable_mask = BD70528_MASK_RUN_EN, + .vsel_reg = BD70528_REG_LDO1_VOLT, + .vsel_mask = BD70528_MASK_LDO_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "ldo2", + .of_match = of_match_ptr("LDO2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_LDO2, + .ops = &bd70528_ldo_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd70528_ldo_volts, + .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts), + .n_voltages = BD70528_LDO_VOLTS, + .enable_reg = BD70528_REG_LDO2_EN, + .enable_mask = BD70528_MASK_RUN_EN, + .vsel_reg = BD70528_REG_LDO2_VOLT, + .vsel_mask = BD70528_MASK_LDO_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "ldo3", + .of_match = of_match_ptr("LDO3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_LDO3, + .ops = &bd70528_ldo_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd70528_ldo_volts, + .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts), + .n_voltages = BD70528_LDO_VOLTS, + .enable_reg = BD70528_REG_LDO3_EN, + .enable_mask = BD70528_MASK_RUN_EN, + .vsel_reg = BD70528_REG_LDO3_VOLT, + .vsel_mask = BD70528_MASK_LDO_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "ldo_led1", + .of_match = of_match_ptr("LDO_LED1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_LED1, + .ops = &bd70528_led_ops, + .type = REGULATOR_VOLTAGE, + .volt_table = &led_volts[0], + .n_voltages = ARRAY_SIZE(led_volts), + .enable_reg = BD70528_REG_LED_EN, + .enable_mask = BD70528_MASK_LED1_EN, + .vsel_reg = BD70528_REG_LED_VOLT, + .vsel_mask = BD70528_MASK_LED1_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "ldo_led2", + .of_match = of_match_ptr("LDO_LED2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_LED2, + .ops = &bd70528_led_ops, + .type = REGULATOR_VOLTAGE, + .volt_table = &led_volts[0], + .n_voltages = ARRAY_SIZE(led_volts), + .enable_reg = BD70528_REG_LED_EN, + .enable_mask = BD70528_MASK_LED2_EN, + .vsel_reg = BD70528_REG_LED_VOLT, + .vsel_mask = BD70528_MASK_LED2_VOLT, + .owner = THIS_MODULE, + }, + +}; + +static int bd70528_probe(struct platform_device *pdev) +{ + struct rohm_regmap_dev *bd70528; + int i; + struct regulator_config config = { + .dev = pdev->dev.parent, + }; + + bd70528 = dev_get_drvdata(pdev->dev.parent); + if (!bd70528) { + dev_err(&pdev->dev, "No MFD driver data\n"); + return -EINVAL; + } + + config.regmap = bd70528->regmap; + + for (i = 0; i < ARRAY_SIZE(bd70528_desc); i++) { + struct regulator_dev *rdev; + + rdev = devm_regulator_register(&pdev->dev, &bd70528_desc[i], + &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, + "failed to register %s regulator\n", + bd70528_desc[i].name); + return PTR_ERR(rdev); + } + } + return 0; +} + +static struct platform_driver bd70528_regulator = { + .driver = { + .name = "bd70528-pmic" + }, + .probe = bd70528_probe, +}; + +module_platform_driver(bd70528_regulator); + +MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); +MODULE_DESCRIPTION("BD70528 voltage regulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c index b8dcdc21dc22..b2191be49670 100644 --- a/drivers/regulator/bd718x7-regulator.c +++ b/drivers/regulator/bd718x7-regulator.c @@ -79,7 +79,7 @@ static int bd718xx_set_voltage_sel_pickable_restricted( return regulator_set_voltage_sel_pickable_regmap(rdev, sel); } -static struct regulator_ops bd718xx_pickable_range_ldo_ops = { +static const struct regulator_ops bd718xx_pickable_range_ldo_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -88,7 +88,7 @@ static struct regulator_ops bd718xx_pickable_range_ldo_ops = { .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, }; -static struct regulator_ops bd718xx_pickable_range_buck_ops = { +static const struct regulator_ops bd718xx_pickable_range_buck_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -98,7 +98,7 @@ static struct regulator_ops bd718xx_pickable_range_buck_ops = { .set_voltage_time_sel = regulator_set_voltage_time_sel, }; -static struct regulator_ops bd718xx_ldo_regulator_ops = { +static const struct regulator_ops bd718xx_ldo_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -107,7 +107,7 @@ static struct regulator_ops bd718xx_ldo_regulator_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, }; -static struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = { +static const struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -116,7 +116,7 @@ static struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, }; -static struct regulator_ops bd718xx_buck_regulator_ops = { +static const struct regulator_ops bd718xx_buck_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -126,7 +126,7 @@ static struct regulator_ops bd718xx_buck_regulator_ops = { .set_voltage_time_sel = regulator_set_voltage_time_sel, }; -static struct regulator_ops bd718xx_buck_regulator_nolinear_ops = { +static const struct regulator_ops bd718xx_buck_regulator_nolinear_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -137,7 +137,7 @@ static struct regulator_ops bd718xx_buck_regulator_nolinear_ops = { .set_voltage_time_sel = regulator_set_voltage_time_sel, }; -static struct regulator_ops bd718xx_dvs_buck_regulator_ops = { +static const struct regulator_ops bd718xx_dvs_buck_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -350,6 +350,135 @@ static const struct reg_init bd71837_ldo6_inits[] = { }, }; +#define NUM_DVS_BUCKS 4 + +struct of_dvs_setting { + const char *prop; + unsigned int reg; +}; + +static int set_dvs_levels(const struct of_dvs_setting *dvs, + struct device_node *np, + const struct regulator_desc *desc, + struct regmap *regmap) +{ + int ret, i; + unsigned int uv; + + ret = of_property_read_u32(np, dvs->prop, &uv); + if (ret) { + if (ret != -EINVAL) + return ret; + return 0; + } + + for (i = 0; i < desc->n_voltages; i++) { + ret = regulator_desc_list_voltage_linear_range(desc, i); + if (ret < 0) + continue; + if (ret == uv) { + i <<= ffs(desc->vsel_mask) - 1; + ret = regmap_update_bits(regmap, dvs->reg, + DVS_BUCK_RUN_MASK, i); + break; + } + } + return ret; +} + +static int buck4_set_hw_dvs_levels(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + int ret, i; + const struct of_dvs_setting dvs[] = { + { + .prop = "rohm,dvs-run-voltage", + .reg = BD71837_REG_BUCK4_VOLT_RUN, + }, + }; + + for (i = 0; i < ARRAY_SIZE(dvs); i++) { + ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap); + if (ret) + break; + } + return ret; +} +static int buck3_set_hw_dvs_levels(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + int ret, i; + const struct of_dvs_setting dvs[] = { + { + .prop = "rohm,dvs-run-voltage", + .reg = BD71837_REG_BUCK3_VOLT_RUN, + }, + }; + + for (i = 0; i < ARRAY_SIZE(dvs); i++) { + ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap); + if (ret) + break; + } + return ret; +} + +static int buck2_set_hw_dvs_levels(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + int ret, i; + const struct of_dvs_setting dvs[] = { + { + .prop = "rohm,dvs-run-voltage", + .reg = BD718XX_REG_BUCK2_VOLT_RUN, + }, + { + .prop = "rohm,dvs-idle-voltage", + .reg = BD718XX_REG_BUCK2_VOLT_IDLE, + }, + }; + + + + for (i = 0; i < ARRAY_SIZE(dvs); i++) { + ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap); + if (ret) + break; + } + return ret; +} + +static int buck1_set_hw_dvs_levels(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + int ret, i; + const struct of_dvs_setting dvs[] = { + { + .prop = "rohm,dvs-run-voltage", + .reg = BD718XX_REG_BUCK1_VOLT_RUN, + }, + { + .prop = "rohm,dvs-idle-voltage", + .reg = BD718XX_REG_BUCK1_VOLT_IDLE, + }, + { + .prop = "rohm,dvs-suspend-voltage", + .reg = BD718XX_REG_BUCK1_VOLT_SUSP, + }, + }; + + for (i = 0; i < ARRAY_SIZE(dvs); i++) { + ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap); + if (ret) + break; + } + return ret; +} + static const struct bd718xx_regulator_data bd71847_regulators[] = { { .desc = { @@ -368,6 +497,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .enable_reg = BD718XX_REG_BUCK1_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, + .of_parse_cb = buck1_set_hw_dvs_levels, }, .init = { .reg = BD718XX_REG_BUCK1_CTRL, @@ -391,6 +521,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .enable_reg = BD718XX_REG_BUCK2_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, + .of_parse_cb = buck2_set_hw_dvs_levels, }, .init = { .reg = BD718XX_REG_BUCK2_CTRL, @@ -662,6 +793,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .enable_reg = BD718XX_REG_BUCK1_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, + .of_parse_cb = buck1_set_hw_dvs_levels, }, .init = { .reg = BD718XX_REG_BUCK1_CTRL, @@ -685,6 +817,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .enable_reg = BD718XX_REG_BUCK2_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, + .of_parse_cb = buck2_set_hw_dvs_levels, }, .init = { .reg = BD718XX_REG_BUCK2_CTRL, @@ -708,6 +841,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .enable_reg = BD71837_REG_BUCK3_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, + .of_parse_cb = buck3_set_hw_dvs_levels, }, .init = { .reg = BD71837_REG_BUCK3_CTRL, @@ -731,6 +865,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .enable_reg = BD71837_REG_BUCK4_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, + .of_parse_cb = buck4_set_hw_dvs_levels, }, .init = { .reg = BD71837_REG_BUCK4_CTRL, @@ -1029,6 +1164,7 @@ static int bd718xx_probe(struct platform_device *pdev) }; int i, j, err; + bool use_snvs; mfd = dev_get_drvdata(pdev->dev.parent); if (!mfd) { @@ -1055,27 +1191,28 @@ static int bd718xx_probe(struct platform_device *pdev) BD718XX_REG_REGLOCK); } - /* At poweroff transition PMIC HW disables EN bit for regulators but - * leaves SEL bit untouched. So if state transition from POWEROFF - * is done to SNVS - then all power rails controlled by SW (having - * SEL bit set) stay disabled as EN is cleared. This may result boot - * failure if any crucial systems are powered by these rails. - * + use_snvs = of_property_read_bool(pdev->dev.parent->of_node, + "rohm,reset-snvs-powered"); + + /* * Change the next stage from poweroff to be READY instead of SNVS * for all reset types because OTP loading at READY will clear SEL * bit allowing HW defaults for power rails to be used */ - err = regmap_update_bits(mfd->regmap, BD718XX_REG_TRANS_COND1, - BD718XX_ON_REQ_POWEROFF_MASK | - BD718XX_SWRESET_POWEROFF_MASK | - BD718XX_WDOG_POWEROFF_MASK | - BD718XX_KEY_L_POWEROFF_MASK, - BD718XX_POWOFF_TO_RDY); - if (err) { - dev_err(&pdev->dev, "Failed to change reset target\n"); - goto err; - } else { - dev_dbg(&pdev->dev, "Changed all resets from SVNS to READY\n"); + if (!use_snvs) { + err = regmap_update_bits(mfd->regmap, BD718XX_REG_TRANS_COND1, + BD718XX_ON_REQ_POWEROFF_MASK | + BD718XX_SWRESET_POWEROFF_MASK | + BD718XX_WDOG_POWEROFF_MASK | + BD718XX_KEY_L_POWEROFF_MASK, + BD718XX_POWOFF_TO_RDY); + if (err) { + dev_err(&pdev->dev, "Failed to change reset target\n"); + goto err; + } else { + dev_dbg(&pdev->dev, + "Changed all resets from SVNS to READY\n"); + } } for (i = 0; i < pmic_regulators[mfd->chip_type].r_amount; i++) { @@ -1098,19 +1235,33 @@ static int bd718xx_probe(struct platform_device *pdev) err = PTR_ERR(rdev); goto err; } - /* Regulator register gets the regulator constraints and + + /* + * Regulator register gets the regulator constraints and * applies them (set_machine_constraints). This should have * turned the control register(s) to correct values and we * can now switch the control from PMIC state machine to the * register interface + * + * At poweroff transition PMIC HW disables EN bit for + * regulators but leaves SEL bit untouched. So if state + * transition from POWEROFF is done to SNVS - then all power + * rails controlled by SW (having SEL bit set) stay disabled + * as EN is cleared. This will result boot failure if any + * crucial systems are powered by these rails. We don't + * enable SW control for crucial regulators if snvs state is + * used */ - err = regmap_update_bits(mfd->regmap, r->init.reg, - r->init.mask, r->init.val); - if (err) { - dev_err(&pdev->dev, - "Failed to write BUCK/LDO SEL bit for (%s)\n", - desc->name); - goto err; + if (!use_snvs || !rdev->constraints->always_on || + !rdev->constraints->boot_on) { + err = regmap_update_bits(mfd->regmap, r->init.reg, + r->init.mask, r->init.val); + if (err) { + dev_err(&pdev->dev, + "Failed to take control for (%s)\n", + desc->name); + goto err; + } } for (j = 0; j < r->additional_init_amnt; j++) { err = regmap_update_bits(mfd->regmap, diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c index e12dd1f750f3..e690c2ce5b3c 100644 --- a/drivers/regulator/bd9571mwv-regulator.c +++ b/drivers/regulator/bd9571mwv-regulator.c @@ -100,7 +100,7 @@ static int bd9571mwv_reg_set_voltage_sel_regmap(struct regulator_dev *rdev, } /* Operations permitted on AVS voltage regulator */ -static struct regulator_ops avs_ops = { +static const struct regulator_ops avs_ops = { .set_voltage_sel = bd9571mwv_avs_set_voltage_sel_regmap, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = bd9571mwv_avs_get_voltage_sel_regmap, @@ -108,7 +108,7 @@ static struct regulator_ops avs_ops = { }; /* Operations permitted on voltage regulators */ -static struct regulator_ops reg_ops = { +static const struct regulator_ops reg_ops = { .set_voltage_sel = bd9571mwv_reg_set_voltage_sel_regmap, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -116,13 +116,13 @@ static struct regulator_ops reg_ops = { }; /* Operations permitted on voltage monitors */ -static struct regulator_ops vid_ops = { +static const struct regulator_ops vid_ops = { .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear, }; -static struct regulator_desc regulators[] = { +static const struct regulator_desc regulators[] = { BD9571MWV_REG("VD09", "vd09", VD09, avs_ops, 0, 0x7f, 0x80, 600000, 10000, 0x3c), BD9571MWV_REG("VD18", "vd18", VD18, vid_ops, BD9571MWV_VD18_VID, 0xf, diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index b9d7b45c7295..68473d0cc57e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -23,7 +23,6 @@ #include <linux/mutex.h> #include <linux/suspend.h> #include <linux/delay.h> -#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/of.h> #include <linux/regmap.h> @@ -82,7 +81,6 @@ struct regulator_enable_gpio { struct gpio_desc *gpiod; u32 enable_count; /* a number of enabled shared GPIO */ u32 request_count; /* a number of requested shared GPIO */ - unsigned int ena_gpio_invert:1; }; /* @@ -145,14 +143,6 @@ static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops) return false; } -static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev) -{ - if (rdev && rdev->supply) - return rdev->supply->rdev; - - return NULL; -} - /** * regulator_lock_nested - lock a single regulator * @rdev: regulator source @@ -326,7 +316,7 @@ err_unlock: * @rdev: regulator source * @ww_ctx: w/w mutex acquire context * - * Unlock all regulators related with rdev by coupling or suppling. + * Unlock all regulators related with rdev by coupling or supplying. */ static void regulator_unlock_dependent(struct regulator_dev *rdev, struct ww_acquire_ctx *ww_ctx) @@ -341,7 +331,7 @@ static void regulator_unlock_dependent(struct regulator_dev *rdev, * @ww_ctx: w/w mutex acquire context * * This function as a wrapper on regulator_lock_recursive(), which locks - * all regulators related with rdev by coupling or suppling. + * all regulators related with rdev by coupling or supplying. */ static void regulator_lock_dependent(struct regulator_dev *rdev, struct ww_acquire_ctx *ww_ctx) @@ -924,14 +914,14 @@ static int drms_uA_update(struct regulator_dev *rdev) int current_uA = 0, output_uV, input_uV, err; unsigned int mode; - lockdep_assert_held_once(&rdev->mutex.base); - /* * first check to see if we can set modes at all, otherwise just * tell the consumer everything is OK. */ - if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) + if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) { + rdev_dbg(rdev, "DRMS operation not allowed\n"); return 0; + } if (!rdev->desc->ops->get_optimum_mode && !rdev->desc->ops->set_load) @@ -1003,7 +993,7 @@ static int suspend_set_state(struct regulator_dev *rdev, if (rstate == NULL) return 0; - /* If we have no suspend mode configration don't set anything; + /* If we have no suspend mode configuration don't set anything; * only warn if the driver implements set_suspend_voltage or * set_suspend_mode callback. */ @@ -1131,7 +1121,7 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, int current_uV = _regulator_get_voltage(rdev); if (current_uV == -ENOTRECOVERABLE) { - /* This regulator can't be read and must be initted */ + /* This regulator can't be read and must be initialized */ rdev_info(rdev, "Setting %d-%duV\n", rdev->constraints->min_uV, rdev->constraints->max_uV); @@ -1349,7 +1339,9 @@ static int set_machine_constraints(struct regulator_dev *rdev, * We'll only apply the initial system load if an * initial mode wasn't specified. */ + regulator_lock(rdev); drms_uA_update(rdev); + regulator_unlock(rdev); } if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) @@ -1780,7 +1772,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) struct device *dev = rdev->dev.parent; int ret; - /* No supply to resovle? */ + /* No supply to resolve? */ if (!rdev->supply_name) return 0; @@ -2058,15 +2050,7 @@ static void _regulator_put(struct regulator *regulator) debugfs_remove_recursive(regulator->debugfs); if (regulator->dev) { - int count = 0; - struct regulator *r; - - list_for_each_entry(r, &rdev->consumer_list, list) - if (r->dev == regulator->dev) - count++; - - if (count == 1) - device_link_remove(regulator->dev, &rdev->dev); + device_link_remove(regulator->dev, &rdev->dev); /* remove any sysfs entries */ sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); @@ -2237,38 +2221,21 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev, { struct regulator_enable_gpio *pin; struct gpio_desc *gpiod; - int ret; - if (config->ena_gpiod) - gpiod = config->ena_gpiod; - else - gpiod = gpio_to_desc(config->ena_gpio); + gpiod = config->ena_gpiod; list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { if (pin->gpiod == gpiod) { - rdev_dbg(rdev, "GPIO %d is already used\n", - config->ena_gpio); + rdev_dbg(rdev, "GPIO is already used\n"); goto update_ena_gpio_to_rdev; } } - if (!config->ena_gpiod) { - ret = gpio_request_one(config->ena_gpio, - GPIOF_DIR_OUT | config->ena_gpio_flags, - rdev_get_name(rdev)); - if (ret) - return ret; - } - pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); - if (pin == NULL) { - if (!config->ena_gpiod) - gpio_free(config->ena_gpio); + if (pin == NULL) return -ENOMEM; - } pin->gpiod = gpiod; - pin->ena_gpio_invert = config->ena_gpio_invert; list_add(&pin->list, ®ulator_ena_gpio_list); update_ena_gpio_to_rdev: @@ -2289,7 +2256,6 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev) if (pin->gpiod == rdev->ena_pin->gpiod) { if (pin->request_count <= 1) { pin->request_count = 0; - gpiod_put(pin->gpiod); list_del(&pin->list); kfree(pin); rdev->ena_pin = NULL; @@ -2319,8 +2285,7 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) if (enable) { /* Enable GPIO at initial use */ if (pin->enable_count == 0) - gpiod_set_value_cansleep(pin->gpiod, - !pin->ena_gpio_invert); + gpiod_set_value_cansleep(pin->gpiod, 1); pin->enable_count++; } else { @@ -2331,8 +2296,7 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) /* Disable GPIO if not used */ if (pin->enable_count <= 1) { - gpiod_set_value_cansleep(pin->gpiod, - pin->ena_gpio_invert); + gpiod_set_value_cansleep(pin->gpiod, 0); pin->enable_count = 0; } } @@ -2409,7 +2373,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev) * timer wrapping. * in case of multiple timer wrapping, either it can be * detected by out-of-range remaining, or it cannot be - * detected and we gets a panelty of + * detected and we get a penalty of * _regulator_enable_delay(). */ remaining = intended - start_jiffy; @@ -2809,7 +2773,7 @@ static void regulator_disable_work(struct work_struct *work) /** * regulator_disable_deferred - disable regulator output with delay * @regulator: regulator source - * @ms: miliseconds until the regulator is disabled + * @ms: milliseconds until the regulator is disabled * * Execute regulator_disable() on the regulator after a delay. This * is intended for use with devices that require some time to quiesce. @@ -4943,7 +4907,7 @@ regulator_register(const struct regulator_desc *regulator_desc, * device tree until we have handled it over to the core. If the * config that was passed in to this function DOES NOT contain * a descriptor, and the config after this call DOES contain - * a descriptor, we definately got one from parsing the device + * a descriptor, we definitely got one from parsing the device * tree. */ if (!cfg->ena_gpiod && config->ena_gpiod) @@ -4975,15 +4939,13 @@ regulator_register(const struct regulator_desc *regulator_desc, goto clean; } - if (config->ena_gpiod || - ((config->ena_gpio || config->ena_gpio_initialized) && - gpio_is_valid(config->ena_gpio))) { + if (config->ena_gpiod) { mutex_lock(®ulator_list_mutex); ret = regulator_ena_gpio_request(rdev, config); mutex_unlock(®ulator_list_mutex); if (ret != 0) { - rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", - config->ena_gpio, ret); + rdev_err(rdev, "Failed to request enable GPIO: %d\n", + ret); goto clean; } /* The regulator core took over the GPIO descriptor */ @@ -5251,6 +5213,12 @@ struct device *rdev_get_dev(struct regulator_dev *rdev) } EXPORT_SYMBOL_GPL(rdev_get_dev); +struct regmap *rdev_get_regmap(struct regulator_dev *rdev) +{ + return rdev->regmap; +} +EXPORT_SYMBOL_GPL(rdev_get_regmap); + void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) { return reg_init_data->driver_data; diff --git a/drivers/regulator/cpcap-regulator.c b/drivers/regulator/cpcap-regulator.c index 2131457937b7..e7dab5c4d1d1 100644 --- a/drivers/regulator/cpcap-regulator.c +++ b/drivers/regulator/cpcap-regulator.c @@ -100,12 +100,11 @@ struct cpcap_regulator { struct regulator_desc rdesc; const u16 assign_reg; const u16 assign_mask; - const u16 vsel_shift; }; #define CPCAP_REG(_ID, reg, assignment_reg, assignment_mask, val_tbl, \ - mode_mask, volt_mask, volt_shft, \ - mode_val, off_val, volt_trans_time) { \ + mode_mask, volt_mask, mode_val, off_val, \ + volt_trans_time) { \ .rdesc = { \ .name = #_ID, \ .of_match = of_match_ptr(#_ID), \ @@ -127,7 +126,6 @@ struct cpcap_regulator { }, \ .assign_reg = (assignment_reg), \ .assign_mask = (assignment_mask), \ - .vsel_shift = (volt_shft), \ } struct cpcap_ddata { @@ -336,155 +334,155 @@ static const unsigned int vaudio_val_tbl[] = { 0, 2775000, }; * SW1 to SW4 and SW6 seems to be unused for mapphone. Note that VSIM and * VSIMCARD have a shared resource assignment bit. */ -static struct cpcap_regulator omap4_regulators[] = { +static const struct cpcap_regulator omap4_regulators[] = { CPCAP_REG(SW1, CPCAP_REG_S1C1, CPCAP_REG_ASSIGN2, CPCAP_BIT_SW1_SEL, unknown_val_tbl, - 0, 0, 0, 0, 0, 0), + 0, 0, 0, 0, 0), CPCAP_REG(SW2, CPCAP_REG_S2C1, CPCAP_REG_ASSIGN2, CPCAP_BIT_SW2_SEL, unknown_val_tbl, - 0, 0, 0, 0, 0, 0), + 0, 0, 0, 0, 0), CPCAP_REG(SW3, CPCAP_REG_S3C, CPCAP_REG_ASSIGN2, CPCAP_BIT_SW3_SEL, unknown_val_tbl, - 0, 0, 0, 0, 0, 0), + 0, 0, 0, 0, 0), CPCAP_REG(SW4, CPCAP_REG_S4C1, CPCAP_REG_ASSIGN2, CPCAP_BIT_SW4_SEL, unknown_val_tbl, - 0, 0, 0, 0, 0, 0), + 0, 0, 0, 0, 0), CPCAP_REG(SW5, CPCAP_REG_S5C, CPCAP_REG_ASSIGN2, CPCAP_BIT_SW5_SEL, sw5_val_tbl, - 0x28, 0, 0, 0x20 | CPCAP_REG_OFF_MODE_SEC, 0, 0), + 0x28, 0, 0x20 | CPCAP_REG_OFF_MODE_SEC, 0, 0), CPCAP_REG(SW6, CPCAP_REG_S6C, CPCAP_REG_ASSIGN2, CPCAP_BIT_SW6_SEL, unknown_val_tbl, - 0, 0, 0, 0, 0, 0), + 0, 0, 0, 0, 0), CPCAP_REG(VCAM, CPCAP_REG_VCAMC, CPCAP_REG_ASSIGN2, CPCAP_BIT_VCAM_SEL, vcam_val_tbl, - 0x87, 0x30, 4, 0x3, 0, 420), + 0x87, 0x30, 0x3, 0, 420), CPCAP_REG(VCSI, CPCAP_REG_VCSIC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VCSI_SEL, vcsi_val_tbl, - 0x47, 0x10, 4, 0x43, 0x41, 350), + 0x47, 0x10, 0x43, 0x41, 350), CPCAP_REG(VDAC, CPCAP_REG_VDACC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VDAC_SEL, vdac_val_tbl, - 0x87, 0x30, 4, 0x3, 0, 420), + 0x87, 0x30, 0x3, 0, 420), CPCAP_REG(VDIG, CPCAP_REG_VDIGC, CPCAP_REG_ASSIGN2, CPCAP_BIT_VDIG_SEL, vdig_val_tbl, - 0x87, 0x30, 4, 0x82, 0, 420), + 0x87, 0x30, 0x82, 0, 420), CPCAP_REG(VFUSE, CPCAP_REG_VFUSEC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VFUSE_SEL, vfuse_val_tbl, - 0x80, 0xf, 0, 0x80, 0, 420), + 0x80, 0xf, 0x80, 0, 420), CPCAP_REG(VHVIO, CPCAP_REG_VHVIOC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VHVIO_SEL, vhvio_val_tbl, - 0x17, 0, 0, 0, 0x12, 0), + 0x17, 0, 0, 0x12, 0), CPCAP_REG(VSDIO, CPCAP_REG_VSDIOC, CPCAP_REG_ASSIGN2, CPCAP_BIT_VSDIO_SEL, vsdio_val_tbl, - 0x87, 0x38, 3, 0x82, 0, 420), + 0x87, 0x38, 0x82, 0, 420), CPCAP_REG(VPLL, CPCAP_REG_VPLLC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VPLL_SEL, vpll_val_tbl, - 0x43, 0x18, 3, 0x2, 0, 420), + 0x43, 0x18, 0x2, 0, 420), CPCAP_REG(VRF1, CPCAP_REG_VRF1C, CPCAP_REG_ASSIGN3, CPCAP_BIT_VRF1_SEL, vrf1_val_tbl, - 0xac, 0x2, 1, 0x4, 0, 10), + 0xac, 0x2, 0x4, 0, 10), CPCAP_REG(VRF2, CPCAP_REG_VRF2C, CPCAP_REG_ASSIGN3, CPCAP_BIT_VRF2_SEL, vrf2_val_tbl, - 0x23, 0x8, 3, 0, 0, 10), + 0x23, 0x8, 0, 0, 10), CPCAP_REG(VRFREF, CPCAP_REG_VRFREFC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VRFREF_SEL, vrfref_val_tbl, - 0x23, 0x8, 3, 0, 0, 420), + 0x23, 0x8, 0, 0, 420), CPCAP_REG(VWLAN1, CPCAP_REG_VWLAN1C, CPCAP_REG_ASSIGN3, CPCAP_BIT_VWLAN1_SEL, vwlan1_val_tbl, - 0x47, 0x10, 4, 0, 0, 420), + 0x47, 0x10, 0, 0, 420), CPCAP_REG(VWLAN2, CPCAP_REG_VWLAN2C, CPCAP_REG_ASSIGN3, CPCAP_BIT_VWLAN2_SEL, vwlan2_val_tbl, - 0x20c, 0xc0, 6, 0x20c, 0, 420), + 0x20c, 0xc0, 0x20c, 0, 420), CPCAP_REG(VSIM, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3, 0xffff, vsim_val_tbl, - 0x23, 0x8, 3, 0x3, 0, 420), + 0x23, 0x8, 0x3, 0, 420), CPCAP_REG(VSIMCARD, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3, 0xffff, vsimcard_val_tbl, - 0x1e80, 0x8, 3, 0x1e00, 0, 420), + 0x1e80, 0x8, 0x1e00, 0, 420), CPCAP_REG(VVIB, CPCAP_REG_VVIBC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VVIB_SEL, vvib_val_tbl, - 0x1, 0xc, 2, 0x1, 0, 500), + 0x1, 0xc, 0x1, 0, 500), CPCAP_REG(VUSB, CPCAP_REG_VUSBC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VUSB_SEL, vusb_val_tbl, - 0x11c, 0x40, 6, 0xc, 0, 0), + 0x11c, 0x40, 0xc, 0, 0), CPCAP_REG(VAUDIO, CPCAP_REG_VAUDIOC, CPCAP_REG_ASSIGN4, CPCAP_BIT_VAUDIO_SEL, vaudio_val_tbl, - 0x16, 0x1, 0, 0x4, 0, 0), + 0x16, 0x1, 0x4, 0, 0), { /* sentinel */ }, }; -static struct cpcap_regulator xoom_regulators[] = { +static const struct cpcap_regulator xoom_regulators[] = { CPCAP_REG(SW1, CPCAP_REG_S1C1, CPCAP_REG_ASSIGN2, CPCAP_BIT_SW1_SEL, unknown_val_tbl, - 0, 0, 0, 0, 0, 0), + 0, 0, 0, 0, 0), CPCAP_REG(SW2, CPCAP_REG_S2C1, CPCAP_REG_ASSIGN2, CPCAP_BIT_SW2_SEL, sw2_sw4_val_tbl, - 0xf00, 0x7f, 0, 0x800, 0, 120), + 0xf00, 0x7f, 0x800, 0, 120), CPCAP_REG(SW3, CPCAP_REG_S3C, CPCAP_REG_ASSIGN2, CPCAP_BIT_SW3_SEL, unknown_val_tbl, - 0, 0, 0, 0, 0, 0), + 0, 0, 0, 0, 0), CPCAP_REG(SW4, CPCAP_REG_S4C1, CPCAP_REG_ASSIGN2, CPCAP_BIT_SW4_SEL, sw2_sw4_val_tbl, - 0xf00, 0x7f, 0, 0x900, 0, 100), + 0xf00, 0x7f, 0x900, 0, 100), CPCAP_REG(SW5, CPCAP_REG_S5C, CPCAP_REG_ASSIGN2, CPCAP_BIT_SW5_SEL, sw5_val_tbl, - 0x2a, 0, 0, 0x22, 0, 0), + 0x2a, 0, 0x22, 0, 0), CPCAP_REG(SW6, CPCAP_REG_S6C, CPCAP_REG_ASSIGN2, CPCAP_BIT_SW6_SEL, unknown_val_tbl, - 0, 0, 0, 0, 0, 0), + 0, 0, 0, 0, 0), CPCAP_REG(VCAM, CPCAP_REG_VCAMC, CPCAP_REG_ASSIGN2, CPCAP_BIT_VCAM_SEL, vcam_val_tbl, - 0x87, 0x30, 4, 0x7, 0, 420), + 0x87, 0x30, 0x7, 0, 420), CPCAP_REG(VCSI, CPCAP_REG_VCSIC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VCSI_SEL, vcsi_val_tbl, - 0x47, 0x10, 4, 0x7, 0, 350), + 0x47, 0x10, 0x7, 0, 350), CPCAP_REG(VDAC, CPCAP_REG_VDACC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VDAC_SEL, vdac_val_tbl, - 0x87, 0x30, 4, 0x3, 0, 420), + 0x87, 0x30, 0x3, 0, 420), CPCAP_REG(VDIG, CPCAP_REG_VDIGC, CPCAP_REG_ASSIGN2, CPCAP_BIT_VDIG_SEL, vdig_val_tbl, - 0x87, 0x30, 4, 0x5, 0, 420), + 0x87, 0x30, 0x5, 0, 420), CPCAP_REG(VFUSE, CPCAP_REG_VFUSEC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VFUSE_SEL, vfuse_val_tbl, - 0x80, 0xf, 0, 0x80, 0, 420), + 0x80, 0xf, 0x80, 0, 420), CPCAP_REG(VHVIO, CPCAP_REG_VHVIOC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VHVIO_SEL, vhvio_val_tbl, - 0x17, 0, 0, 0x2, 0, 0), + 0x17, 0, 0x2, 0, 0), CPCAP_REG(VSDIO, CPCAP_REG_VSDIOC, CPCAP_REG_ASSIGN2, CPCAP_BIT_VSDIO_SEL, vsdio_val_tbl, - 0x87, 0x38, 3, 0x2, 0, 420), + 0x87, 0x38, 0x2, 0, 420), CPCAP_REG(VPLL, CPCAP_REG_VPLLC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VPLL_SEL, vpll_val_tbl, - 0x43, 0x18, 3, 0x1, 0, 420), + 0x43, 0x18, 0x1, 0, 420), CPCAP_REG(VRF1, CPCAP_REG_VRF1C, CPCAP_REG_ASSIGN3, CPCAP_BIT_VRF1_SEL, vrf1_val_tbl, - 0xac, 0x2, 1, 0xc, 0, 10), + 0xac, 0x2, 0xc, 0, 10), CPCAP_REG(VRF2, CPCAP_REG_VRF2C, CPCAP_REG_ASSIGN3, CPCAP_BIT_VRF2_SEL, vrf2_val_tbl, - 0x23, 0x8, 3, 0x3, 0, 10), + 0x23, 0x8, 0x3, 0, 10), CPCAP_REG(VRFREF, CPCAP_REG_VRFREFC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VRFREF_SEL, vrfref_val_tbl, - 0x23, 0x8, 3, 0x3, 0, 420), + 0x23, 0x8, 0x3, 0, 420), CPCAP_REG(VWLAN1, CPCAP_REG_VWLAN1C, CPCAP_REG_ASSIGN3, CPCAP_BIT_VWLAN1_SEL, vwlan1_val_tbl, - 0x47, 0x10, 4, 0x5, 0, 420), + 0x47, 0x10, 0x5, 0, 420), CPCAP_REG(VWLAN2, CPCAP_REG_VWLAN2C, CPCAP_REG_ASSIGN3, CPCAP_BIT_VWLAN2_SEL, vwlan2_val_tbl, - 0x20c, 0xc0, 6, 0x8, 0, 420), + 0x20c, 0xc0, 0x8, 0, 420), CPCAP_REG(VSIM, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3, 0xffff, vsim_val_tbl, - 0x23, 0x8, 3, 0x3, 0, 420), + 0x23, 0x8, 0x3, 0, 420), CPCAP_REG(VSIMCARD, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3, 0xffff, vsimcard_val_tbl, - 0x1e80, 0x8, 3, 0x1e00, 0, 420), + 0x1e80, 0x8, 0x1e00, 0, 420), CPCAP_REG(VVIB, CPCAP_REG_VVIBC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VVIB_SEL, vvib_val_tbl, - 0x1, 0xc, 2, 0, 0x1, 500), + 0x1, 0xc, 0, 0x1, 500), CPCAP_REG(VUSB, CPCAP_REG_VUSBC, CPCAP_REG_ASSIGN3, CPCAP_BIT_VUSB_SEL, vusb_val_tbl, - 0x11c, 0x40, 6, 0xc, 0, 0), + 0x11c, 0x40, 0xc, 0, 0), CPCAP_REG(VAUDIO, CPCAP_REG_VAUDIOC, CPCAP_REG_ASSIGN4, CPCAP_BIT_VAUDIO_SEL, vaudio_val_tbl, - 0x16, 0x1, 0, 0x4, 0, 0), + 0x16, 0x1, 0x4, 0, 0), { /* sentinel */ }, }; diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 207cb3859dcc..cefa3558236d 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -290,10 +290,10 @@ static const struct regulator_ops da9052_ldo_ops = { .disable = regulator_disable_regmap, }; -#define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \ +#define DA9052_LDO(_id, _name, step, min, max, sbits, ebits, abits) \ {\ .reg_desc = {\ - .name = #_id,\ + .name = #_name,\ .ops = &da9052_ldo_ops,\ .type = REGULATOR_VOLTAGE,\ .id = DA9052_ID_##_id,\ @@ -310,10 +310,10 @@ static const struct regulator_ops da9052_ldo_ops = { .activate_bit = (abits),\ } -#define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \ +#define DA9052_DCDC(_id, _name, step, min, max, sbits, ebits, abits) \ {\ .reg_desc = {\ - .name = #_id,\ + .name = #_name,\ .ops = &da9052_dcdc_ops,\ .type = REGULATOR_VOLTAGE,\ .id = DA9052_ID_##_id,\ @@ -331,37 +331,37 @@ static const struct regulator_ops da9052_ldo_ops = { } static struct da9052_regulator_info da9052_regulator_info[] = { - DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), - DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), - DA9052_DCDC(BUCK3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO), - DA9052_DCDC(BUCK4, 50, 1800, 3600, 5, 6, 0), - DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0), - DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), - DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), - DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0), - DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0), - DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0), + DA9052_DCDC(BUCK1, buck1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), + DA9052_DCDC(BUCK2, buck2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), + DA9052_DCDC(BUCK3, buck3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO), + DA9052_DCDC(BUCK4, buck4, 50, 1800, 3600, 5, 6, 0), + DA9052_LDO(LDO1, ldo1, 50, 600, 1800, 5, 6, 0), + DA9052_LDO(LDO2, ldo2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), + DA9052_LDO(LDO3, ldo3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), + DA9052_LDO(LDO4, ldo4, 25, 1725, 3300, 6, 6, 0), + DA9052_LDO(LDO5, ldo5, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO6, ldo6, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO7, ldo7, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO8, ldo8, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO9, ldo9, 50, 1250, 3650, 6, 6, 0), + DA9052_LDO(LDO10, ldo10, 50, 1200, 3600, 6, 6, 0), }; static struct da9052_regulator_info da9053_regulator_info[] = { - DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), - DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), - DA9052_DCDC(BUCK3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO), - DA9052_DCDC(BUCK4, 25, 950, 2525, 6, 6, 0), - DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0), - DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), - DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), - DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0), - DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0), - DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0), + DA9052_DCDC(BUCK1, buck1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), + DA9052_DCDC(BUCK2, buck2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), + DA9052_DCDC(BUCK3, buck3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO), + DA9052_DCDC(BUCK4, buck4, 25, 950, 2525, 6, 6, 0), + DA9052_LDO(LDO1, ldo1, 50, 600, 1800, 5, 6, 0), + DA9052_LDO(LDO2, ldo2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), + DA9052_LDO(LDO3, ldo3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), + DA9052_LDO(LDO4, ldo4, 25, 1725, 3300, 6, 6, 0), + DA9052_LDO(LDO5, ldo5, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO6, ldo6, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO7, ldo7, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO8, ldo8, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO9, ldo9, 50, 1250, 3650, 6, 6, 0), + DA9052_LDO(LDO10, ldo10, 50, 1200, 3600, 6, 6, 0), }; static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id, diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c index 588c3d2445cf..3c6fac793658 100644 --- a/drivers/regulator/da9055-regulator.c +++ b/drivers/regulator/da9055-regulator.c @@ -48,7 +48,9 @@ #define DA9055_ID_LDO6 7 /* DA9055 BUCK current limit */ -static const int da9055_current_limits[] = { 500000, 600000, 700000, 800000 }; +static const unsigned int da9055_current_limits[] = { + 500000, 600000, 700000, 800000 +}; struct da9055_conf_reg { int reg; @@ -169,39 +171,6 @@ static int da9055_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode) val << volt.sl_shift); } -static int da9055_buck_get_current_limit(struct regulator_dev *rdev) -{ - struct da9055_regulator *regulator = rdev_get_drvdata(rdev); - struct da9055_regulator_info *info = regulator->info; - int ret; - - ret = da9055_reg_read(regulator->da9055, DA9055_REG_BUCK_LIM); - if (ret < 0) - return ret; - - ret &= info->mode.mask; - return da9055_current_limits[ret >> info->mode.shift]; -} - -static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA, - int max_uA) -{ - struct da9055_regulator *regulator = rdev_get_drvdata(rdev); - struct da9055_regulator_info *info = regulator->info; - int i; - - for (i = ARRAY_SIZE(da9055_current_limits) - 1; i >= 0; i--) { - if ((min_uA <= da9055_current_limits[i]) && - (da9055_current_limits[i] <= max_uA)) - return da9055_reg_update(regulator->da9055, - DA9055_REG_BUCK_LIM, - info->mode.mask, - i << info->mode.shift); - } - - return -EINVAL; -} - static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev) { struct da9055_regulator *regulator = rdev_get_drvdata(rdev); @@ -329,8 +298,8 @@ static const struct regulator_ops da9055_buck_ops = { .get_mode = da9055_buck_get_mode, .set_mode = da9055_buck_set_mode, - .get_current_limit = da9055_buck_get_current_limit, - .set_current_limit = da9055_buck_set_current_limit, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, .get_voltage_sel = da9055_regulator_get_voltage_sel, .set_voltage_sel = da9055_regulator_set_voltage_sel, @@ -407,6 +376,10 @@ static const struct regulator_ops da9055_ldo_ops = { .uV_step = (step) * 1000,\ .linear_min_sel = (voffset),\ .owner = THIS_MODULE,\ + .curr_table = da9055_current_limits,\ + .n_current_limits = ARRAY_SIZE(da9055_current_limits),\ + .csel_reg = DA9055_REG_BUCK_LIM,\ + .csel_mask = (mbits),\ },\ .conf = {\ .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \ @@ -457,7 +430,6 @@ static int da9055_gpio_init(struct da9055_regulator *regulator, int gpio_mux = pdata->gpio_ren[id]; config->ena_gpiod = pdata->ena_gpiods[id]; - config->ena_gpio_invert = 1; /* * GPI pin is muxed with regulator to control the diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c index 34a70d9dc450..b064d8a19d4c 100644 --- a/drivers/regulator/da9062-regulator.c +++ b/drivers/regulator/da9062-regulator.c @@ -126,7 +126,7 @@ static int da9062_set_current_limit(struct regulator_dev *rdev, const struct da9062_regulator_info *rinfo = regl->info; int n, tval; - for (n = 0; n < rinfo->n_current_limits; n++) { + for (n = rinfo->n_current_limits - 1; n >= 0; n--) { tval = rinfo->current_limits[n]; if (tval >= min_ua && tval <= max_ua) return regmap_field_write(regl->ilimit, n); @@ -992,7 +992,6 @@ static int da9062_regulator_probe(struct platform_device *pdev) struct regulator_config config = { }; const struct da9062_regulator_info *rinfo; int irq, n, ret; - size_t size; int max_regulators; switch (chip->chip_type) { @@ -1010,9 +1009,8 @@ static int da9062_regulator_probe(struct platform_device *pdev) } /* Allocate memory required by usable regulators */ - size = sizeof(struct da9062_regulators) + - max_regulators * sizeof(struct da9062_regulator); - regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + regulators = devm_kzalloc(&pdev->dev, struct_size(regulators, regulator, + max_regulators), GFP_KERNEL); if (!regulators) return -ENOMEM; @@ -1029,31 +1027,50 @@ static int da9062_regulator_probe(struct platform_device *pdev) regl->desc.type = REGULATOR_VOLTAGE; regl->desc.owner = THIS_MODULE; - if (regl->info->mode.reg) + if (regl->info->mode.reg) { regl->mode = devm_regmap_field_alloc( &pdev->dev, chip->regmap, regl->info->mode); - if (regl->info->suspend.reg) + if (IS_ERR(regl->mode)) + return PTR_ERR(regl->mode); + } + + if (regl->info->suspend.reg) { regl->suspend = devm_regmap_field_alloc( &pdev->dev, chip->regmap, regl->info->suspend); - if (regl->info->sleep.reg) + if (IS_ERR(regl->suspend)) + return PTR_ERR(regl->suspend); + } + + if (regl->info->sleep.reg) { regl->sleep = devm_regmap_field_alloc( &pdev->dev, chip->regmap, regl->info->sleep); - if (regl->info->suspend_sleep.reg) + if (IS_ERR(regl->sleep)) + return PTR_ERR(regl->sleep); + } + + if (regl->info->suspend_sleep.reg) { regl->suspend_sleep = devm_regmap_field_alloc( &pdev->dev, chip->regmap, regl->info->suspend_sleep); - if (regl->info->ilimit.reg) + if (IS_ERR(regl->suspend_sleep)) + return PTR_ERR(regl->suspend_sleep); + } + + if (regl->info->ilimit.reg) { regl->ilimit = devm_regmap_field_alloc( &pdev->dev, chip->regmap, regl->info->ilimit); + if (IS_ERR(regl->ilimit)) + return PTR_ERR(regl->ilimit); + } /* Register regulator */ memset(&config, 0, sizeof(config)); diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index 8cbcd2a3eb20..2b0c7a85306a 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -167,7 +167,7 @@ static int da9063_set_current_limit(struct regulator_dev *rdev, const struct da9063_regulator_info *rinfo = regl->info; int n, tval; - for (n = 0; n < rinfo->n_current_limits; n++) { + for (n = rinfo->n_current_limits - 1; n >= 0; n--) { tval = rinfo->current_limits[n]; if (tval >= min_uA && tval <= max_uA) return regmap_field_write(regl->ilimit, n); @@ -739,7 +739,6 @@ static int da9063_regulator_probe(struct platform_device *pdev) struct regulator_config config; bool bcores_merged, bmem_bio_merged; int id, irq, n, n_regulators, ret, val; - size_t size; regl_pdata = da9063_pdata ? da9063_pdata->regulators_pdata : NULL; @@ -784,9 +783,8 @@ static int da9063_regulator_probe(struct platform_device *pdev) n_regulators--; /* remove BMEM_BIO_MERGED */ /* Allocate memory required by usable regulators */ - size = sizeof(struct da9063_regulators) + - n_regulators * sizeof(struct da9063_regulator); - regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + regulators = devm_kzalloc(&pdev->dev, struct_size(regulators, + regulator, n_regulators), GFP_KERNEL); if (!regulators) return -ENOMEM; @@ -835,21 +833,40 @@ static int da9063_regulator_probe(struct platform_device *pdev) regl->desc.type = REGULATOR_VOLTAGE; regl->desc.owner = THIS_MODULE; - if (regl->info->mode.reg) + if (regl->info->mode.reg) { regl->mode = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->mode); - if (regl->info->suspend.reg) + if (IS_ERR(regl->mode)) + return PTR_ERR(regl->mode); + } + + if (regl->info->suspend.reg) { regl->suspend = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->suspend); - if (regl->info->sleep.reg) + if (IS_ERR(regl->suspend)) + return PTR_ERR(regl->suspend); + } + + if (regl->info->sleep.reg) { regl->sleep = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->sleep); - if (regl->info->suspend_sleep.reg) + if (IS_ERR(regl->sleep)) + return PTR_ERR(regl->sleep); + } + + if (regl->info->suspend_sleep.reg) { regl->suspend_sleep = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->suspend_sleep); - if (regl->info->ilimit.reg) + if (IS_ERR(regl->suspend_sleep)) + return PTR_ERR(regl->suspend_sleep); + } + + if (regl->info->ilimit.reg) { regl->ilimit = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->ilimit); + if (IS_ERR(regl->ilimit)) + return PTR_ERR(regl->ilimit); + } /* Register regulator */ memset(&config, 0, sizeof(config)); diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c index 84dba64ed11e..528303771723 100644 --- a/drivers/regulator/da9210-regulator.c +++ b/drivers/regulator/da9210-regulator.c @@ -41,10 +41,6 @@ static const struct regmap_config da9210_regmap_config = { .val_bits = 8, }; -static int da9210_set_current_limit(struct regulator_dev *rdev, int min_uA, - int max_uA); -static int da9210_get_current_limit(struct regulator_dev *rdev); - static const struct regulator_ops da9210_buck_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -52,8 +48,8 @@ static const struct regulator_ops da9210_buck_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear, - .set_current_limit = da9210_set_current_limit, - .get_current_limit = da9210_get_current_limit, + .set_current_limit = regulator_set_current_limit_regmap, + .get_current_limit = regulator_get_current_limit_regmap, }; /* Default limits measured in millivolts and milliamps */ @@ -62,7 +58,7 @@ static const struct regulator_ops da9210_buck_ops = { #define DA9210_STEP_MV 10 /* Current limits for buck (uA) indices corresponds with register values */ -static const int da9210_buck_limits[] = { +static const unsigned int da9210_buck_limits[] = { 1600000, 1800000, 2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000, 4600000 }; @@ -80,47 +76,12 @@ static const struct regulator_desc da9210_reg = { .enable_reg = DA9210_REG_BUCK_CONT, .enable_mask = DA9210_BUCK_EN, .owner = THIS_MODULE, + .curr_table = da9210_buck_limits, + .n_current_limits = ARRAY_SIZE(da9210_buck_limits), + .csel_reg = DA9210_REG_BUCK_ILIM, + .csel_mask = DA9210_BUCK_ILIM_MASK, }; -static int da9210_set_current_limit(struct regulator_dev *rdev, int min_uA, - int max_uA) -{ - struct da9210 *chip = rdev_get_drvdata(rdev); - unsigned int sel; - int i; - - /* search for closest to maximum */ - for (i = ARRAY_SIZE(da9210_buck_limits)-1; i >= 0; i--) { - if (min_uA <= da9210_buck_limits[i] && - max_uA >= da9210_buck_limits[i]) { - sel = i; - sel = sel << DA9210_BUCK_ILIM_SHIFT; - return regmap_update_bits(chip->regmap, - DA9210_REG_BUCK_ILIM, - DA9210_BUCK_ILIM_MASK, sel); - } - } - - return -EINVAL; -} - -static int da9210_get_current_limit(struct regulator_dev *rdev) -{ - struct da9210 *chip = rdev_get_drvdata(rdev); - unsigned int data; - unsigned int sel; - int ret; - - ret = regmap_read(chip->regmap, DA9210_REG_BUCK_ILIM, &data); - if (ret < 0) - return ret; - - /* select one of 16 values: 0000 (1600mA) to 1111 (4600mA) */ - sel = (data & DA9210_BUCK_ILIM_MASK) >> DA9210_BUCK_ILIM_SHIFT; - - return da9210_buck_limits[sel]; -} - static irqreturn_t da9210_irq_handler(int irq, void *data) { struct da9210 *chip = data; diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index a3bc8037153e..771a06d1900d 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -40,7 +40,6 @@ /* VSEL bit definitions */ #define VSEL_BUCK_EN (1 << 7) #define VSEL_MODE (1 << 6) -#define VSEL_NSEL_MASK 0x3F /* Chip ID and Verison */ #define DIE_ID 0x0F /* ID1 */ #define DIE_REV 0x0F /* ID2 */ @@ -49,14 +48,26 @@ #define CTL_SLEW_MASK (0x7 << 4) #define CTL_SLEW_SHIFT 4 #define CTL_RESET (1 << 2) +#define CTL_MODE_VSEL0_MODE BIT(0) +#define CTL_MODE_VSEL1_MODE BIT(1) #define FAN53555_NVOLTAGES 64 /* Numbers of voltages */ +#define FAN53526_NVOLTAGES 128 enum fan53555_vendor { - FAN53555_VENDOR_FAIRCHILD = 0, + FAN53526_VENDOR_FAIRCHILD = 0, + FAN53555_VENDOR_FAIRCHILD, FAN53555_VENDOR_SILERGY, }; +enum { + FAN53526_CHIP_ID_01 = 1, +}; + +enum { + FAN53526_CHIP_REV_08 = 8, +}; + /* IC Type */ enum { FAN53555_CHIP_ID_00 = 0, @@ -94,8 +105,12 @@ struct fan53555_device_info { /* Voltage range and step(linear) */ unsigned int vsel_min; unsigned int vsel_step; + unsigned int vsel_count; /* Voltage slew rate limiting */ unsigned int slew_rate; + /* Mode */ + unsigned int mode_reg; + unsigned int mode_mask; /* Sleep voltage cache */ unsigned int sleep_vol_cache; }; @@ -111,7 +126,7 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV) if (ret < 0) return ret; ret = regmap_update_bits(di->regmap, di->sleep_reg, - VSEL_NSEL_MASK, ret); + di->desc.vsel_mask, ret); if (ret < 0) return ret; /* Cache the sleep voltage setting. @@ -143,11 +158,11 @@ static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode) switch (mode) { case REGULATOR_MODE_FAST: - regmap_update_bits(di->regmap, di->vol_reg, - VSEL_MODE, VSEL_MODE); + regmap_update_bits(di->regmap, di->mode_reg, + di->mode_mask, di->mode_mask); break; case REGULATOR_MODE_NORMAL: - regmap_update_bits(di->regmap, di->vol_reg, VSEL_MODE, 0); + regmap_update_bits(di->regmap, di->vol_reg, di->mode_mask, 0); break; default: return -EINVAL; @@ -161,10 +176,10 @@ static unsigned int fan53555_get_mode(struct regulator_dev *rdev) unsigned int val; int ret = 0; - ret = regmap_read(di->regmap, di->vol_reg, &val); + ret = regmap_read(di->regmap, di->mode_reg, &val); if (ret < 0) return ret; - if (val & VSEL_MODE) + if (val & di->mode_mask) return REGULATOR_MODE_FAST; else return REGULATOR_MODE_NORMAL; @@ -219,6 +234,34 @@ static const struct regulator_ops fan53555_regulator_ops = { .set_suspend_disable = fan53555_set_suspend_disable, }; +static int fan53526_voltages_setup_fairchild(struct fan53555_device_info *di) +{ + /* Init voltage range and step */ + switch (di->chip_id) { + case FAN53526_CHIP_ID_01: + switch (di->chip_rev) { + case FAN53526_CHIP_REV_08: + di->vsel_min = 600000; + di->vsel_step = 6250; + break; + default: + dev_err(di->dev, + "Chip ID %d with rev %d not supported!\n", + di->chip_id, di->chip_rev); + return -EINVAL; + } + break; + default: + dev_err(di->dev, + "Chip ID %d not supported!\n", di->chip_id); + return -EINVAL; + } + + di->vsel_count = FAN53526_NVOLTAGES; + + return 0; +} + static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) { /* Init voltage range and step */ @@ -257,6 +300,8 @@ static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) return -EINVAL; } + di->vsel_count = FAN53555_NVOLTAGES; + return 0; } @@ -274,6 +319,8 @@ static int fan53555_voltages_setup_silergy(struct fan53555_device_info *di) return -EINVAL; } + di->vsel_count = FAN53555_NVOLTAGES; + return 0; } @@ -302,7 +349,35 @@ static int fan53555_device_setup(struct fan53555_device_info *di, return -EINVAL; } + /* Setup mode control register */ + switch (di->vendor) { + case FAN53526_VENDOR_FAIRCHILD: + di->mode_reg = FAN53555_CONTROL; + + switch (pdata->sleep_vsel_id) { + case FAN53555_VSEL_ID_0: + di->mode_mask = CTL_MODE_VSEL1_MODE; + break; + case FAN53555_VSEL_ID_1: + di->mode_mask = CTL_MODE_VSEL0_MODE; + break; + } + break; + case FAN53555_VENDOR_FAIRCHILD: + case FAN53555_VENDOR_SILERGY: + di->mode_reg = di->vol_reg; + di->mode_mask = VSEL_MODE; + break; + default: + dev_err(di->dev, "vendor %d not supported!\n", di->vendor); + return -EINVAL; + } + + /* Setup voltage range */ switch (di->vendor) { + case FAN53526_VENDOR_FAIRCHILD: + ret = fan53526_voltages_setup_fairchild(di); + break; case FAN53555_VENDOR_FAIRCHILD: ret = fan53555_voltages_setup_fairchild(di); break; @@ -326,13 +401,13 @@ static int fan53555_regulator_register(struct fan53555_device_info *di, rdesc->supply_name = "vin"; rdesc->ops = &fan53555_regulator_ops; rdesc->type = REGULATOR_VOLTAGE; - rdesc->n_voltages = FAN53555_NVOLTAGES; + rdesc->n_voltages = di->vsel_count; rdesc->enable_reg = di->vol_reg; rdesc->enable_mask = VSEL_BUCK_EN; rdesc->min_uV = di->vsel_min; rdesc->uV_step = di->vsel_step; rdesc->vsel_reg = di->vol_reg; - rdesc->vsel_mask = VSEL_NSEL_MASK; + rdesc->vsel_mask = di->vsel_count - 1; rdesc->owner = THIS_MODULE; di->rdev = devm_regulator_register(di->dev, &di->desc, config); @@ -368,6 +443,9 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev, static const struct of_device_id fan53555_dt_ids[] = { { + .compatible = "fcs,fan53526", + .data = (void *)FAN53526_VENDOR_FAIRCHILD, + }, { .compatible = "fcs,fan53555", .data = (void *)FAN53555_VENDOR_FAIRCHILD }, { @@ -412,11 +490,13 @@ static int fan53555_regulator_probe(struct i2c_client *client, } else { /* if no ramp constraint set, get the pdata ramp_delay */ if (!di->regulator->constraints.ramp_delay) { - int slew_idx = (pdata->slew_rate & 0x7) - ? pdata->slew_rate : 0; + if (pdata->slew_rate >= ARRAY_SIZE(slew_rates)) { + dev_err(&client->dev, "Invalid slew_rate\n"); + return -EINVAL; + } di->regulator->constraints.ramp_delay - = slew_rates[slew_idx]; + = slew_rates[pdata->slew_rate]; } di->vendor = id->driver_data; @@ -467,6 +547,9 @@ static int fan53555_regulator_probe(struct i2c_client *client, static const struct i2c_device_id fan53555_id[] = { { + .name = "fan53526", + .driver_data = FAN53526_VENDOR_FAIRCHILD + }, { .name = "fan53555", .driver_data = FAN53555_VENDOR_FAIRCHILD }, { diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 9abdb9130766..b5afc9db2c61 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -79,15 +79,6 @@ of_get_fixed_voltage_config(struct device *dev, of_property_read_u32(np, "startup-delay-us", &config->startup_delay); - /* - * FIXME: we pulled active low/high and open drain handling into - * gpiolib so it will be handled there. Delete this in the second - * step when we also remove the custom inversion handling for all - * legacy boardfiles. - */ - config->enable_high = 1; - config->gpio_is_open_drain = 0; - if (of_find_property(np, "vin-supply", NULL)) config->input_supply = "vin"; @@ -151,24 +142,14 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->desc.fixed_uV = config->microvolts; - cfg.ena_gpio_invert = !config->enable_high; - if (config->enabled_at_boot) { - if (config->enable_high) - gflags = GPIOD_OUT_HIGH; - else - gflags = GPIOD_OUT_LOW; - } else { - if (config->enable_high) - gflags = GPIOD_OUT_LOW; - else - gflags = GPIOD_OUT_HIGH; - } - if (config->gpio_is_open_drain) { - if (gflags == GPIOD_OUT_HIGH) - gflags = GPIOD_OUT_HIGH_OPEN_DRAIN; - else - gflags = GPIOD_OUT_LOW_OPEN_DRAIN; - } + /* + * The signal will be inverted by the GPIO core if flagged so in the + * decriptor. + */ + if (config->enabled_at_boot) + gflags = GPIOD_OUT_HIGH; + else + gflags = GPIOD_OUT_LOW; /* * Some fixed regulators share the enable line between two diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index b2f5ec4f658a..6157001df0a4 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -30,16 +30,15 @@ #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/gpio-regulator.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/slab.h> #include <linux/of.h> -#include <linux/of_gpio.h> struct gpio_regulator_data { struct regulator_desc desc; struct regulator_dev *dev; - struct gpio *gpios; + struct gpio_desc **gpiods; int nr_gpios; struct gpio_regulator_state *states; @@ -82,7 +81,7 @@ static int gpio_regulator_set_voltage(struct regulator_dev *dev, for (ptr = 0; ptr < data->nr_gpios; ptr++) { state = (target & (1 << ptr)) >> ptr; - gpio_set_value_cansleep(data->gpios[ptr].gpio, state); + gpiod_set_value_cansleep(data->gpiods[ptr], state); } data->state = target; @@ -119,7 +118,7 @@ static int gpio_regulator_set_current_limit(struct regulator_dev *dev, for (ptr = 0; ptr < data->nr_gpios; ptr++) { state = (target & (1 << ptr)) >> ptr; - gpio_set_value_cansleep(data->gpios[ptr].gpio, state); + gpiod_set_value_cansleep(data->gpiods[ptr], state); } data->state = target; @@ -138,7 +137,8 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np, { struct gpio_regulator_config *config; const char *regtype; - int proplen, gpio, i; + int proplen, i; + int ngpios; int ret; config = devm_kzalloc(dev, @@ -153,59 +153,36 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np, config->supply_name = config->init_data->constraints.name; - if (of_property_read_bool(np, "enable-active-high")) - config->enable_high = true; - if (of_property_read_bool(np, "enable-at-boot")) config->enabled_at_boot = true; of_property_read_u32(np, "startup-delay-us", &config->startup_delay); - config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0); - if (config->enable_gpio < 0 && config->enable_gpio != -ENOENT) - return ERR_PTR(config->enable_gpio); - - /* Fetch GPIOs. - optional property*/ - ret = of_gpio_count(np); - if ((ret < 0) && (ret != -ENOENT)) - return ERR_PTR(ret); - - if (ret > 0) { - config->nr_gpios = ret; - config->gpios = devm_kcalloc(dev, - config->nr_gpios, sizeof(struct gpio), - GFP_KERNEL); - if (!config->gpios) + /* Fetch GPIO init levels */ + ngpios = gpiod_count(dev, NULL); + if (ngpios > 0) { + config->gflags = devm_kzalloc(dev, + sizeof(enum gpiod_flags) + * ngpios, + GFP_KERNEL); + if (!config->gflags) return ERR_PTR(-ENOMEM); - proplen = of_property_count_u32_elems(np, "gpios-states"); - /* optional property */ - if (proplen < 0) - proplen = 0; + for (i = 0; i < ngpios; i++) { + u32 val; - if (proplen > 0 && proplen != config->nr_gpios) { - dev_warn(dev, "gpios <-> gpios-states mismatch\n"); - proplen = 0; - } + ret = of_property_read_u32_index(np, "gpios-states", i, + &val); - for (i = 0; i < config->nr_gpios; i++) { - gpio = of_get_named_gpio(np, "gpios", i); - if (gpio < 0) { - if (gpio != -ENOENT) - return ERR_PTR(gpio); - break; - } - config->gpios[i].gpio = gpio; - config->gpios[i].label = config->supply_name; - if (proplen > 0) { - of_property_read_u32_index(np, "gpios-states", - i, &ret); - if (ret) - config->gpios[i].flags = - GPIOF_OUT_INIT_HIGH; - } + /* Default to high per specification */ + if (ret) + config->gflags[i] = GPIOD_OUT_HIGH; + else + config->gflags[i] = + val ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; } } + config->ngpios = ngpios; /* Fetch states. */ proplen = of_property_count_u32_elems(np, "states"); @@ -251,59 +228,56 @@ static struct regulator_ops gpio_regulator_current_ops = { static int gpio_regulator_probe(struct platform_device *pdev) { - struct gpio_regulator_config *config = dev_get_platdata(&pdev->dev); - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct gpio_regulator_config *config = dev_get_platdata(dev); + struct device_node *np = dev->of_node; struct gpio_regulator_data *drvdata; struct regulator_config cfg = { }; - int ptr, ret, state; + enum gpiod_flags gflags; + int ptr, ret, state, i; - drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data), + drvdata = devm_kzalloc(dev, sizeof(struct gpio_regulator_data), GFP_KERNEL); if (drvdata == NULL) return -ENOMEM; if (np) { - config = of_get_gpio_regulator_config(&pdev->dev, np, + config = of_get_gpio_regulator_config(dev, np, &drvdata->desc); if (IS_ERR(config)) return PTR_ERR(config); } - drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); + drvdata->desc.name = devm_kstrdup(dev, config->supply_name, GFP_KERNEL); if (drvdata->desc.name == NULL) { - dev_err(&pdev->dev, "Failed to allocate supply name\n"); + dev_err(dev, "Failed to allocate supply name\n"); return -ENOMEM; } - if (config->nr_gpios != 0) { - drvdata->gpios = kmemdup(config->gpios, - config->nr_gpios * sizeof(struct gpio), - GFP_KERNEL); - if (drvdata->gpios == NULL) { - dev_err(&pdev->dev, "Failed to allocate gpio data\n"); - ret = -ENOMEM; - goto err_name; - } - - drvdata->nr_gpios = config->nr_gpios; - ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "Could not obtain regulator setting GPIOs: %d\n", - ret); - goto err_memgpio; - } + drvdata->gpiods = devm_kzalloc(dev, sizeof(struct gpio_desc *), + GFP_KERNEL); + if (!drvdata->gpiods) + return -ENOMEM; + for (i = 0; i < config->ngpios; i++) { + drvdata->gpiods[i] = devm_gpiod_get_index(dev, + NULL, + i, + config->gflags[i]); + if (IS_ERR(drvdata->gpiods[i])) + return PTR_ERR(drvdata->gpiods[i]); + /* This is good to know */ + gpiod_set_consumer_name(drvdata->gpiods[i], drvdata->desc.name); } + drvdata->nr_gpios = config->ngpios; - drvdata->states = kmemdup(config->states, - config->nr_states * - sizeof(struct gpio_regulator_state), - GFP_KERNEL); + drvdata->states = devm_kmemdup(dev, + config->states, + config->nr_states * + sizeof(struct gpio_regulator_state), + GFP_KERNEL); if (drvdata->states == NULL) { - dev_err(&pdev->dev, "Failed to allocate state data\n"); - ret = -ENOMEM; - goto err_stategpio; + dev_err(dev, "Failed to allocate state data\n"); + return -ENOMEM; } drvdata->nr_states = config->nr_states; @@ -322,61 +296,46 @@ static int gpio_regulator_probe(struct platform_device *pdev) drvdata->desc.ops = &gpio_regulator_current_ops; break; default: - dev_err(&pdev->dev, "No regulator type set\n"); - ret = -EINVAL; - goto err_memstate; + dev_err(dev, "No regulator type set\n"); + return -EINVAL; } /* build initial state from gpio init data. */ state = 0; for (ptr = 0; ptr < drvdata->nr_gpios; ptr++) { - if (config->gpios[ptr].flags & GPIOF_OUT_INIT_HIGH) + if (config->gflags[ptr] == GPIOD_OUT_HIGH) state |= (1 << ptr); } drvdata->state = state; - cfg.dev = &pdev->dev; + cfg.dev = dev; cfg.init_data = config->init_data; cfg.driver_data = drvdata; cfg.of_node = np; - if (gpio_is_valid(config->enable_gpio)) { - cfg.ena_gpio = config->enable_gpio; - cfg.ena_gpio_initialized = true; - } - cfg.ena_gpio_invert = !config->enable_high; - if (config->enabled_at_boot) { - if (config->enable_high) - cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; - else - cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW; - } else { - if (config->enable_high) - cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW; - else - cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; - } + /* + * The signal will be inverted by the GPIO core if flagged so in the + * decriptor. + */ + if (config->enabled_at_boot) + gflags = GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE; + else + gflags = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE; + + cfg.ena_gpiod = gpiod_get_optional(dev, "enable", gflags); + if (IS_ERR(cfg.ena_gpiod)) + return PTR_ERR(cfg.ena_gpiod); drvdata->dev = regulator_register(&drvdata->desc, &cfg); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); - dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); - goto err_memstate; + dev_err(dev, "Failed to register regulator: %d\n", ret); + return ret; } platform_set_drvdata(pdev, drvdata); return 0; - -err_memstate: - kfree(drvdata->states); -err_stategpio: - gpio_free_array(drvdata->gpios, drvdata->nr_gpios); -err_memgpio: - kfree(drvdata->gpios); -err_name: - kfree(drvdata->desc.name); - return ret; } static int gpio_regulator_remove(struct platform_device *pdev) @@ -385,13 +344,6 @@ static int gpio_regulator_remove(struct platform_device *pdev) regulator_unregister(drvdata->dev); - gpio_free_array(drvdata->gpios, drvdata->nr_gpios); - - kfree(drvdata->states); - kfree(drvdata->gpios); - - kfree(drvdata->desc.name); - return 0; } diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index 5686a1335bd3..32d3f0499e2d 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c @@ -594,28 +594,30 @@ int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev, EXPORT_SYMBOL_GPL(regulator_list_voltage_pickable_linear_range); /** - * regulator_list_voltage_linear_range - List voltages for linear ranges + * regulator_desc_list_voltage_linear_range - List voltages for linear ranges * - * @rdev: Regulator device + * @desc: Regulator desc for regulator which volatges are to be listed * @selector: Selector to convert into a voltage * * Regulators with a series of simple linear mappings between voltages - * and selectors can set linear_ranges in the regulator descriptor and - * then use this function as their list_voltage() operation, + * and selectors who have set linear_ranges in the regulator descriptor + * can use this function prior regulator registration to list voltages. + * This is useful when voltages need to be listed during device-tree + * parsing. */ -int regulator_list_voltage_linear_range(struct regulator_dev *rdev, - unsigned int selector) +int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc, + unsigned int selector) { const struct regulator_linear_range *range; int i; - if (!rdev->desc->n_linear_ranges) { - BUG_ON(!rdev->desc->n_linear_ranges); + if (!desc->n_linear_ranges) { + BUG_ON(!desc->n_linear_ranges); return -EINVAL; } - for (i = 0; i < rdev->desc->n_linear_ranges; i++) { - range = &rdev->desc->linear_ranges[i]; + for (i = 0; i < desc->n_linear_ranges; i++) { + range = &desc->linear_ranges[i]; if (!(selector >= range->min_sel && selector <= range->max_sel)) @@ -628,6 +630,23 @@ int regulator_list_voltage_linear_range(struct regulator_dev *rdev, return -EINVAL; } +EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear_range); + +/** + * regulator_list_voltage_linear_range - List voltages for linear ranges + * + * @rdev: Regulator device + * @selector: Selector to convert into a voltage + * + * Regulators with a series of simple linear mappings between voltages + * and selectors can set linear_ranges in the regulator descriptor and + * then use this function as their list_voltage() operation, + */ +int regulator_list_voltage_linear_range(struct regulator_dev *rdev, + unsigned int selector) +{ + return regulator_desc_list_voltage_linear_range(rdev->desc, selector); +} EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range); /** @@ -761,3 +780,89 @@ int regulator_set_active_discharge_regmap(struct regulator_dev *rdev, rdev->desc->active_discharge_mask, val); } EXPORT_SYMBOL_GPL(regulator_set_active_discharge_regmap); + +/** + * regulator_set_current_limit_regmap - set_current_limit for regmap users + * + * @rdev: regulator to operate on + * @min_uA: Lower bound for current limit + * @max_uA: Upper bound for current limit + * + * Regulators that use regmap for their register I/O can set curr_table, + * csel_reg and csel_mask fields in their descriptor and then use this + * as their set_current_limit operation, saving some code. + */ +int regulator_set_current_limit_regmap(struct regulator_dev *rdev, + int min_uA, int max_uA) +{ + unsigned int n_currents = rdev->desc->n_current_limits; + int i, sel = -1; + + if (n_currents == 0) + return -EINVAL; + + if (rdev->desc->curr_table) { + const unsigned int *curr_table = rdev->desc->curr_table; + bool ascend = curr_table[n_currents - 1] > curr_table[0]; + + /* search for closest to maximum */ + if (ascend) { + for (i = n_currents - 1; i >= 0; i--) { + if (min_uA <= curr_table[i] && + curr_table[i] <= max_uA) { + sel = i; + break; + } + } + } else { + for (i = 0; i < n_currents; i++) { + if (min_uA <= curr_table[i] && + curr_table[i] <= max_uA) { + sel = i; + break; + } + } + } + } + + if (sel < 0) + return -EINVAL; + + sel <<= ffs(rdev->desc->csel_mask) - 1; + + return regmap_update_bits(rdev->regmap, rdev->desc->csel_reg, + rdev->desc->csel_mask, sel); +} +EXPORT_SYMBOL_GPL(regulator_set_current_limit_regmap); + +/** + * regulator_get_current_limit_regmap - get_current_limit for regmap users + * + * @rdev: regulator to operate on + * + * Regulators that use regmap for their register I/O can set the + * csel_reg and csel_mask fields in their descriptor and then use this + * as their get_current_limit operation, saving some code. + */ +int regulator_get_current_limit_regmap(struct regulator_dev *rdev) +{ + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, rdev->desc->csel_reg, &val); + if (ret != 0) + return ret; + + val &= rdev->desc->csel_mask; + val >>= ffs(rdev->desc->csel_mask) - 1; + + if (rdev->desc->curr_table) { + if (val >= rdev->desc->n_current_limits) + return -EINVAL; + + return rdev->desc->curr_table[val]; + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(regulator_get_current_limit_regmap); diff --git a/drivers/regulator/hi655x-regulator.c b/drivers/regulator/hi655x-regulator.c index 36ae54b53814..bba24a6fdb1e 100644 --- a/drivers/regulator/hi655x-regulator.c +++ b/drivers/regulator/hi655x-regulator.c @@ -28,7 +28,6 @@ struct hi655x_regulator { unsigned int disable_reg; unsigned int status_reg; - unsigned int ctrl_regs; unsigned int ctrl_mask; struct regulator_desc rdesc; }; diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 4abd8e9c81e5..6f28bba81d13 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -31,7 +31,6 @@ /* PMIC details */ struct isl_pmic { struct i2c_client *client; - struct regulator_dev *rdev[3]; struct mutex mtx; }; @@ -66,14 +65,14 @@ static int isl6271a_set_voltage_sel(struct regulator_dev *dev, return err; } -static struct regulator_ops isl_core_ops = { +static const struct regulator_ops isl_core_ops = { .get_voltage_sel = isl6271a_get_voltage_sel, .set_voltage_sel = isl6271a_set_voltage_sel, .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, }; -static struct regulator_ops isl_fixed_ops = { +static const struct regulator_ops isl_fixed_ops = { .list_voltage = regulator_list_voltage_linear, }; @@ -109,6 +108,7 @@ static const struct regulator_desc isl_rd[] = { static int isl6271a_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { + struct regulator_dev *rdev; struct regulator_config config = { }; struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev); struct isl_pmic *pmic; @@ -133,11 +133,10 @@ static int isl6271a_probe(struct i2c_client *i2c, config.init_data = NULL; config.driver_data = pmic; - pmic->rdev[i] = devm_regulator_register(&i2c->dev, &isl_rd[i], - &config); - if (IS_ERR(pmic->rdev[i])) { + rdev = devm_regulator_register(&i2c->dev, &isl_rd[i], &config); + if (IS_ERR(rdev)) { dev_err(&i2c->dev, "failed to register %s\n", id->name); - return PTR_ERR(pmic->rdev[i]); + return PTR_ERR(rdev); } } diff --git a/drivers/regulator/lm363x-regulator.c b/drivers/regulator/lm363x-regulator.c index 8c0e8419c43f..c876e161052a 100644 --- a/drivers/regulator/lm363x-regulator.c +++ b/drivers/regulator/lm363x-regulator.c @@ -258,6 +258,9 @@ static int lm363x_regulator_probe(struct platform_device *pdev) * Register update is required if the pin is used. */ gpiod = lm363x_regulator_of_get_enable_gpio(dev, id); + if (IS_ERR(gpiod)) + return PTR_ERR(gpiod); + if (gpiod) { cfg.ena_gpiod = gpiod; @@ -265,8 +268,7 @@ static int lm363x_regulator_probe(struct platform_device *pdev) LM3632_EXT_EN_MASK, LM3632_EXT_EN_MASK); if (ret) { - if (gpiod) - gpiod_put(gpiod); + gpiod_put(gpiod); dev_err(dev, "External pin err: %d\n", ret); return ret; } diff --git a/drivers/regulator/lochnagar-regulator.c b/drivers/regulator/lochnagar-regulator.c index 5a89e6d4b9a6..ff97cc50f2eb 100644 --- a/drivers/regulator/lochnagar-regulator.c +++ b/drivers/regulator/lochnagar-regulator.c @@ -194,7 +194,7 @@ static const struct regulator_desc lochnagar_regulators[] = { .name = "VDDCORE", .supply_name = "SYSVDD", .type = REGULATOR_VOLTAGE, - .n_voltages = 57, + .n_voltages = 66, .ops = &lochnagar_vddcore_ops, .id = LOCHNAGAR_VDDCORE, @@ -226,14 +226,15 @@ static const struct of_device_id lochnagar_of_match[] = { }, { .compatible = "cirrus,lochnagar2-mic2vdd", - .data = &lochnagar_regulators[LOCHNAGAR_MIC1VDD], + .data = &lochnagar_regulators[LOCHNAGAR_MIC2VDD], }, { .compatible = "cirrus,lochnagar2-vddcore", .data = &lochnagar_regulators[LOCHNAGAR_VDDCORE], }, - {}, + {} }; +MODULE_DEVICE_TABLE(of, lochnagar_of_match); static int lochnagar_regulator_probe(struct platform_device *pdev) { diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 204b5c5270e0..9e45112658ba 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -159,7 +159,7 @@ static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev, selector << LDO_VOL_CONTR_SHIFT(ldo)); } -static struct regulator_ops lp3971_ldo_ops = { +static const struct regulator_ops lp3971_ldo_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .is_enabled = lp3971_ldo_is_enabled, @@ -233,7 +233,7 @@ static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev, 0 << BUCK_VOL_CHANGE_SHIFT(buck)); } -static struct regulator_ops lp3971_dcdc_ops = { +static const struct regulator_ops lp3971_dcdc_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .is_enabled = lp3971_dcdc_is_enabled, diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index ff0c275f902e..fb098198b688 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -305,7 +305,7 @@ static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev, return ret; } -static struct regulator_ops lp3972_ldo_ops = { +static const struct regulator_ops lp3972_ldo_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .is_enabled = lp3972_ldo_is_enabled, @@ -386,7 +386,7 @@ static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev, LP3972_VOL_CHANGE_FLAG_MASK, 0); } -static struct regulator_ops lp3972_dcdc_ops = { +static const struct regulator_ops lp3972_dcdc_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .is_enabled = lp3972_dcdc_is_enabled, diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 38992112fd6e..ca95257ce252 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -353,64 +353,6 @@ static int lp872x_buck_get_voltage_sel(struct regulator_dev *rdev) return val & LP872X_VOUT_M; } -static int lp8725_buck_set_current_limit(struct regulator_dev *rdev, - int min_uA, int max_uA) -{ - struct lp872x *lp = rdev_get_drvdata(rdev); - enum lp872x_regulator_id buck = rdev_get_id(rdev); - int i; - u8 addr; - - switch (buck) { - case LP8725_ID_BUCK1: - addr = LP8725_BUCK1_VOUT2; - break; - case LP8725_ID_BUCK2: - addr = LP8725_BUCK2_VOUT2; - break; - default: - return -EINVAL; - } - - for (i = ARRAY_SIZE(lp8725_buck_uA) - 1; i >= 0; i--) { - if (lp8725_buck_uA[i] >= min_uA && - lp8725_buck_uA[i] <= max_uA) - return lp872x_update_bits(lp, addr, - LP8725_BUCK_CL_M, - i << LP8725_BUCK_CL_S); - } - - return -EINVAL; -} - -static int lp8725_buck_get_current_limit(struct regulator_dev *rdev) -{ - struct lp872x *lp = rdev_get_drvdata(rdev); - enum lp872x_regulator_id buck = rdev_get_id(rdev); - u8 addr, val; - int ret; - - switch (buck) { - case LP8725_ID_BUCK1: - addr = LP8725_BUCK1_VOUT2; - break; - case LP8725_ID_BUCK2: - addr = LP8725_BUCK2_VOUT2; - break; - default: - return -EINVAL; - } - - ret = lp872x_read_byte(lp, addr, &val); - if (ret) - return ret; - - val = (val & LP8725_BUCK_CL_M) >> LP8725_BUCK_CL_S; - - return (val < ARRAY_SIZE(lp8725_buck_uA)) ? - lp8725_buck_uA[val] : -EINVAL; -} - static int lp872x_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct lp872x *lp = rdev_get_drvdata(rdev); @@ -478,7 +420,7 @@ static unsigned int lp872x_buck_get_mode(struct regulator_dev *rdev) return val & mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; } -static struct regulator_ops lp872x_ldo_ops = { +static const struct regulator_ops lp872x_ldo_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .set_voltage_sel = regulator_set_voltage_sel_regmap, @@ -489,7 +431,7 @@ static struct regulator_ops lp872x_ldo_ops = { .enable_time = lp872x_regulator_enable_time, }; -static struct regulator_ops lp8720_buck_ops = { +static const struct regulator_ops lp8720_buck_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .set_voltage_sel = lp872x_buck_set_voltage_sel, @@ -502,7 +444,7 @@ static struct regulator_ops lp8720_buck_ops = { .get_mode = lp872x_buck_get_mode, }; -static struct regulator_ops lp8725_buck_ops = { +static const struct regulator_ops lp8725_buck_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .set_voltage_sel = lp872x_buck_set_voltage_sel, @@ -513,11 +455,11 @@ static struct regulator_ops lp8725_buck_ops = { .enable_time = lp872x_regulator_enable_time, .set_mode = lp872x_buck_set_mode, .get_mode = lp872x_buck_get_mode, - .set_current_limit = lp8725_buck_set_current_limit, - .get_current_limit = lp8725_buck_get_current_limit, + .set_current_limit = regulator_set_current_limit_regmap, + .get_current_limit = regulator_get_current_limit_regmap, }; -static struct regulator_desc lp8720_regulator_desc[] = { +static const struct regulator_desc lp8720_regulator_desc[] = { { .name = "ldo1", .of_match = of_match_ptr("ldo1"), @@ -602,7 +544,7 @@ static struct regulator_desc lp8720_regulator_desc[] = { }, }; -static struct regulator_desc lp8725_regulator_desc[] = { +static const struct regulator_desc lp8725_regulator_desc[] = { { .name = "ldo1", .of_match = of_match_ptr("ldo1"), @@ -712,6 +654,10 @@ static struct regulator_desc lp8725_regulator_desc[] = { .owner = THIS_MODULE, .enable_reg = LP872X_GENERAL_CFG, .enable_mask = LP8725_BUCK1_EN_M, + .curr_table = lp8725_buck_uA, + .n_current_limits = ARRAY_SIZE(lp8725_buck_uA), + .csel_reg = LP8725_BUCK1_VOUT2, + .csel_mask = LP8725_BUCK_CL_M, }, { .name = "buck2", @@ -724,6 +670,10 @@ static struct regulator_desc lp8725_regulator_desc[] = { .owner = THIS_MODULE, .enable_reg = LP872X_GENERAL_CFG, .enable_mask = LP8725_BUCK2_EN_M, + .curr_table = lp8725_buck_uA, + .n_current_limits = ARRAY_SIZE(lp8725_buck_uA), + .csel_reg = LP8725_BUCK2_VOUT2, + .csel_mask = LP8725_BUCK_CL_M, }, }; @@ -820,7 +770,7 @@ static struct regulator_init_data static int lp872x_regulator_register(struct lp872x *lp) { - struct regulator_desc *desc; + const struct regulator_desc *desc; struct regulator_config cfg = { }; struct regulator_dev *rdev; int i; diff --git a/drivers/regulator/lp873x-regulator.c b/drivers/regulator/lp873x-regulator.c index 70e3df653381..b55de293ca7a 100644 --- a/drivers/regulator/lp873x-regulator.c +++ b/drivers/regulator/lp873x-regulator.c @@ -39,6 +39,10 @@ .ramp_delay = _delay, \ .linear_ranges = _lr, \ .n_linear_ranges = ARRAY_SIZE(_lr), \ + .curr_table = lp873x_buck_uA, \ + .n_current_limits = ARRAY_SIZE(lp873x_buck_uA), \ + .csel_reg = (_cr), \ + .csel_mask = LP873X_BUCK0_CTRL_2_BUCK0_ILIM,\ }, \ .ctrl2_reg = _cr, \ } @@ -61,7 +65,7 @@ static const struct regulator_linear_range ldo0_ldo1_ranges[] = { REGULATOR_LINEAR_RANGE(800000, 0x0, 0x19, 100000), }; -static unsigned int lp873x_buck_ramp_delay[] = { +static const unsigned int lp873x_buck_ramp_delay[] = { 30000, 15000, 10000, 7500, 3800, 1900, 940, 470 }; @@ -108,45 +112,8 @@ static int lp873x_buck_set_ramp_delay(struct regulator_dev *rdev, return 0; } -static int lp873x_buck_set_current_limit(struct regulator_dev *rdev, - int min_uA, int max_uA) -{ - int id = rdev_get_id(rdev); - struct lp873x *lp873 = rdev_get_drvdata(rdev); - int i; - - for (i = ARRAY_SIZE(lp873x_buck_uA) - 1; i >= 0; i--) { - if (lp873x_buck_uA[i] >= min_uA && - lp873x_buck_uA[i] <= max_uA) - return regmap_update_bits(lp873->regmap, - regulators[id].ctrl2_reg, - LP873X_BUCK0_CTRL_2_BUCK0_ILIM, - i << __ffs(LP873X_BUCK0_CTRL_2_BUCK0_ILIM)); - } - - return -EINVAL; -} - -static int lp873x_buck_get_current_limit(struct regulator_dev *rdev) -{ - int id = rdev_get_id(rdev); - struct lp873x *lp873 = rdev_get_drvdata(rdev); - int ret; - unsigned int val; - - ret = regmap_read(lp873->regmap, regulators[id].ctrl2_reg, &val); - if (ret) - return ret; - - val = (val & LP873X_BUCK0_CTRL_2_BUCK0_ILIM) >> - __ffs(LP873X_BUCK0_CTRL_2_BUCK0_ILIM); - - return (val < ARRAY_SIZE(lp873x_buck_uA)) ? - lp873x_buck_uA[val] : -EINVAL; -} - /* Operations permitted on BUCK0, BUCK1 */ -static struct regulator_ops lp873x_buck01_ops = { +static const struct regulator_ops lp873x_buck01_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -156,12 +123,12 @@ static struct regulator_ops lp873x_buck01_ops = { .map_voltage = regulator_map_voltage_linear_range, .set_voltage_time_sel = regulator_set_voltage_time_sel, .set_ramp_delay = lp873x_buck_set_ramp_delay, - .set_current_limit = lp873x_buck_set_current_limit, - .get_current_limit = lp873x_buck_get_current_limit, + .set_current_limit = regulator_set_current_limit_regmap, + .get_current_limit = regulator_get_current_limit_regmap, }; /* Operations permitted on LDO0 and LDO1 */ -static struct regulator_ops lp873x_ldo01_ops = { +static const struct regulator_ops lp873x_ldo01_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 244822bb63cd..14fd38807134 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -315,7 +315,7 @@ out_i2c_error: .vsel_mask = LP8755_BUCK_VOUT_M,\ } -static struct regulator_desc lp8755_regulators[] = { +static const struct regulator_desc lp8755_regulators[] = { lp8755_buck_desc(0), lp8755_buck_desc(1), lp8755_buck_desc(2), @@ -386,7 +386,7 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data) if (ret < 0) goto err_i2c; - /* send OCP event to all regualtor devices */ + /* send OCP event to all regulator devices */ if ((flag1 & 0x01) && (pchip->irqmask & 0x01)) for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) if (pchip->rdev[icnt] != NULL) @@ -394,7 +394,7 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data) LP8755_EVENT_OCP, NULL); - /* send OVP event to all regualtor devices */ + /* send OVP event to all regulator devices */ if ((flag1 & 0x02) && (pchip->irqmask & 0x02)) for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) if (pchip->rdev[icnt] != NULL) diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c index c192357d1dea..4ed41731a5b1 100644 --- a/drivers/regulator/lp87565-regulator.c +++ b/drivers/regulator/lp87565-regulator.c @@ -51,7 +51,7 @@ static const struct regulator_linear_range buck0_1_2_3_ranges[] = { REGULATOR_LINEAR_RANGE(1420000, 0x9e, 0xff, 20000), }; -static unsigned int lp87565_buck_ramp_delay[] = { +static const unsigned int lp87565_buck_ramp_delay[] = { 30000, 15000, 10000, 7500, 3800, 1900, 940, 470 }; @@ -140,7 +140,7 @@ static int lp87565_buck_get_current_limit(struct regulator_dev *rdev) } /* Operations permitted on BUCK0, BUCK1 */ -static struct regulator_ops lp87565_buck_ops = { +static const struct regulator_ops lp87565_buck_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c index ec46290b647e..a7d30550bb5f 100644 --- a/drivers/regulator/lp8788-buck.c +++ b/drivers/regulator/lp8788-buck.c @@ -95,12 +95,10 @@ struct lp8788_buck { void *dvs; }; -/* BUCK 1 ~ 4 voltage table */ -static const int lp8788_buck_vtbl[] = { - 500000, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, - 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, - 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, - 1950000, 2000000, +/* BUCK 1 ~ 4 voltage ranges */ +static const struct regulator_linear_range buck_volt_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 0, 0), + REGULATOR_LINEAR_RANGE(800000, 1, 25, 50000), }; static void lp8788_buck1_set_dvs(struct lp8788_buck *buck) @@ -345,8 +343,8 @@ static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev) } static const struct regulator_ops lp8788_buck12_ops = { - .list_voltage = regulator_list_voltage_table, - .map_voltage = regulator_map_voltage_ascend, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .set_voltage_sel = lp8788_buck12_set_voltage_sel, .get_voltage_sel = lp8788_buck12_get_voltage_sel, .enable = regulator_enable_regmap, @@ -358,8 +356,8 @@ static const struct regulator_ops lp8788_buck12_ops = { }; static const struct regulator_ops lp8788_buck34_ops = { - .list_voltage = regulator_list_voltage_table, - .map_voltage = regulator_map_voltage_ascend, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .enable = regulator_enable_regmap, @@ -370,13 +368,14 @@ static const struct regulator_ops lp8788_buck34_ops = { .get_mode = lp8788_buck_get_mode, }; -static struct regulator_desc lp8788_buck_desc[] = { +static const struct regulator_desc lp8788_buck_desc[] = { { .name = "buck1", .id = BUCK1, .ops = &lp8788_buck12_ops, - .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl), - .volt_table = lp8788_buck_vtbl, + .n_voltages = 26, + .linear_ranges = buck_volt_ranges, + .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges), .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_BUCK, @@ -386,8 +385,9 @@ static struct regulator_desc lp8788_buck_desc[] = { .name = "buck2", .id = BUCK2, .ops = &lp8788_buck12_ops, - .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl), - .volt_table = lp8788_buck_vtbl, + .n_voltages = 26, + .linear_ranges = buck_volt_ranges, + .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges), .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_BUCK, @@ -397,8 +397,9 @@ static struct regulator_desc lp8788_buck_desc[] = { .name = "buck3", .id = BUCK3, .ops = &lp8788_buck34_ops, - .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl), - .volt_table = lp8788_buck_vtbl, + .n_voltages = 26, + .linear_ranges = buck_volt_ranges, + .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges), .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .vsel_reg = LP8788_BUCK3_VOUT, @@ -410,8 +411,9 @@ static struct regulator_desc lp8788_buck_desc[] = { .name = "buck4", .id = BUCK4, .ops = &lp8788_buck34_ops, - .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl), - .volt_table = lp8788_buck_vtbl, + .n_voltages = 26, + .linear_ranges = buck_volt_ranges, + .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges), .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .vsel_reg = LP8788_BUCK4_VOUT, diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c index 2ee22e7ea675..a2ef146e6b3a 100644 --- a/drivers/regulator/lp8788-ldo.c +++ b/drivers/regulator/lp8788-ldo.c @@ -186,7 +186,7 @@ static const struct regulator_ops lp8788_ldo_voltage_fixed_ops = { .enable_time = lp8788_ldo_enable_time, }; -static struct regulator_desc lp8788_dldo_desc[] = { +static const struct regulator_desc lp8788_dldo_desc[] = { { .name = "dldo1", .id = DLDO1, @@ -343,7 +343,7 @@ static struct regulator_desc lp8788_dldo_desc[] = { }, }; -static struct regulator_desc lp8788_aldo_desc[] = { +static const struct regulator_desc lp8788_aldo_desc[] = { { .name = "aldo1", .id = ALDO1, diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c index 71fd0f2a4b76..e6d66e492b85 100644 --- a/drivers/regulator/ltc3676.c +++ b/drivers/regulator/ltc3676.c @@ -241,61 +241,10 @@ static struct regulator_desc ltc3676_regulators[LTC3676_NUM_REGULATORS] = { LTC3676_FIXED_REG(LDO4, ldo4, LDOB, 2), }; -static bool ltc3676_writeable_reg(struct device *dev, unsigned int reg) +static bool ltc3676_readable_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { - case LTC3676_IRQSTAT: - case LTC3676_BUCK1: - case LTC3676_BUCK2: - case LTC3676_BUCK3: - case LTC3676_BUCK4: - case LTC3676_LDOA: - case LTC3676_LDOB: - case LTC3676_SQD1: - case LTC3676_SQD2: - case LTC3676_CNTRL: - case LTC3676_DVB1A: - case LTC3676_DVB1B: - case LTC3676_DVB2A: - case LTC3676_DVB2B: - case LTC3676_DVB3A: - case LTC3676_DVB3B: - case LTC3676_DVB4A: - case LTC3676_DVB4B: - case LTC3676_MSKIRQ: - case LTC3676_MSKPG: - case LTC3676_USER: - case LTC3676_HRST: - case LTC3676_CLIRQ: - return true; - } - return false; -} - -static bool ltc3676_readable_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case LTC3676_IRQSTAT: - case LTC3676_BUCK1: - case LTC3676_BUCK2: - case LTC3676_BUCK3: - case LTC3676_BUCK4: - case LTC3676_LDOA: - case LTC3676_LDOB: - case LTC3676_SQD1: - case LTC3676_SQD2: - case LTC3676_CNTRL: - case LTC3676_DVB1A: - case LTC3676_DVB1B: - case LTC3676_DVB2A: - case LTC3676_DVB2B: - case LTC3676_DVB3A: - case LTC3676_DVB3B: - case LTC3676_DVB4A: - case LTC3676_DVB4B: - case LTC3676_MSKIRQ: - case LTC3676_MSKPG: - case LTC3676_USER: + case LTC3676_BUCK1 ... LTC3676_IRQSTAT: case LTC3676_HRST: case LTC3676_CLIRQ: return true; @@ -306,9 +255,7 @@ static bool ltc3676_readable_reg(struct device *dev, unsigned int reg) static bool ltc3676_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { - case LTC3676_IRQSTAT: - case LTC3676_PGSTATL: - case LTC3676_PGSTATRT: + case LTC3676_IRQSTAT ... LTC3676_PGSTATRT: return true; } return false; @@ -317,8 +264,8 @@ static bool ltc3676_volatile_reg(struct device *dev, unsigned int reg) static const struct regmap_config ltc3676_regmap_config = { .reg_bits = 8, .val_bits = 8, - .writeable_reg = ltc3676_writeable_reg, - .readable_reg = ltc3676_readable_reg, + .writeable_reg = ltc3676_readable_writeable_reg, + .readable_reg = ltc3676_readable_writeable_reg, .volatile_reg = ltc3676_volatile_reg, .max_register = LTC3676_CLIRQ, .use_single_read = true, @@ -442,5 +389,5 @@ static struct i2c_driver ltc3676_driver = { module_i2c_driver(ltc3676_driver); MODULE_AUTHOR("Tim Harvey <tharvey@gateworks.com>"); -MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC1376"); +MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC3676"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/max14577-regulator.c b/drivers/regulator/max14577-regulator.c index bc7f4751bf9c..85a88a9e4d42 100644 --- a/drivers/regulator/max14577-regulator.c +++ b/drivers/regulator/max14577-regulator.c @@ -324,4 +324,3 @@ module_exit(max14577_regulator_exit); MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>"); MODULE_DESCRIPTION("Maxim 14577/77836 regulator driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:max14577-regulator"); diff --git a/drivers/regulator/max77620-regulator.c b/drivers/regulator/max77620-regulator.c index b94e3a721721..1607ac673e44 100644 --- a/drivers/regulator/max77620-regulator.c +++ b/drivers/regulator/max77620-regulator.c @@ -1,7 +1,7 @@ /* * Maxim MAX77620 Regulator driver * - * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved. * * Author: Mallikarjun Kasoju <mkasoju@nvidia.com> * Laxman Dewangan <ldewangan@nvidia.com> @@ -690,6 +690,7 @@ static const struct regulator_ops max77620_regulator_ops = { .active_discharge_mask = MAX77620_SD_CFG1_ADE_MASK, \ .active_discharge_reg = MAX77620_REG_##_id##_CFG, \ .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ }, \ } @@ -721,6 +722,7 @@ static const struct regulator_ops max77620_regulator_ops = { .active_discharge_mask = MAX77620_LDO_CFG2_ADE_MASK, \ .active_discharge_reg = MAX77620_REG_##_id##_CFG2, \ .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ }, \ } @@ -803,6 +805,14 @@ static int max77620_regulator_probe(struct platform_device *pdev) rdesc = &rinfo[id].desc; pmic->rinfo[id] = &max77620_regs_info[id]; pmic->enable_power_mode[id] = MAX77620_POWER_MODE_NORMAL; + pmic->reg_pdata[id].active_fps_src = -1; + pmic->reg_pdata[id].active_fps_pd_slot = -1; + pmic->reg_pdata[id].active_fps_pu_slot = -1; + pmic->reg_pdata[id].suspend_fps_src = -1; + pmic->reg_pdata[id].suspend_fps_pd_slot = -1; + pmic->reg_pdata[id].suspend_fps_pu_slot = -1; + pmic->reg_pdata[id].power_ok = -1; + pmic->reg_pdata[id].ramp_rate_setting = -1; ret = max77620_read_slew_rate(pmic, id); if (ret < 0) diff --git a/drivers/regulator/max77650-regulator.c b/drivers/regulator/max77650-regulator.c new file mode 100644 index 000000000000..31ebf34b01ec --- /dev/null +++ b/drivers/regulator/max77650-regulator.c @@ -0,0 +1,498 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2018 BayLibre SAS +// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> +// +// Regulator driver for MAXIM 77650/77651 charger/power-supply. + +#include <linux/of.h> +#include <linux/mfd/max77650.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> + +#define MAX77650_REGULATOR_EN_CTRL_MASK GENMASK(3, 0) +#define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \ + ((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK) +#define MAX77650_REGULATOR_ENABLED GENMASK(2, 1) +#define MAX77650_REGULATOR_DISABLED BIT(2) + +#define MAX77650_REGULATOR_V_LDO_MASK GENMASK(6, 0) +#define MAX77650_REGULATOR_V_SBB_MASK GENMASK(5, 0) + +#define MAX77650_REGULATOR_AD_MASK BIT(3) +#define MAX77650_REGULATOR_AD_DISABLED 0x00 +#define MAX77650_REGULATOR_AD_ENABLED BIT(3) + +#define MAX77650_REGULATOR_CURR_LIM_MASK GENMASK(7, 6) + +enum { + MAX77650_REGULATOR_ID_LDO = 0, + MAX77650_REGULATOR_ID_SBB0, + MAX77650_REGULATOR_ID_SBB1, + MAX77650_REGULATOR_ID_SBB2, + MAX77650_REGULATOR_NUM_REGULATORS, +}; + +struct max77650_regulator_desc { + struct regulator_desc desc; + unsigned int regA; + unsigned int regB; +}; + +static const u32 max77651_sbb1_regulator_volt_table[] = { + 2400000, 3200000, 4000000, 4800000, + 2450000, 3250000, 4050000, 4850000, + 2500000, 3300000, 4100000, 4900000, + 2550000, 3350000, 4150000, 4950000, + 2600000, 3400000, 4200000, 5000000, + 2650000, 3450000, 4250000, 5050000, + 2700000, 3500000, 4300000, 5100000, + 2750000, 3550000, 4350000, 5150000, + 2800000, 3600000, 4400000, 5200000, + 2850000, 3650000, 4450000, 5250000, + 2900000, 3700000, 4500000, 0, + 2950000, 3750000, 4550000, 0, + 3000000, 3800000, 4600000, 0, + 3050000, 3850000, 4650000, 0, + 3100000, 3900000, 4700000, 0, + 3150000, 3950000, 4750000, 0, +}; + +#define MAX77651_REGULATOR_SBB1_SEL_DEC(_val) \ + (((_val & 0x3c) >> 2) | ((_val & 0x03) << 4)) +#define MAX77651_REGULATOR_SBB1_SEL_ENC(_val) \ + (((_val & 0x30) >> 4) | ((_val & 0x0f) << 2)) + +#define MAX77650_REGULATOR_SBB1_SEL_DECR(_val) \ + do { \ + _val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \ + _val--; \ + _val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \ + } while (0) + +#define MAX77650_REGULATOR_SBB1_SEL_INCR(_val) \ + do { \ + _val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \ + _val++; \ + _val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \ + } while (0) + +static const unsigned int max77650_current_limit_table[] = { + 1000000, 866000, 707000, 500000, +}; + +static int max77650_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct max77650_regulator_desc *rdesc; + struct regmap *map; + int val, rv, en; + + rdesc = rdev_get_drvdata(rdev); + map = rdev_get_regmap(rdev); + + rv = regmap_read(map, rdesc->regB, &val); + if (rv) + return rv; + + en = MAX77650_REGULATOR_EN_CTRL_BITS(val); + + return en != MAX77650_REGULATOR_DISABLED; +} + +static int max77650_regulator_enable(struct regulator_dev *rdev) +{ + struct max77650_regulator_desc *rdesc; + struct regmap *map; + + rdesc = rdev_get_drvdata(rdev); + map = rdev_get_regmap(rdev); + + return regmap_update_bits(map, rdesc->regB, + MAX77650_REGULATOR_EN_CTRL_MASK, + MAX77650_REGULATOR_ENABLED); +} + +static int max77650_regulator_disable(struct regulator_dev *rdev) +{ + struct max77650_regulator_desc *rdesc; + struct regmap *map; + + rdesc = rdev_get_drvdata(rdev); + map = rdev_get_regmap(rdev); + + return regmap_update_bits(map, rdesc->regB, + MAX77650_REGULATOR_EN_CTRL_MASK, + MAX77650_REGULATOR_DISABLED); +} + +static int max77650_regulator_set_voltage_sel(struct regulator_dev *rdev, + unsigned int sel) +{ + int rv = 0, curr, diff; + bool ascending; + + /* + * If the regulator is disabled, we can program the desired + * voltage right away. + */ + if (!max77650_regulator_is_enabled(rdev)) + return regulator_set_voltage_sel_regmap(rdev, sel); + + /* + * Otherwise we need to manually ramp the output voltage up/down + * one step at a time. + */ + + curr = regulator_get_voltage_sel_regmap(rdev); + if (curr < 0) + return curr; + + diff = curr - sel; + if (diff == 0) + return 0; /* Already there. */ + else if (diff > 0) + ascending = false; + else + ascending = true; + + /* + * Make sure we'll get to the right voltage and break the loop even if + * the selector equals 0. + */ + for (ascending ? curr++ : curr--;; ascending ? curr++ : curr--) { + rv = regulator_set_voltage_sel_regmap(rdev, curr); + if (rv) + return rv; + + if (curr == sel) + break; + } + + return 0; +} + +/* + * Special case: non-linear voltage table for max77651 SBB1 - software + * must ensure the voltage is ramped in 50mV increments. + */ +static int max77651_regulator_sbb1_set_voltage_sel(struct regulator_dev *rdev, + unsigned int sel) +{ + int rv = 0, curr, vcurr, vdest, vdiff; + + /* + * If the regulator is disabled, we can program the desired + * voltage right away. + */ + if (!max77650_regulator_is_enabled(rdev)) + return regulator_set_voltage_sel_regmap(rdev, sel); + + curr = regulator_get_voltage_sel_regmap(rdev); + if (curr < 0) + return curr; + + if (curr == sel) + return 0; /* Already there. */ + + vcurr = max77651_sbb1_regulator_volt_table[curr]; + vdest = max77651_sbb1_regulator_volt_table[sel]; + vdiff = vcurr - vdest; + + for (;;) { + if (vdiff > 0) + MAX77650_REGULATOR_SBB1_SEL_DECR(curr); + else + MAX77650_REGULATOR_SBB1_SEL_INCR(curr); + + rv = regulator_set_voltage_sel_regmap(rdev, curr); + if (rv) + return rv; + + if (curr == sel) + break; + }; + + return 0; +} + +static const struct regulator_ops max77650_regulator_LDO_ops = { + .is_enabled = max77650_regulator_is_enabled, + .enable = max77650_regulator_enable, + .disable = max77650_regulator_disable, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = max77650_regulator_set_voltage_sel, + .set_active_discharge = regulator_set_active_discharge_regmap, +}; + +static const struct regulator_ops max77650_regulator_SBB_ops = { + .is_enabled = max77650_regulator_is_enabled, + .enable = max77650_regulator_enable, + .disable = max77650_regulator_disable, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = max77650_regulator_set_voltage_sel, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, +}; + +/* Special case for max77651 SBB1 - non-linear voltage mapping. */ +static const struct regulator_ops max77651_SBB1_regulator_ops = { + .is_enabled = max77650_regulator_is_enabled, + .enable = max77650_regulator_enable, + .disable = max77650_regulator_disable, + .list_voltage = regulator_list_voltage_table, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = max77651_regulator_sbb1_set_voltage_sel, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, +}; + +static struct max77650_regulator_desc max77650_LDO_desc = { + .desc = { + .name = "ldo", + .of_match = of_match_ptr("ldo"), + .regulators_node = of_match_ptr("regulators"), + .supply_name = "in-ldo", + .id = MAX77650_REGULATOR_ID_LDO, + .ops = &max77650_regulator_LDO_ops, + .min_uV = 1350000, + .uV_step = 12500, + .n_voltages = 128, + .vsel_mask = MAX77650_REGULATOR_V_LDO_MASK, + .vsel_reg = MAX77650_REG_CNFG_LDO_A, + .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, + .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, + .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77650_REG_CNFG_LDO_B, + .enable_time = 100, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .regA = MAX77650_REG_CNFG_LDO_A, + .regB = MAX77650_REG_CNFG_LDO_B, +}; + +static struct max77650_regulator_desc max77650_SBB0_desc = { + .desc = { + .name = "sbb0", + .of_match = of_match_ptr("sbb0"), + .regulators_node = of_match_ptr("regulators"), + .supply_name = "in-sbb0", + .id = MAX77650_REGULATOR_ID_SBB0, + .ops = &max77650_regulator_SBB_ops, + .min_uV = 800000, + .uV_step = 25000, + .n_voltages = 64, + .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, + .vsel_reg = MAX77650_REG_CNFG_SBB0_A, + .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, + .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, + .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77650_REG_CNFG_SBB0_B, + .enable_time = 100, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .csel_reg = MAX77650_REG_CNFG_SBB0_A, + .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK, + .curr_table = max77650_current_limit_table, + .n_current_limits = ARRAY_SIZE(max77650_current_limit_table), + }, + .regA = MAX77650_REG_CNFG_SBB0_A, + .regB = MAX77650_REG_CNFG_SBB0_B, +}; + +static struct max77650_regulator_desc max77650_SBB1_desc = { + .desc = { + .name = "sbb1", + .of_match = of_match_ptr("sbb1"), + .regulators_node = of_match_ptr("regulators"), + .supply_name = "in-sbb1", + .id = MAX77650_REGULATOR_ID_SBB1, + .ops = &max77650_regulator_SBB_ops, + .min_uV = 800000, + .uV_step = 12500, + .n_voltages = 64, + .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, + .vsel_reg = MAX77650_REG_CNFG_SBB1_A, + .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, + .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, + .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B, + .enable_time = 100, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .csel_reg = MAX77650_REG_CNFG_SBB1_A, + .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK, + .curr_table = max77650_current_limit_table, + .n_current_limits = ARRAY_SIZE(max77650_current_limit_table), + }, + .regA = MAX77650_REG_CNFG_SBB1_A, + .regB = MAX77650_REG_CNFG_SBB1_B, +}; + +static struct max77650_regulator_desc max77651_SBB1_desc = { + .desc = { + .name = "sbb1", + .of_match = of_match_ptr("sbb1"), + .regulators_node = of_match_ptr("regulators"), + .supply_name = "in-sbb1", + .id = MAX77650_REGULATOR_ID_SBB1, + .ops = &max77651_SBB1_regulator_ops, + .volt_table = max77651_sbb1_regulator_volt_table, + .n_voltages = ARRAY_SIZE(max77651_sbb1_regulator_volt_table), + .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, + .vsel_reg = MAX77650_REG_CNFG_SBB1_A, + .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, + .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, + .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B, + .enable_time = 100, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .csel_reg = MAX77650_REG_CNFG_SBB1_A, + .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK, + .curr_table = max77650_current_limit_table, + .n_current_limits = ARRAY_SIZE(max77650_current_limit_table), + }, + .regA = MAX77650_REG_CNFG_SBB1_A, + .regB = MAX77650_REG_CNFG_SBB1_B, +}; + +static struct max77650_regulator_desc max77650_SBB2_desc = { + .desc = { + .name = "sbb2", + .of_match = of_match_ptr("sbb2"), + .regulators_node = of_match_ptr("regulators"), + .supply_name = "in-sbb0", + .id = MAX77650_REGULATOR_ID_SBB2, + .ops = &max77650_regulator_SBB_ops, + .min_uV = 800000, + .uV_step = 50000, + .n_voltages = 64, + .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, + .vsel_reg = MAX77650_REG_CNFG_SBB2_A, + .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, + .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, + .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B, + .enable_time = 100, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .csel_reg = MAX77650_REG_CNFG_SBB2_A, + .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK, + .curr_table = max77650_current_limit_table, + .n_current_limits = ARRAY_SIZE(max77650_current_limit_table), + }, + .regA = MAX77650_REG_CNFG_SBB2_A, + .regB = MAX77650_REG_CNFG_SBB2_B, +}; + +static struct max77650_regulator_desc max77651_SBB2_desc = { + .desc = { + .name = "sbb2", + .of_match = of_match_ptr("sbb2"), + .regulators_node = of_match_ptr("regulators"), + .supply_name = "in-sbb0", + .id = MAX77650_REGULATOR_ID_SBB2, + .ops = &max77650_regulator_SBB_ops, + .min_uV = 2400000, + .uV_step = 50000, + .n_voltages = 64, + .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, + .vsel_reg = MAX77650_REG_CNFG_SBB2_A, + .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, + .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, + .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B, + .enable_time = 100, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .csel_reg = MAX77650_REG_CNFG_SBB2_A, + .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK, + .curr_table = max77650_current_limit_table, + .n_current_limits = ARRAY_SIZE(max77650_current_limit_table), + }, + .regA = MAX77650_REG_CNFG_SBB2_A, + .regB = MAX77650_REG_CNFG_SBB2_B, +}; + +static int max77650_regulator_probe(struct platform_device *pdev) +{ + struct max77650_regulator_desc **rdescs; + struct max77650_regulator_desc *rdesc; + struct regulator_config config = { }; + struct device *dev, *parent; + struct regulator_dev *rdev; + struct regmap *map; + unsigned int val; + int i, rv; + + dev = &pdev->dev; + parent = dev->parent; + + if (!dev->of_node) + dev->of_node = parent->of_node; + + rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS, + sizeof(*rdescs), GFP_KERNEL); + if (!rdescs) + return -ENOMEM; + + map = dev_get_regmap(parent, NULL); + if (!map) + return -ENODEV; + + rv = regmap_read(map, MAX77650_REG_CID, &val); + if (rv) + return rv; + + rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc; + rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc; + + switch (MAX77650_CID_BITS(val)) { + case MAX77650_CID_77650A: + case MAX77650_CID_77650C: + rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc; + rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc; + break; + case MAX77650_CID_77651A: + case MAX77650_CID_77651B: + rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc; + rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc; + break; + default: + return -ENODEV; + } + + config.dev = parent; + + for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) { + rdesc = rdescs[i]; + config.driver_data = rdesc; + + rdev = devm_regulator_register(dev, &rdesc->desc, &config); + if (IS_ERR(rdev)) + return PTR_ERR(rdev); + } + + return 0; +} + +static struct platform_driver max77650_regulator_driver = { + .driver = { + .name = "max77650-regulator", + }, + .probe = max77650_regulator_probe, +}; +module_platform_driver(max77650_regulator_driver); + +MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver"); +MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/max77802-regulator.c b/drivers/regulator/max77802-regulator.c index c30cf5c9f2de..ea7b50397300 100644 --- a/drivers/regulator/max77802-regulator.c +++ b/drivers/regulator/max77802-regulator.c @@ -248,9 +248,9 @@ static int max77802_set_ramp_delay_2bit(struct regulator_dev *rdev, unsigned int ramp_value; if (id > MAX77802_BUCK4) { - dev_warn(&rdev->dev, - "%s: regulator: ramp delay not supported\n", - rdev->desc->name); + dev_warn(&rdev->dev, + "%s: regulator: ramp delay not supported\n", + rdev->desc->name); return -EINVAL; } ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_2bit, diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 8fd1adc9c9a9..ab558b26cd7c 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -226,69 +226,69 @@ static const unsigned int mc13783_pwgtdrv_val[] = { 5500000, }; -static struct regulator_ops mc13783_gpo_regulator_ops; +static const struct regulator_ops mc13783_gpo_regulator_ops; -#define MC13783_DEFINE(prefix, name, reg, vsel_reg, voltages) \ - MC13xxx_DEFINE(MC13783_REG_, name, reg, vsel_reg, voltages, \ +#define MC13783_DEFINE(prefix, name, node, reg, vsel_reg, voltages) \ + MC13xxx_DEFINE(MC13783_REG_, name, node, reg, vsel_reg, voltages, \ mc13xxx_regulator_ops) -#define MC13783_FIXED_DEFINE(prefix, name, reg, voltages) \ - MC13xxx_FIXED_DEFINE(MC13783_REG_, name, reg, voltages, \ +#define MC13783_FIXED_DEFINE(prefix, name, node, reg, voltages) \ + MC13xxx_FIXED_DEFINE(MC13783_REG_, name, node, reg, voltages, \ mc13xxx_fixed_regulator_ops) -#define MC13783_GPO_DEFINE(prefix, name, reg, voltages) \ - MC13xxx_GPO_DEFINE(MC13783_REG_, name, reg, voltages, \ +#define MC13783_GPO_DEFINE(prefix, name, node, reg, voltages) \ + MC13xxx_GPO_DEFINE(MC13783_REG_, name, node, reg, voltages, \ mc13783_gpo_regulator_ops) -#define MC13783_DEFINE_SW(_name, _reg, _vsel_reg, _voltages) \ - MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages) -#define MC13783_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages) \ - MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages) +#define MC13783_DEFINE_SW(_name, _node, _reg, _vsel_reg, _voltages) \ + MC13783_DEFINE(REG, _name, _node, _reg, _vsel_reg, _voltages) +#define MC13783_DEFINE_REGU(_name, _node, _reg, _vsel_reg, _voltages) \ + MC13783_DEFINE(REG, _name, _node, _reg, _vsel_reg, _voltages) static struct mc13xxx_regulator mc13783_regulators[] = { - MC13783_DEFINE_SW(SW1A, SWITCHERS0, SWITCHERS0, mc13783_sw1x_val), - MC13783_DEFINE_SW(SW1B, SWITCHERS1, SWITCHERS1, mc13783_sw1x_val), - MC13783_DEFINE_SW(SW2A, SWITCHERS2, SWITCHERS2, mc13783_sw2x_val), - MC13783_DEFINE_SW(SW2B, SWITCHERS3, SWITCHERS3, mc13783_sw2x_val), - MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val), - - MC13783_FIXED_DEFINE(REG, VAUDIO, REGULATORMODE0, mc13783_vaudio_val), - MC13783_FIXED_DEFINE(REG, VIOHI, REGULATORMODE0, mc13783_viohi_val), - MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0, + MC13783_DEFINE_SW(SW1A, sw1a, SWITCHERS0, SWITCHERS0, mc13783_sw1x_val), + MC13783_DEFINE_SW(SW1B, sw1b, SWITCHERS1, SWITCHERS1, mc13783_sw1x_val), + MC13783_DEFINE_SW(SW2A, sw2a, SWITCHERS2, SWITCHERS2, mc13783_sw2x_val), + MC13783_DEFINE_SW(SW2B, sw2b, SWITCHERS3, SWITCHERS3, mc13783_sw2x_val), + MC13783_DEFINE_SW(SW3, sw3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val), + + MC13783_FIXED_DEFINE(REG, VAUDIO, vaudio, REGULATORMODE0, mc13783_vaudio_val), + MC13783_FIXED_DEFINE(REG, VIOHI, viohi, REGULATORMODE0, mc13783_viohi_val), + MC13783_DEFINE_REGU(VIOLO, violo, REGULATORMODE0, REGULATORSETTING0, mc13783_violo_val), - MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, + MC13783_DEFINE_REGU(VDIG, vdig, REGULATORMODE0, REGULATORSETTING0, mc13783_vdig_val), - MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0, + MC13783_DEFINE_REGU(VGEN, vgen, REGULATORMODE0, REGULATORSETTING0, mc13783_vgen_val), - MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0, + MC13783_DEFINE_REGU(VRFDIG, vrfdig, REGULATORMODE0, REGULATORSETTING0, mc13783_vrfdig_val), - MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0, + MC13783_DEFINE_REGU(VRFREF, vrfref, REGULATORMODE0, REGULATORSETTING0, mc13783_vrfref_val), - MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0, + MC13783_DEFINE_REGU(VRFCP, vrfcp, REGULATORMODE0, REGULATORSETTING0, mc13783_vrfcp_val), - MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0, + MC13783_DEFINE_REGU(VSIM, vsim, REGULATORMODE1, REGULATORSETTING0, mc13783_vsim_val), - MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0, + MC13783_DEFINE_REGU(VESIM, vesim, REGULATORMODE1, REGULATORSETTING0, mc13783_vesim_val), - MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, + MC13783_DEFINE_REGU(VCAM, vcam, REGULATORMODE1, REGULATORSETTING0, mc13783_vcam_val), - MC13783_FIXED_DEFINE(REG, VRFBG, REGULATORMODE1, mc13783_vrfbg_val), - MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1, + MC13783_FIXED_DEFINE(REG, VRFBG, vrfbg, REGULATORMODE1, mc13783_vrfbg_val), + MC13783_DEFINE_REGU(VVIB, vvib, REGULATORMODE1, REGULATORSETTING1, mc13783_vvib_val), - MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1, + MC13783_DEFINE_REGU(VRF1, vrf1, REGULATORMODE1, REGULATORSETTING1, mc13783_vrf_val), - MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1, + MC13783_DEFINE_REGU(VRF2, vrf2, REGULATORMODE1, REGULATORSETTING1, mc13783_vrf_val), - MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1, + MC13783_DEFINE_REGU(VMMC1, vmmc1, REGULATORMODE1, REGULATORSETTING1, mc13783_vmmc_val), - MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1, + MC13783_DEFINE_REGU(VMMC2, vmmc2, REGULATORMODE1, REGULATORSETTING1, mc13783_vmmc_val), - MC13783_GPO_DEFINE(REG, GPO1, POWERMISC, mc13783_gpo_val), - MC13783_GPO_DEFINE(REG, GPO2, POWERMISC, mc13783_gpo_val), - MC13783_GPO_DEFINE(REG, GPO3, POWERMISC, mc13783_gpo_val), - MC13783_GPO_DEFINE(REG, GPO4, POWERMISC, mc13783_gpo_val), - MC13783_GPO_DEFINE(REG, PWGT1SPI, POWERMISC, mc13783_pwgtdrv_val), - MC13783_GPO_DEFINE(REG, PWGT2SPI, POWERMISC, mc13783_pwgtdrv_val), + MC13783_GPO_DEFINE(REG, GPO1, gpo1, POWERMISC, mc13783_gpo_val), + MC13783_GPO_DEFINE(REG, GPO2, gpo1, POWERMISC, mc13783_gpo_val), + MC13783_GPO_DEFINE(REG, GPO3, gpo1, POWERMISC, mc13783_gpo_val), + MC13783_GPO_DEFINE(REG, GPO4, gpo1, POWERMISC, mc13783_gpo_val), + MC13783_GPO_DEFINE(REG, PWGT1SPI, pwgt1spi, POWERMISC, mc13783_pwgtdrv_val), + MC13783_GPO_DEFINE(REG, PWGT2SPI, pwgt2spi, POWERMISC, mc13783_pwgtdrv_val), }; static int mc13783_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, @@ -380,7 +380,7 @@ static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev) return (val & mc13xxx_regulators[id].enable_bit) != 0; } -static struct regulator_ops mc13783_gpo_regulator_ops = { +static const struct regulator_ops mc13783_gpo_regulator_ops = { .enable = mc13783_gpo_regulator_enable, .disable = mc13783_gpo_regulator_disable, .is_enabled = mc13783_gpo_regulator_is_enabled, diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index f3fba1cc1379..a731e826a037 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -242,61 +242,61 @@ static const unsigned int mc13892_pwgtdrv[] = { 5000000, }; -static struct regulator_ops mc13892_gpo_regulator_ops; -static struct regulator_ops mc13892_sw_regulator_ops; +static const struct regulator_ops mc13892_gpo_regulator_ops; +static const struct regulator_ops mc13892_sw_regulator_ops; -#define MC13892_FIXED_DEFINE(name, reg, voltages) \ - MC13xxx_FIXED_DEFINE(MC13892_, name, reg, voltages, \ +#define MC13892_FIXED_DEFINE(name, node, reg, voltages) \ + MC13xxx_FIXED_DEFINE(MC13892_, name, node, reg, voltages, \ mc13xxx_fixed_regulator_ops) -#define MC13892_GPO_DEFINE(name, reg, voltages) \ - MC13xxx_GPO_DEFINE(MC13892_, name, reg, voltages, \ +#define MC13892_GPO_DEFINE(name, node, reg, voltages) \ + MC13xxx_GPO_DEFINE(MC13892_, name, node, reg, voltages, \ mc13892_gpo_regulator_ops) -#define MC13892_SW_DEFINE(name, reg, vsel_reg, voltages) \ - MC13xxx_DEFINE(MC13892_, name, reg, vsel_reg, voltages, \ +#define MC13892_SW_DEFINE(name, node, reg, vsel_reg, voltages) \ + MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \ mc13892_sw_regulator_ops) -#define MC13892_DEFINE_REGU(name, reg, vsel_reg, voltages) \ - MC13xxx_DEFINE(MC13892_, name, reg, vsel_reg, voltages, \ +#define MC13892_DEFINE_REGU(name, node, reg, vsel_reg, voltages) \ + MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \ mc13xxx_regulator_ops) static struct mc13xxx_regulator mc13892_regulators[] = { - MC13892_DEFINE_REGU(VCOINCELL, POWERCTL0, POWERCTL0, mc13892_vcoincell), - MC13892_SW_DEFINE(SW1, SWITCHERS0, SWITCHERS0, mc13892_sw1), - MC13892_SW_DEFINE(SW2, SWITCHERS1, SWITCHERS1, mc13892_sw), - MC13892_SW_DEFINE(SW3, SWITCHERS2, SWITCHERS2, mc13892_sw), - MC13892_SW_DEFINE(SW4, SWITCHERS3, SWITCHERS3, mc13892_sw), - MC13892_FIXED_DEFINE(SWBST, SWITCHERS5, mc13892_swbst), - MC13892_FIXED_DEFINE(VIOHI, REGULATORMODE0, mc13892_viohi), - MC13892_DEFINE_REGU(VPLL, REGULATORMODE0, REGULATORSETTING0, + MC13892_DEFINE_REGU(VCOINCELL, vcoincell, POWERCTL0, POWERCTL0, mc13892_vcoincell), + MC13892_SW_DEFINE(SW1, sw1, SWITCHERS0, SWITCHERS0, mc13892_sw1), + MC13892_SW_DEFINE(SW2, sw2, SWITCHERS1, SWITCHERS1, mc13892_sw), + MC13892_SW_DEFINE(SW3, sw3, SWITCHERS2, SWITCHERS2, mc13892_sw), + MC13892_SW_DEFINE(SW4, sw4, SWITCHERS3, SWITCHERS3, mc13892_sw), + MC13892_FIXED_DEFINE(SWBST, swbst, SWITCHERS5, mc13892_swbst), + MC13892_FIXED_DEFINE(VIOHI, viohi, REGULATORMODE0, mc13892_viohi), + MC13892_DEFINE_REGU(VPLL, vpll, REGULATORMODE0, REGULATORSETTING0, mc13892_vpll), - MC13892_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, + MC13892_DEFINE_REGU(VDIG, vdig, REGULATORMODE0, REGULATORSETTING0, mc13892_vdig), - MC13892_DEFINE_REGU(VSD, REGULATORMODE1, REGULATORSETTING1, + MC13892_DEFINE_REGU(VSD, vsd, REGULATORMODE1, REGULATORSETTING1, mc13892_vsd), - MC13892_DEFINE_REGU(VUSB2, REGULATORMODE0, REGULATORSETTING0, + MC13892_DEFINE_REGU(VUSB2, vusb2, REGULATORMODE0, REGULATORSETTING0, mc13892_vusb2), - MC13892_DEFINE_REGU(VVIDEO, REGULATORMODE1, REGULATORSETTING1, + MC13892_DEFINE_REGU(VVIDEO, vvideo, REGULATORMODE1, REGULATORSETTING1, mc13892_vvideo), - MC13892_DEFINE_REGU(VAUDIO, REGULATORMODE1, REGULATORSETTING1, + MC13892_DEFINE_REGU(VAUDIO, vaudio, REGULATORMODE1, REGULATORSETTING1, mc13892_vaudio), - MC13892_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, + MC13892_DEFINE_REGU(VCAM, vcam, REGULATORMODE1, REGULATORSETTING0, mc13892_vcam), - MC13892_DEFINE_REGU(VGEN1, REGULATORMODE0, REGULATORSETTING0, + MC13892_DEFINE_REGU(VGEN1, vgen1, REGULATORMODE0, REGULATORSETTING0, mc13892_vgen1), - MC13892_DEFINE_REGU(VGEN2, REGULATORMODE0, REGULATORSETTING0, + MC13892_DEFINE_REGU(VGEN2, vgen2, REGULATORMODE0, REGULATORSETTING0, mc13892_vgen2), - MC13892_DEFINE_REGU(VGEN3, REGULATORMODE1, REGULATORSETTING0, + MC13892_DEFINE_REGU(VGEN3, vgen3, REGULATORMODE1, REGULATORSETTING0, mc13892_vgen3), - MC13892_FIXED_DEFINE(VUSB, USB1, mc13892_vusb), - MC13892_GPO_DEFINE(GPO1, POWERMISC, mc13892_gpo), - MC13892_GPO_DEFINE(GPO2, POWERMISC, mc13892_gpo), - MC13892_GPO_DEFINE(GPO3, POWERMISC, mc13892_gpo), - MC13892_GPO_DEFINE(GPO4, POWERMISC, mc13892_gpo), - MC13892_GPO_DEFINE(PWGT1SPI, POWERMISC, mc13892_pwgtdrv), - MC13892_GPO_DEFINE(PWGT2SPI, POWERMISC, mc13892_pwgtdrv), + MC13892_FIXED_DEFINE(VUSB, vusb, USB1, mc13892_vusb), + MC13892_GPO_DEFINE(GPO1, gpo1, POWERMISC, mc13892_gpo), + MC13892_GPO_DEFINE(GPO2, gpo2, POWERMISC, mc13892_gpo), + MC13892_GPO_DEFINE(GPO3, gpo3, POWERMISC, mc13892_gpo), + MC13892_GPO_DEFINE(GPO4, gpo4, POWERMISC, mc13892_gpo), + MC13892_GPO_DEFINE(PWGT1SPI, pwgt1spi, POWERMISC, mc13892_pwgtdrv), + MC13892_GPO_DEFINE(PWGT2SPI, pwgt2spi, POWERMISC, mc13892_pwgtdrv), }; static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, @@ -387,7 +387,7 @@ static int mc13892_gpo_regulator_is_enabled(struct regulator_dev *rdev) } -static struct regulator_ops mc13892_gpo_regulator_ops = { +static const struct regulator_ops mc13892_gpo_regulator_ops = { .enable = mc13892_gpo_regulator_enable, .disable = mc13892_gpo_regulator_disable, .is_enabled = mc13892_gpo_regulator_is_enabled, @@ -479,7 +479,7 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, return ret; } -static struct regulator_ops mc13892_sw_regulator_ops = { +static const struct regulator_ops mc13892_sw_regulator_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .set_voltage_sel = mc13892_sw_regulator_set_voltage_sel, diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 2243138d8a58..8ff19150ca92 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -99,7 +99,7 @@ static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev) return rdev->desc->volt_table[val]; } -struct regulator_ops mc13xxx_regulator_ops = { +const struct regulator_ops mc13xxx_regulator_ops = { .enable = mc13xxx_regulator_enable, .disable = mc13xxx_regulator_disable, .is_enabled = mc13xxx_regulator_is_enabled, @@ -127,7 +127,7 @@ int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, } EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage); -struct regulator_ops mc13xxx_fixed_regulator_ops = { +const struct regulator_ops mc13xxx_fixed_regulator_ops = { .enable = mc13xxx_regulator_enable, .disable = mc13xxx_regulator_disable, .is_enabled = mc13xxx_regulator_is_enabled, diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h index 2ab9bfd93b4e..ba7eff1070bd 100644 --- a/drivers/regulator/mc13xxx.h +++ b/drivers/regulator/mc13xxx.h @@ -53,13 +53,13 @@ static inline struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( } #endif -extern struct regulator_ops mc13xxx_regulator_ops; -extern struct regulator_ops mc13xxx_fixed_regulator_ops; +extern const struct regulator_ops mc13xxx_regulator_ops; +extern const struct regulator_ops mc13xxx_fixed_regulator_ops; -#define MC13xxx_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages, _ops) \ +#define MC13xxx_DEFINE(prefix, _name, _node, _reg, _vsel_reg, _voltages, _ops) \ [prefix ## _name] = { \ .desc = { \ - .name = #_name, \ + .name = #_node, \ .n_voltages = ARRAY_SIZE(_voltages), \ .volt_table = _voltages, \ .ops = &_ops, \ @@ -74,10 +74,10 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops; .vsel_mask = prefix ## _vsel_reg ## _ ## _name ## VSEL_M,\ } -#define MC13xxx_FIXED_DEFINE(prefix, _name, _reg, _voltages, _ops) \ +#define MC13xxx_FIXED_DEFINE(prefix, _name, _node, _reg, _voltages, _ops) \ [prefix ## _name] = { \ .desc = { \ - .name = #_name, \ + .name = #_node, \ .n_voltages = ARRAY_SIZE(_voltages), \ .volt_table = _voltages, \ .ops = &_ops, \ @@ -89,10 +89,10 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops; .enable_bit = prefix ## _reg ## _ ## _name ## EN, \ } -#define MC13xxx_GPO_DEFINE(prefix, _name, _reg, _voltages, _ops) \ +#define MC13xxx_GPO_DEFINE(prefix, _name, _node, _reg, _voltages, _ops) \ [prefix ## _name] = { \ .desc = { \ - .name = #_name, \ + .name = #_node, \ .n_voltages = ARRAY_SIZE(_voltages), \ .volt_table = _voltages, \ .ops = &_ops, \ @@ -104,9 +104,9 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops; .enable_bit = prefix ## _reg ## _ ## _name ## EN, \ } -#define MC13xxx_DEFINE_SW(_name, _reg, _vsel_reg, _voltages, ops) \ - MC13xxx_DEFINE(SW, _name, _reg, _vsel_reg, _voltages, ops) -#define MC13xxx_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages, ops) \ - MC13xxx_DEFINE(REGU, _name, _reg, _vsel_reg, _voltages, ops) +#define MC13xxx_DEFINE_SW(_name, _node, _reg, _vsel_reg, _voltages, ops) \ + MC13xxx_DEFINE(SW, _name, _node, _reg, _vsel_reg, _voltages, ops) +#define MC13xxx_DEFINE_REGU(_name, _node, _reg, _vsel_reg, _voltages, ops) \ + MC13xxx_DEFINE(REGU, _name, _node, _reg, _vsel_reg, _voltages, ops) #endif diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c index 3479ae009b0b..3a8004abe044 100644 --- a/drivers/regulator/mcp16502.c +++ b/drivers/regulator/mcp16502.c @@ -17,6 +17,7 @@ #include <linux/regmap.h> #include <linux/regulator/driver.h> #include <linux/suspend.h> +#include <linux/gpio/consumer.h> #define VDD_LOW_SEL 0x0D #define VDD_HIGH_SEL 0x3F @@ -546,7 +547,6 @@ static struct i2c_driver mcp16502_drv = { module_i2c_driver(mcp16502_drv); -MODULE_VERSION("1.0"); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("MCP16502 PMIC driver"); MODULE_AUTHOR("Andrei Stefanescu andrei.stefanescu@microchip.com"); diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c index 0495716fd35f..01d69f43d2b0 100644 --- a/drivers/regulator/mt6311-regulator.c +++ b/drivers/regulator/mt6311-regulator.c @@ -38,13 +38,9 @@ static const struct regmap_config mt6311_regmap_config = { #define MT6311_MAX_UV 1393750 #define MT6311_STEP_UV 6250 -static const struct regulator_linear_range buck_volt_range[] = { - REGULATOR_LINEAR_RANGE(MT6311_MIN_UV, 0, 0x7f, MT6311_STEP_UV), -}; - static const struct regulator_ops mt6311_buck_ops = { - .list_voltage = regulator_list_voltage_linear_range, - .map_voltage = regulator_map_voltage_linear_range, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_time_sel = regulator_set_voltage_time_sel, @@ -71,8 +67,6 @@ static const struct regulator_ops mt6311_ldo_ops = { .min_uV = MT6311_MIN_UV,\ .uV_step = MT6311_STEP_UV,\ .owner = THIS_MODULE,\ - .linear_ranges = buck_volt_range, \ - .n_linear_ranges = ARRAY_SIZE(buck_volt_range), \ .enable_reg = MT6311_VDVFS11_CON9,\ .enable_mask = MT6311_PMIC_VDVFS11_EN_MASK,\ .vsel_reg = MT6311_VDVFS11_CON12,\ diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index ffa5fc3724e4..7b6bf3536271 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -255,7 +255,7 @@ static void of_get_regulation_constraints(struct device_node *np, * @desc: regulator description * * Populates regulator_init_data structure by extracting data from device - * tree node, returns a pointer to the populated struture or NULL if memory + * tree node, returns a pointer to the populated structure or NULL if memory * alloc fails. */ struct regulator_init_data *of_get_regulator_init_data(struct device *dev, @@ -547,7 +547,7 @@ bool of_check_coupling_data(struct regulator_dev *rdev) NULL); if (c_n_phandles != n_phandles) { - dev_err(&rdev->dev, "number of couped reg phandles mismatch\n"); + dev_err(&rdev->dev, "number of coupled reg phandles mismatch\n"); ret = false; goto clean; } diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index c2cc392a27d4..7fb9e8dd834e 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -382,7 +382,7 @@ static struct palmas_sleep_requestor_info tps65917_sleep_req_info[] = { EXTERNAL_REQUESTOR_TPS65917(LDO5, 2, 4), }; -static unsigned int palmas_smps_ramp_delay[4] = {0, 10000, 5000, 2500}; +static const unsigned int palmas_smps_ramp_delay[4] = {0, 10000, 5000, 2500}; #define SMPS_CTRL_MODE_OFF 0x00 #define SMPS_CTRL_MODE_ON 0x01 diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c index a9446056435f..1600f9821891 100644 --- a/drivers/regulator/pv88060-regulator.c +++ b/drivers/regulator/pv88060-regulator.c @@ -53,10 +53,6 @@ enum { struct pv88060_regulator { struct regulator_desc desc; - /* Current limiting */ - unsigned n_current_limits; - const int *current_limits; - unsigned int limit_mask; unsigned int conf; /* buck configuration register */ }; @@ -75,7 +71,7 @@ static const struct regmap_config pv88060_regmap_config = { * Entry indexes corresponds to register values. */ -static const int pv88060_buck1_limits[] = { +static const unsigned int pv88060_buck1_limits[] = { 1496000, 2393000, 3291000, 4189000 }; @@ -128,40 +124,6 @@ static int pv88060_buck_set_mode(struct regulator_dev *rdev, PV88060_BUCK_MODE_MASK, val); } -static int pv88060_set_current_limit(struct regulator_dev *rdev, int min, - int max) -{ - struct pv88060_regulator *info = rdev_get_drvdata(rdev); - int i; - - /* search for closest to maximum */ - for (i = info->n_current_limits; i >= 0; i--) { - if (min <= info->current_limits[i] - && max >= info->current_limits[i]) { - return regmap_update_bits(rdev->regmap, - info->conf, - info->limit_mask, - i << PV88060_BUCK_ILIM_SHIFT); - } - } - - return -EINVAL; -} - -static int pv88060_get_current_limit(struct regulator_dev *rdev) -{ - struct pv88060_regulator *info = rdev_get_drvdata(rdev); - unsigned int data; - int ret; - - ret = regmap_read(rdev->regmap, info->conf, &data); - if (ret < 0) - return ret; - - data = (data & info->limit_mask) >> PV88060_BUCK_ILIM_SHIFT; - return info->current_limits[data]; -} - static const struct regulator_ops pv88060_buck_ops = { .get_mode = pv88060_buck_get_mode, .set_mode = pv88060_buck_set_mode, @@ -171,8 +133,8 @@ static const struct regulator_ops pv88060_buck_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear, - .set_current_limit = pv88060_set_current_limit, - .get_current_limit = pv88060_get_current_limit, + .set_current_limit = regulator_set_current_limit_regmap, + .get_current_limit = regulator_get_current_limit_regmap, }; static const struct regulator_ops pv88060_ldo_ops = { @@ -184,6 +146,12 @@ static const struct regulator_ops pv88060_ldo_ops = { .list_voltage = regulator_list_voltage_linear, }; +static const struct regulator_ops pv88060_sw_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + #define PV88060_BUCK(chip, regl_name, min, step, max, limits_array) \ {\ .desc = {\ @@ -201,10 +169,11 @@ static const struct regulator_ops pv88060_ldo_ops = { .enable_mask = PV88060_BUCK_EN, \ .vsel_reg = PV88060_REG_##regl_name##_CONF0,\ .vsel_mask = PV88060_VBUCK_MASK,\ + .curr_table = limits_array,\ + .n_current_limits = ARRAY_SIZE(limits_array),\ + .csel_reg = PV88060_REG_##regl_name##_CONF1,\ + .csel_mask = PV88060_BUCK_ILIM_MASK,\ },\ - .current_limits = limits_array,\ - .n_current_limits = ARRAY_SIZE(limits_array),\ - .limit_mask = PV88060_BUCK_ILIM_MASK, \ .conf = PV88060_REG_##regl_name##_CONF1,\ } @@ -237,9 +206,8 @@ static const struct regulator_ops pv88060_ldo_ops = { .regulators_node = of_match_ptr("regulators"),\ .type = REGULATOR_VOLTAGE,\ .owner = THIS_MODULE,\ - .ops = &pv88060_ldo_ops,\ - .min_uV = max,\ - .uV_step = 0,\ + .ops = &pv88060_sw_ops,\ + .fixed_uV = max,\ .n_voltages = 1,\ .enable_reg = PV88060_REG_##regl_name##_CONF,\ .enable_mask = PV88060_SW_EN,\ diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c index 9a08cb2de501..bdddacdbeb99 100644 --- a/drivers/regulator/pv88080-regulator.c +++ b/drivers/regulator/pv88080-regulator.c @@ -45,12 +45,7 @@ enum pv88080_types { struct pv88080_regulator { struct regulator_desc desc; - /* Current limiting */ - unsigned int n_current_limits; - const int *current_limits; - unsigned int limit_mask; unsigned int mode_reg; - unsigned int limit_reg; unsigned int conf2; unsigned int conf5; }; @@ -102,11 +97,11 @@ static const struct regmap_config pv88080_regmap_config = { * Entry indexes corresponds to register values. */ -static const int pv88080_buck1_limits[] = { +static const unsigned int pv88080_buck1_limits[] = { 3230000, 5130000, 6960000, 8790000 }; -static const int pv88080_buck23_limits[] = { +static const unsigned int pv88080_buck23_limits[] = { 1496000, 2393000, 3291000, 4189000 }; @@ -272,40 +267,6 @@ static int pv88080_buck_set_mode(struct regulator_dev *rdev, PV88080_BUCK1_MODE_MASK, val); } -static int pv88080_set_current_limit(struct regulator_dev *rdev, int min, - int max) -{ - struct pv88080_regulator *info = rdev_get_drvdata(rdev); - int i; - - /* search for closest to maximum */ - for (i = info->n_current_limits; i >= 0; i--) { - if (min <= info->current_limits[i] - && max >= info->current_limits[i]) { - return regmap_update_bits(rdev->regmap, - info->limit_reg, - info->limit_mask, - i << PV88080_BUCK1_ILIM_SHIFT); - } - } - - return -EINVAL; -} - -static int pv88080_get_current_limit(struct regulator_dev *rdev) -{ - struct pv88080_regulator *info = rdev_get_drvdata(rdev); - unsigned int data; - int ret; - - ret = regmap_read(rdev->regmap, info->limit_reg, &data); - if (ret < 0) - return ret; - - data = (data & info->limit_mask) >> PV88080_BUCK1_ILIM_SHIFT; - return info->current_limits[data]; -} - static const struct regulator_ops pv88080_buck_ops = { .get_mode = pv88080_buck_get_mode, .set_mode = pv88080_buck_set_mode, @@ -315,8 +276,8 @@ static const struct regulator_ops pv88080_buck_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear, - .set_current_limit = pv88080_set_current_limit, - .get_current_limit = pv88080_get_current_limit, + .set_current_limit = regulator_set_current_limit_regmap, + .get_current_limit = regulator_get_current_limit_regmap, }; static const struct regulator_ops pv88080_hvbuck_ops = { @@ -341,9 +302,9 @@ static const struct regulator_ops pv88080_hvbuck_ops = { .min_uV = min, \ .uV_step = step, \ .n_voltages = ((max) - (min))/(step) + 1, \ + .curr_table = limits_array, \ + .n_current_limits = ARRAY_SIZE(limits_array), \ },\ - .current_limits = limits_array, \ - .n_current_limits = ARRAY_SIZE(limits_array), \ } #define PV88080_HVBUCK(chip, regl_name, min, step, max) \ @@ -521,9 +482,9 @@ static int pv88080_i2c_probe(struct i2c_client *i2c, if (init_data) config.init_data = &init_data[i]; - pv88080_regulator_info[i].limit_reg + pv88080_regulator_info[i].desc.csel_reg = regmap_config->buck_regmap[i].buck_limit_reg; - pv88080_regulator_info[i].limit_mask + pv88080_regulator_info[i].desc.csel_mask = regmap_config->buck_regmap[i].buck_limit_mask; pv88080_regulator_info[i].mode_reg = regmap_config->buck_regmap[i].buck_mode_reg; diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c index 7a0c15957bd0..6e97cc6df2ee 100644 --- a/drivers/regulator/pv88090-regulator.c +++ b/drivers/regulator/pv88090-regulator.c @@ -42,10 +42,6 @@ enum { struct pv88090_regulator { struct regulator_desc desc; - /* Current limiting */ - unsigned int n_current_limits; - const int *current_limits; - unsigned int limit_mask; unsigned int conf; unsigned int conf2; }; @@ -71,14 +67,14 @@ static const struct regmap_config pv88090_regmap_config = { * Entry indexes corresponds to register values. */ -static const int pv88090_buck1_limits[] = { +static const unsigned int pv88090_buck1_limits[] = { 220000, 440000, 660000, 880000, 1100000, 1320000, 1540000, 1760000, 1980000, 2200000, 2420000, 2640000, 2860000, 3080000, 3300000, 3520000, 3740000, 3960000, 4180000, 4400000, 4620000, 4840000, 5060000, 5280000, 5500000, 5720000, 5940000, 6160000, 6380000, 6600000, 6820000, 7040000 }; -static const int pv88090_buck23_limits[] = { +static const unsigned int pv88090_buck23_limits[] = { 1496000, 2393000, 3291000, 4189000 }; @@ -150,40 +146,6 @@ static int pv88090_buck_set_mode(struct regulator_dev *rdev, PV88090_BUCK1_MODE_MASK, val); } -static int pv88090_set_current_limit(struct regulator_dev *rdev, int min, - int max) -{ - struct pv88090_regulator *info = rdev_get_drvdata(rdev); - int i; - - /* search for closest to maximum */ - for (i = info->n_current_limits; i >= 0; i--) { - if (min <= info->current_limits[i] - && max >= info->current_limits[i]) { - return regmap_update_bits(rdev->regmap, - info->conf, - info->limit_mask, - i << PV88090_BUCK1_ILIM_SHIFT); - } - } - - return -EINVAL; -} - -static int pv88090_get_current_limit(struct regulator_dev *rdev) -{ - struct pv88090_regulator *info = rdev_get_drvdata(rdev); - unsigned int data; - int ret; - - ret = regmap_read(rdev->regmap, info->conf, &data); - if (ret < 0) - return ret; - - data = (data & info->limit_mask) >> PV88090_BUCK1_ILIM_SHIFT; - return info->current_limits[data]; -} - static const struct regulator_ops pv88090_buck_ops = { .get_mode = pv88090_buck_get_mode, .set_mode = pv88090_buck_set_mode, @@ -193,8 +155,8 @@ static const struct regulator_ops pv88090_buck_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear, - .set_current_limit = pv88090_set_current_limit, - .get_current_limit = pv88090_get_current_limit, + .set_current_limit = regulator_set_current_limit_regmap, + .get_current_limit = regulator_get_current_limit_regmap, }; static const struct regulator_ops pv88090_ldo_ops = { @@ -223,10 +185,11 @@ static const struct regulator_ops pv88090_ldo_ops = { .enable_mask = PV88090_##regl_name##_EN, \ .vsel_reg = PV88090_REG_##regl_name##_CONF0, \ .vsel_mask = PV88090_V##regl_name##_MASK, \ + .curr_table = limits_array, \ + .n_current_limits = ARRAY_SIZE(limits_array), \ + .csel_reg = PV88090_REG_##regl_name##_CONF1, \ + .csel_mask = PV88090_##regl_name##_ILIM_MASK, \ },\ - .current_limits = limits_array, \ - .n_current_limits = ARRAY_SIZE(limits_array), \ - .limit_mask = PV88090_##regl_name##_ILIM_MASK, \ .conf = PV88090_REG_##regl_name##_CONF1, \ .conf2 = PV88090_REG_##regl_name##_CONF2, \ } diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c index a2fd140eff81..3f53f9134b32 100644 --- a/drivers/regulator/pwm-regulator.c +++ b/drivers/regulator/pwm-regulator.c @@ -40,9 +40,6 @@ struct pwm_regulator_data { /* regulator descriptor */ struct regulator_desc desc; - /* Regulator ops */ - struct regulator_ops ops; - int state; /* Enable GPIO */ @@ -231,7 +228,7 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev, return 0; } -static struct regulator_ops pwm_regulator_voltage_table_ops = { +static const struct regulator_ops pwm_regulator_voltage_table_ops = { .set_voltage_sel = pwm_regulator_set_voltage_sel, .get_voltage_sel = pwm_regulator_get_voltage_sel, .list_voltage = pwm_regulator_list_voltage, @@ -241,7 +238,7 @@ static struct regulator_ops pwm_regulator_voltage_table_ops = { .is_enabled = pwm_regulator_is_enabled, }; -static struct regulator_ops pwm_regulator_voltage_continuous_ops = { +static const struct regulator_ops pwm_regulator_voltage_continuous_ops = { .get_voltage = pwm_regulator_get_voltage, .set_voltage = pwm_regulator_set_voltage, .enable = pwm_regulator_enable, @@ -249,7 +246,7 @@ static struct regulator_ops pwm_regulator_voltage_continuous_ops = { .is_enabled = pwm_regulator_is_enabled, }; -static struct regulator_desc pwm_regulator_desc = { +static const struct regulator_desc pwm_regulator_desc = { .name = "pwm-regulator", .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, @@ -287,9 +284,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev, drvdata->state = -EINVAL; drvdata->duty_cycle_table = duty_cycle_table; - memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops, - sizeof(drvdata->ops)); - drvdata->desc.ops = &drvdata->ops; + drvdata->desc.ops = &pwm_regulator_voltage_table_ops; drvdata->desc.n_voltages = length / sizeof(*duty_cycle_table); return 0; @@ -301,9 +296,7 @@ static int pwm_regulator_init_continuous(struct platform_device *pdev, u32 dutycycle_range[2] = { 0, 100 }; u32 dutycycle_unit = 100; - memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops, - sizeof(drvdata->ops)); - drvdata->desc.ops = &drvdata->ops; + drvdata->desc.ops = &pwm_regulator_voltage_continuous_ops; drvdata->desc.continuous_voltage_range = true; of_property_read_u32_array(pdev->dev.of_node, diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c index f5bca77d67c1..68bc23df4213 100644 --- a/drivers/regulator/qcom_smd-regulator.c +++ b/drivers/regulator/qcom_smd-regulator.c @@ -31,6 +31,11 @@ struct qcom_rpm_reg { int is_enabled; int uV; + u32 load; + + unsigned int enabled_updated:1; + unsigned int uv_updated:1; + unsigned int load_updated:1; }; struct rpm_regulator_req { @@ -43,30 +48,59 @@ struct rpm_regulator_req { #define RPM_KEY_UV 0x00007675 /* "uv" */ #define RPM_KEY_MA 0x0000616d /* "ma" */ -static int rpm_reg_write_active(struct qcom_rpm_reg *vreg, - struct rpm_regulator_req *req, - size_t size) +static int rpm_reg_write_active(struct qcom_rpm_reg *vreg) { - return qcom_rpm_smd_write(vreg->rpm, - QCOM_SMD_RPM_ACTIVE_STATE, - vreg->type, - vreg->id, - req, size); + struct rpm_regulator_req req[3]; + int reqlen = 0; + int ret; + + if (vreg->enabled_updated) { + req[reqlen].key = cpu_to_le32(RPM_KEY_SWEN); + req[reqlen].nbytes = cpu_to_le32(sizeof(u32)); + req[reqlen].value = cpu_to_le32(vreg->is_enabled); + reqlen++; + } + + if (vreg->uv_updated && vreg->is_enabled) { + req[reqlen].key = cpu_to_le32(RPM_KEY_UV); + req[reqlen].nbytes = cpu_to_le32(sizeof(u32)); + req[reqlen].value = cpu_to_le32(vreg->uV); + reqlen++; + } + + if (vreg->load_updated && vreg->is_enabled) { + req[reqlen].key = cpu_to_le32(RPM_KEY_MA); + req[reqlen].nbytes = cpu_to_le32(sizeof(u32)); + req[reqlen].value = cpu_to_le32(vreg->load / 1000); + reqlen++; + } + + if (!reqlen) + return 0; + + ret = qcom_rpm_smd_write(vreg->rpm, QCOM_SMD_RPM_ACTIVE_STATE, + vreg->type, vreg->id, + req, sizeof(req[0]) * reqlen); + if (!ret) { + vreg->enabled_updated = 0; + vreg->uv_updated = 0; + vreg->load_updated = 0; + } + + return ret; } static int rpm_reg_enable(struct regulator_dev *rdev) { struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); - struct rpm_regulator_req req; int ret; - req.key = cpu_to_le32(RPM_KEY_SWEN); - req.nbytes = cpu_to_le32(sizeof(u32)); - req.value = cpu_to_le32(1); + vreg->is_enabled = 1; + vreg->enabled_updated = 1; - ret = rpm_reg_write_active(vreg, &req, sizeof(req)); - if (!ret) - vreg->is_enabled = 1; + ret = rpm_reg_write_active(vreg); + if (ret) + vreg->is_enabled = 0; return ret; } @@ -81,16 +115,14 @@ static int rpm_reg_is_enabled(struct regulator_dev *rdev) static int rpm_reg_disable(struct regulator_dev *rdev) { struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); - struct rpm_regulator_req req; int ret; - req.key = cpu_to_le32(RPM_KEY_SWEN); - req.nbytes = cpu_to_le32(sizeof(u32)); - req.value = 0; + vreg->is_enabled = 0; + vreg->enabled_updated = 1; - ret = rpm_reg_write_active(vreg, &req, sizeof(req)); - if (!ret) - vreg->is_enabled = 0; + ret = rpm_reg_write_active(vreg); + if (ret) + vreg->is_enabled = 1; return ret; } @@ -108,16 +140,15 @@ static int rpm_reg_set_voltage(struct regulator_dev *rdev, unsigned *selector) { struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); - struct rpm_regulator_req req; - int ret = 0; + int ret; + int old_uV = vreg->uV; - req.key = cpu_to_le32(RPM_KEY_UV); - req.nbytes = cpu_to_le32(sizeof(u32)); - req.value = cpu_to_le32(min_uV); + vreg->uV = min_uV; + vreg->uv_updated = 1; - ret = rpm_reg_write_active(vreg, &req, sizeof(req)); - if (!ret) - vreg->uV = min_uV; + ret = rpm_reg_write_active(vreg); + if (ret) + vreg->uV = old_uV; return ret; } @@ -125,13 +156,16 @@ static int rpm_reg_set_voltage(struct regulator_dev *rdev, static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA) { struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); - struct rpm_regulator_req req; + u32 old_load = vreg->load; + int ret; - req.key = cpu_to_le32(RPM_KEY_MA); - req.nbytes = cpu_to_le32(sizeof(u32)); - req.value = cpu_to_le32(load_uA / 1000); + vreg->load = load_uA; + vreg->load_updated = 1; + ret = rpm_reg_write_active(vreg); + if (ret) + vreg->load = old_load; - return rpm_reg_write_active(vreg, &req, sizeof(req)); + return ret; } static const struct regulator_ops rpm_smps_ldo_ops = { diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 213b68743cc8..23713e16c286 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -1,5 +1,5 @@ /* - * Regulator driver for Rockchip RK808/RK818 + * Regulator driver for Rockchip RK805/RK808/RK818 * * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd * @@ -363,28 +363,28 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev) rdev->desc->enable_mask); } -static struct regulator_ops rk805_reg_ops = { - .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .set_suspend_voltage = rk808_set_suspend_voltage, - .set_suspend_enable = rk805_set_suspend_enable, - .set_suspend_disable = rk805_set_suspend_disable, +static const struct regulator_ops rk805_reg_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_suspend_voltage = rk808_set_suspend_voltage, + .set_suspend_enable = rk805_set_suspend_enable, + .set_suspend_disable = rk805_set_suspend_disable, }; -static struct regulator_ops rk805_switch_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .set_suspend_enable = rk805_set_suspend_enable, - .set_suspend_disable = rk805_set_suspend_disable, +static const struct regulator_ops rk805_switch_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_suspend_enable = rk805_set_suspend_enable, + .set_suspend_disable = rk805_set_suspend_disable, }; -static struct regulator_ops rk808_buck1_2_ops = { +static const struct regulator_ops rk808_buck1_2_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = rk808_buck1_2_get_voltage_sel_regmap, @@ -399,7 +399,7 @@ static struct regulator_ops rk808_buck1_2_ops = { .set_suspend_disable = rk808_set_suspend_disable, }; -static struct regulator_ops rk808_reg_ops = { +static const struct regulator_ops rk808_reg_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -412,7 +412,7 @@ static struct regulator_ops rk808_reg_ops = { .set_suspend_disable = rk808_set_suspend_disable, }; -static struct regulator_ops rk808_reg_ops_ranges = { +static const struct regulator_ops rk808_reg_ops_ranges = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -425,7 +425,7 @@ static struct regulator_ops rk808_reg_ops_ranges = { .set_suspend_disable = rk808_set_suspend_disable, }; -static struct regulator_ops rk808_switch_ops = { +static const struct regulator_ops rk808_switch_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -433,6 +433,12 @@ static struct regulator_ops rk808_switch_ops = { .set_suspend_disable = rk808_set_suspend_disable, }; +static const struct regulator_linear_range rk805_buck_1_2_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(712500, 0, 59, 12500), + REGULATOR_LINEAR_RANGE(1800000, 60, 62, 200000), + REGULATOR_LINEAR_RANGE(2300000, 63, 63, 0), +}; + static const struct regulator_desc rk805_reg[] = { { .name = "DCDC_REG1", @@ -440,11 +446,11 @@ static const struct regulator_desc rk805_reg[] = { .of_match = of_match_ptr("DCDC_REG1"), .regulators_node = of_match_ptr("regulators"), .id = RK805_ID_DCDC1, - .ops = &rk805_reg_ops, + .ops = &rk808_reg_ops_ranges, .type = REGULATOR_VOLTAGE, - .min_uV = 712500, - .uV_step = 12500, .n_voltages = 64, + .linear_ranges = rk805_buck_1_2_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges), .vsel_reg = RK805_BUCK1_ON_VSEL_REG, .vsel_mask = RK818_BUCK_VSEL_MASK, .enable_reg = RK805_DCDC_EN_REG, @@ -456,11 +462,11 @@ static const struct regulator_desc rk805_reg[] = { .of_match = of_match_ptr("DCDC_REG2"), .regulators_node = of_match_ptr("regulators"), .id = RK805_ID_DCDC2, - .ops = &rk805_reg_ops, + .ops = &rk808_reg_ops_ranges, .type = REGULATOR_VOLTAGE, - .min_uV = 712500, - .uV_step = 12500, .n_voltages = 64, + .linear_ranges = rk805_buck_1_2_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges), .vsel_reg = RK805_BUCK2_ON_VSEL_REG, .vsel_mask = RK818_BUCK_VSEL_MASK, .enable_reg = RK805_DCDC_EN_REG, @@ -796,7 +802,7 @@ static struct platform_driver rk808_regulator_driver = { module_platform_driver(rk808_regulator_driver); -MODULE_DESCRIPTION("regulator driver for the RK808/RK818 series PMICs"); +MODULE_DESCRIPTION("regulator driver for the RK805/RK808/RK818 series PMICs"); MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>"); MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>"); diff --git a/drivers/regulator/rt5033-regulator.c b/drivers/regulator/rt5033-regulator.c index 96d2c18e051a..639cbadc044a 100644 --- a/drivers/regulator/rt5033-regulator.c +++ b/drivers/regulator/rt5033-regulator.c @@ -16,14 +16,14 @@ #include <linux/mfd/rt5033-private.h> #include <linux/regulator/of_regulator.h> -static struct regulator_ops rt5033_safe_ldo_ops = { +static const struct regulator_ops rt5033_safe_ldo_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .list_voltage = regulator_list_voltage_linear, }; -static struct regulator_ops rt5033_buck_ops = { +static const struct regulator_ops rt5033_buck_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c index 095d25f3d2ea..58a1fe583a6c 100644 --- a/drivers/regulator/s2mpa01.c +++ b/drivers/regulator/s2mpa01.c @@ -298,13 +298,13 @@ static const struct regulator_desc regulators[] = { regulator_desc_ldo(2, STEP_50_MV), regulator_desc_ldo(3, STEP_50_MV), regulator_desc_ldo(4, STEP_50_MV), - regulator_desc_ldo(5, STEP_50_MV), + regulator_desc_ldo(5, STEP_25_MV), regulator_desc_ldo(6, STEP_25_MV), regulator_desc_ldo(7, STEP_50_MV), regulator_desc_ldo(8, STEP_50_MV), regulator_desc_ldo(9, STEP_50_MV), regulator_desc_ldo(10, STEP_50_MV), - regulator_desc_ldo(11, STEP_25_MV), + regulator_desc_ldo(11, STEP_50_MV), regulator_desc_ldo(12, STEP_50_MV), regulator_desc_ldo(13, STEP_50_MV), regulator_desc_ldo(14, STEP_50_MV), @@ -315,11 +315,11 @@ static const struct regulator_desc regulators[] = { regulator_desc_ldo(19, STEP_50_MV), regulator_desc_ldo(20, STEP_50_MV), regulator_desc_ldo(21, STEP_50_MV), - regulator_desc_ldo(22, STEP_25_MV), - regulator_desc_ldo(23, STEP_25_MV), + regulator_desc_ldo(22, STEP_50_MV), + regulator_desc_ldo(23, STEP_50_MV), regulator_desc_ldo(24, STEP_50_MV), regulator_desc_ldo(25, STEP_50_MV), - regulator_desc_ldo(26, STEP_50_MV), + regulator_desc_ldo(26, STEP_25_MV), regulator_desc_buck1_4(1), regulator_desc_buck1_4(2), regulator_desc_buck1_4(3), diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index ee4a23ab0663..134c62db36c5 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -362,7 +362,7 @@ static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_ldo(32, STEP_50_MV), regulator_desc_s2mps11_ldo(33, STEP_50_MV), regulator_desc_s2mps11_ldo(34, STEP_50_MV), - regulator_desc_s2mps11_ldo(35, STEP_50_MV), + regulator_desc_s2mps11_ldo(35, STEP_25_MV), regulator_desc_s2mps11_ldo(36, STEP_50_MV), regulator_desc_s2mps11_ldo(37, STEP_50_MV), regulator_desc_s2mps11_ldo(38, STEP_50_MV), @@ -372,8 +372,8 @@ static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_buck1_4(4), regulator_desc_s2mps11_buck5, regulator_desc_s2mps11_buck67810(6, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_12_5_MV), + regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_12_5_MV), regulator_desc_s2mps11_buck9, regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV), }; diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index b581f01f3395..bb9d1a083299 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -115,7 +115,7 @@ static const struct sec_voltage_desc *reg_voltage_map[] = { [S5M8767_BUCK9] = &buck_voltage_val3, }; -static unsigned int s5m8767_opmode_reg[][4] = { +static const unsigned int s5m8767_opmode_reg[][4] = { /* {OFF, ON, LOWPOWER, SUSPEND} */ /* LDO1 ... LDO28 */ {0x0, 0x3, 0x2, 0x1}, /* LDO1 */ @@ -339,13 +339,9 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int new_sel) { struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); - const struct sec_voltage_desc *desc; - int reg_id = rdev_get_id(rdev); - - desc = reg_voltage_map[reg_id]; if ((old_sel < new_sel) && s5m8767->ramp_delay) - return DIV_ROUND_UP(desc->step * (new_sel - old_sel), + return DIV_ROUND_UP(rdev->desc->uV_step * (new_sel - old_sel), s5m8767->ramp_delay * 1000); return 0; } diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c index e0a9c445ed67..ba2f24949dc9 100644 --- a/drivers/regulator/stm32-vrefbuf.c +++ b/drivers/regulator/stm32-vrefbuf.c @@ -15,6 +15,7 @@ #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> +#include <linux/pm_runtime.h> /* STM32 VREFBUF registers */ #define STM32_VREFBUF_CSR 0x00 @@ -25,9 +26,12 @@ #define STM32_HIZ BIT(1) #define STM32_ENVR BIT(0) +#define STM32_VREFBUF_AUTO_SUSPEND_DELAY_MS 10 + struct stm32_vrefbuf { void __iomem *base; struct clk *clk; + struct device *dev; }; static const unsigned int stm32_vrefbuf_voltages[] = { @@ -38,9 +42,16 @@ static const unsigned int stm32_vrefbuf_voltages[] = { static int stm32_vrefbuf_enable(struct regulator_dev *rdev) { struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); - u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); + u32 val; int ret; + ret = pm_runtime_get_sync(priv->dev); + if (ret < 0) { + pm_runtime_put_noidle(priv->dev); + return ret; + } + + val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); val = (val & ~STM32_HIZ) | STM32_ENVR; writel_relaxed(val, priv->base + STM32_VREFBUF_CSR); @@ -59,45 +70,95 @@ static int stm32_vrefbuf_enable(struct regulator_dev *rdev) writel_relaxed(val, priv->base + STM32_VREFBUF_CSR); } + pm_runtime_mark_last_busy(priv->dev); + pm_runtime_put_autosuspend(priv->dev); + return ret; } static int stm32_vrefbuf_disable(struct regulator_dev *rdev) { struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); - u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); + u32 val; + int ret; + ret = pm_runtime_get_sync(priv->dev); + if (ret < 0) { + pm_runtime_put_noidle(priv->dev); + return ret; + } + + val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); val = (val & ~STM32_ENVR) | STM32_HIZ; writel_relaxed(val, priv->base + STM32_VREFBUF_CSR); + pm_runtime_mark_last_busy(priv->dev); + pm_runtime_put_autosuspend(priv->dev); + return 0; } static int stm32_vrefbuf_is_enabled(struct regulator_dev *rdev) { struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); + int ret; + + ret = pm_runtime_get_sync(priv->dev); + if (ret < 0) { + pm_runtime_put_noidle(priv->dev); + return ret; + } + + ret = readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR; - return readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR; + pm_runtime_mark_last_busy(priv->dev); + pm_runtime_put_autosuspend(priv->dev); + + return ret; } static int stm32_vrefbuf_set_voltage_sel(struct regulator_dev *rdev, unsigned sel) { struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); - u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); + u32 val; + int ret; + ret = pm_runtime_get_sync(priv->dev); + if (ret < 0) { + pm_runtime_put_noidle(priv->dev); + return ret; + } + + val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); val = (val & ~STM32_VRS) | FIELD_PREP(STM32_VRS, sel); writel_relaxed(val, priv->base + STM32_VREFBUF_CSR); + pm_runtime_mark_last_busy(priv->dev); + pm_runtime_put_autosuspend(priv->dev); + return 0; } static int stm32_vrefbuf_get_voltage_sel(struct regulator_dev *rdev) { struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); - u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); + u32 val; + int ret; - return FIELD_GET(STM32_VRS, val); + ret = pm_runtime_get_sync(priv->dev); + if (ret < 0) { + pm_runtime_put_noidle(priv->dev); + return ret; + } + + val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); + ret = FIELD_GET(STM32_VRS, val); + + pm_runtime_mark_last_busy(priv->dev); + pm_runtime_put_autosuspend(priv->dev); + + return ret; } static const struct regulator_ops stm32_vrefbuf_volt_ops = { @@ -130,6 +191,7 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev) priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + priv->dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->base = devm_ioremap_resource(&pdev->dev, res); @@ -140,10 +202,17 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev) if (IS_ERR(priv->clk)) return PTR_ERR(priv->clk); + pm_runtime_get_noresume(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, + STM32_VREFBUF_AUTO_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); + ret = clk_prepare_enable(priv->clk); if (ret) { dev_err(&pdev->dev, "clk prepare failed with error %d\n", ret); - return ret; + goto err_pm_stop; } config.dev = &pdev->dev; @@ -161,10 +230,17 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, rdev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + return 0; err_clk_dis: clk_disable_unprepare(priv->clk); +err_pm_stop: + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); return ret; } @@ -174,12 +250,42 @@ static int stm32_vrefbuf_remove(struct platform_device *pdev) struct regulator_dev *rdev = platform_get_drvdata(pdev); struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); + pm_runtime_get_sync(&pdev->dev); regulator_unregister(rdev); clk_disable_unprepare(priv->clk); + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); return 0; }; +static int __maybe_unused stm32_vrefbuf_runtime_suspend(struct device *dev) +{ + struct regulator_dev *rdev = dev_get_drvdata(dev); + struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); + + clk_disable_unprepare(priv->clk); + + return 0; +} + +static int __maybe_unused stm32_vrefbuf_runtime_resume(struct device *dev) +{ + struct regulator_dev *rdev = dev_get_drvdata(dev); + struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); + + return clk_prepare_enable(priv->clk); +} + +static const struct dev_pm_ops stm32_vrefbuf_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(stm32_vrefbuf_runtime_suspend, + stm32_vrefbuf_runtime_resume, + NULL) +}; + static const struct of_device_id stm32_vrefbuf_of_match[] = { { .compatible = "st,stm32-vrefbuf", }, {}, @@ -192,6 +298,7 @@ static struct platform_driver stm32_vrefbuf_driver = { .driver = { .name = "stm32-vrefbuf", .of_match_table = of_match_ptr(stm32_vrefbuf_of_match), + .pm = &stm32_vrefbuf_pm_ops, }, }; module_platform_driver(stm32_vrefbuf_driver); diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c index 16ba0297f709..f09061473613 100644 --- a/drivers/regulator/stpmic1_regulator.c +++ b/drivers/regulator/stpmic1_regulator.c @@ -12,8 +12,10 @@ #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> +#include <dt-bindings/mfd/st,stpmic1.h> + /** - * stpmic1 regulator description + * stpmic1 regulator description: this structure is used as driver data * @desc: regulator framework description * @mask_reset_reg: mask reset register address * @mask_reset_mask: mask rank and mask reset register mask @@ -28,28 +30,9 @@ struct stpmic1_regulator_cfg { u8 icc_mask; }; -/** - * stpmic1 regulator data: this structure is used as driver data - * @regul_id: regulator id - * @reg_node: DT node of regulator (unused on non-DT platforms) - * @cfg: stpmic specific regulator description - * @mask_reset: mask_reset bit value - * @irq_curlim: current limit interrupt number - * @regmap: point to parent regmap structure - */ -struct stpmic1_regulator { - unsigned int regul_id; - struct device_node *reg_node; - struct stpmic1_regulator_cfg *cfg; - u8 mask_reset; - int irq_curlim; - struct regmap *regmap; -}; - static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode); static unsigned int stpmic1_get_mode(struct regulator_dev *rdev); static int stpmic1_set_icc(struct regulator_dev *rdev); -static int stpmic1_regulator_parse_dt(void *driver_data); static unsigned int stpmic1_map_mode(unsigned int mode); enum { @@ -72,15 +55,13 @@ enum { /* Enable time worst case is 5000mV/(2250uV/uS) */ #define PMIC_ENABLE_TIME_US 2200 -#define STPMIC1_BUCK_MODE_NORMAL 0 -#define STPMIC1_BUCK_MODE_LP BUCK_HPLP_ENABLE_MASK - -struct regulator_linear_range buck1_ranges[] = { - REGULATOR_LINEAR_RANGE(600000, 0, 30, 25000), - REGULATOR_LINEAR_RANGE(1350000, 31, 63, 0), +static const struct regulator_linear_range buck1_ranges[] = { + REGULATOR_LINEAR_RANGE(725000, 0, 4, 0), + REGULATOR_LINEAR_RANGE(725000, 5, 36, 25000), + REGULATOR_LINEAR_RANGE(1500000, 37, 63, 0), }; -struct regulator_linear_range buck2_ranges[] = { +static const struct regulator_linear_range buck2_ranges[] = { REGULATOR_LINEAR_RANGE(1000000, 0, 17, 0), REGULATOR_LINEAR_RANGE(1050000, 18, 19, 0), REGULATOR_LINEAR_RANGE(1100000, 20, 21, 0), @@ -94,7 +75,7 @@ struct regulator_linear_range buck2_ranges[] = { REGULATOR_LINEAR_RANGE(1500000, 36, 63, 0), }; -struct regulator_linear_range buck3_ranges[] = { +static const struct regulator_linear_range buck3_ranges[] = { REGULATOR_LINEAR_RANGE(1000000, 0, 19, 0), REGULATOR_LINEAR_RANGE(1100000, 20, 23, 0), REGULATOR_LINEAR_RANGE(1200000, 24, 27, 0), @@ -102,10 +83,9 @@ struct regulator_linear_range buck3_ranges[] = { REGULATOR_LINEAR_RANGE(1400000, 32, 35, 0), REGULATOR_LINEAR_RANGE(1500000, 36, 55, 100000), REGULATOR_LINEAR_RANGE(3400000, 56, 63, 0), - }; -struct regulator_linear_range buck4_ranges[] = { +static const struct regulator_linear_range buck4_ranges[] = { REGULATOR_LINEAR_RANGE(600000, 0, 27, 25000), REGULATOR_LINEAR_RANGE(1300000, 28, 29, 0), REGULATOR_LINEAR_RANGE(1350000, 30, 31, 0), @@ -113,24 +93,21 @@ struct regulator_linear_range buck4_ranges[] = { REGULATOR_LINEAR_RANGE(1450000, 34, 35, 0), REGULATOR_LINEAR_RANGE(1500000, 36, 60, 100000), REGULATOR_LINEAR_RANGE(3900000, 61, 63, 0), - }; -struct regulator_linear_range ldo1_ranges[] = { +static const struct regulator_linear_range ldo1_ranges[] = { REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0), REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000), REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0), - }; -struct regulator_linear_range ldo2_ranges[] = { +static const struct regulator_linear_range ldo2_ranges[] = { REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0), REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000), REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0), - }; -struct regulator_linear_range ldo3_ranges[] = { +static const struct regulator_linear_range ldo3_ranges[] = { REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0), REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000), REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0), @@ -138,18 +115,18 @@ struct regulator_linear_range ldo3_ranges[] = { REGULATOR_LINEAR_RANGE(500000, 31, 31, 0), }; -struct regulator_linear_range ldo5_ranges[] = { +static const struct regulator_linear_range ldo5_ranges[] = { REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0), REGULATOR_LINEAR_RANGE(1700000, 8, 30, 100000), REGULATOR_LINEAR_RANGE(3900000, 31, 31, 0), }; -struct regulator_linear_range ldo6_ranges[] = { +static const struct regulator_linear_range ldo6_ranges[] = { REGULATOR_LINEAR_RANGE(900000, 0, 24, 100000), REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0), }; -static struct regulator_ops stpmic1_ldo_ops = { +static const struct regulator_ops stpmic1_ldo_ops = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .is_enabled = regulator_is_enabled_regmap, @@ -157,11 +134,10 @@ static struct regulator_ops stpmic1_ldo_ops = { .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_pull_down = regulator_set_pull_down_regmap, .set_over_current_protection = stpmic1_set_icc, }; -static struct regulator_ops stpmic1_ldo3_ops = { +static const struct regulator_ops stpmic1_ldo3_ops = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_iterate, .is_enabled = regulator_is_enabled_regmap, @@ -169,21 +145,19 @@ static struct regulator_ops stpmic1_ldo3_ops = { .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_pull_down = regulator_set_pull_down_regmap, .get_bypass = regulator_get_bypass_regmap, .set_bypass = regulator_set_bypass_regmap, .set_over_current_protection = stpmic1_set_icc, }; -static struct regulator_ops stpmic1_ldo4_fixed_regul_ops = { +static const struct regulator_ops stpmic1_ldo4_fixed_regul_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .set_pull_down = regulator_set_pull_down_regmap, .set_over_current_protection = stpmic1_set_icc, }; -static struct regulator_ops stpmic1_buck_ops = { +static const struct regulator_ops stpmic1_buck_ops = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .is_enabled = regulator_is_enabled_regmap, @@ -197,20 +171,27 @@ static struct regulator_ops stpmic1_buck_ops = { .set_over_current_protection = stpmic1_set_icc, }; -static struct regulator_ops stpmic1_vref_ddr_ops = { +static const struct regulator_ops stpmic1_vref_ddr_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .set_pull_down = regulator_set_pull_down_regmap, }; -static struct regulator_ops stpmic1_switch_regul_ops = { +static const struct regulator_ops stpmic1_boost_regul_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .set_over_current_protection = stpmic1_set_icc, }; +static const struct regulator_ops stpmic1_switch_regul_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .set_over_current_protection = stpmic1_set_icc, + .set_active_discharge = regulator_set_active_discharge_regmap, +}; + #define REG_LDO(ids, base) { \ .name = #ids, \ .id = STPMIC1_##ids, \ @@ -227,8 +208,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = { .enable_val = 1, \ .disable_val = 0, \ .enable_time = PMIC_ENABLE_TIME_US, \ - .pull_down_reg = ids##_PULL_DOWN_REG, \ - .pull_down_mask = ids##_PULL_DOWN_MASK, \ .supply_name = #base, \ } @@ -252,8 +231,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = { .bypass_mask = LDO_BYPASS_MASK, \ .bypass_val_on = LDO_BYPASS_MASK, \ .bypass_val_off = 0, \ - .pull_down_reg = ids##_PULL_DOWN_REG, \ - .pull_down_mask = ids##_PULL_DOWN_MASK, \ .supply_name = #base, \ } @@ -271,8 +248,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = { .enable_val = 1, \ .disable_val = 0, \ .enable_time = PMIC_ENABLE_TIME_US, \ - .pull_down_reg = ids##_PULL_DOWN_REG, \ - .pull_down_mask = ids##_PULL_DOWN_MASK, \ .supply_name = #base, \ } @@ -312,12 +287,47 @@ static struct regulator_ops stpmic1_switch_regul_ops = { .enable_val = 1, \ .disable_val = 0, \ .enable_time = PMIC_ENABLE_TIME_US, \ - .pull_down_reg = ids##_PULL_DOWN_REG, \ - .pull_down_mask = ids##_PULL_DOWN_MASK, \ .supply_name = #base, \ } -#define REG_SWITCH(ids, base, reg, mask, val) { \ +#define REG_BOOST(ids, base) { \ + .name = #ids, \ + .id = STPMIC1_##ids, \ + .n_voltages = 1, \ + .ops = &stpmic1_boost_regul_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 0, \ + .fixed_uV = 5000000, \ + .enable_reg = BST_SW_CR, \ + .enable_mask = BOOST_ENABLED, \ + .enable_val = BOOST_ENABLED, \ + .disable_val = 0, \ + .enable_time = PMIC_ENABLE_TIME_US, \ + .supply_name = #base, \ +} + +#define REG_VBUS_OTG(ids, base) { \ + .name = #ids, \ + .id = STPMIC1_##ids, \ + .n_voltages = 1, \ + .ops = &stpmic1_switch_regul_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 0, \ + .fixed_uV = 5000000, \ + .enable_reg = BST_SW_CR, \ + .enable_mask = USBSW_OTG_SWITCH_ENABLED, \ + .enable_val = USBSW_OTG_SWITCH_ENABLED, \ + .disable_val = 0, \ + .enable_time = PMIC_ENABLE_TIME_US, \ + .supply_name = #base, \ + .active_discharge_reg = BST_SW_CR, \ + .active_discharge_mask = VBUS_OTG_DISCHARGE, \ + .active_discharge_on = VBUS_OTG_DISCHARGE, \ +} + +#define REG_SW_OUT(ids, base) { \ .name = #ids, \ .id = STPMIC1_##ids, \ .n_voltages = 1, \ @@ -326,15 +336,18 @@ static struct regulator_ops stpmic1_switch_regul_ops = { .owner = THIS_MODULE, \ .min_uV = 0, \ .fixed_uV = 5000000, \ - .enable_reg = (reg), \ - .enable_mask = (mask), \ - .enable_val = (val), \ + .enable_reg = BST_SW_CR, \ + .enable_mask = SWIN_SWOUT_ENABLED, \ + .enable_val = SWIN_SWOUT_ENABLED, \ .disable_val = 0, \ .enable_time = PMIC_ENABLE_TIME_US, \ .supply_name = #base, \ + .active_discharge_reg = BST_SW_CR, \ + .active_discharge_mask = SW_OUT_DISCHARGE, \ + .active_discharge_on = SW_OUT_DISCHARGE, \ } -struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = { +static const struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = { [STPMIC1_BUCK1] = { .desc = REG_BUCK(BUCK1, buck1), .icc_reg = BUCKS_ICCTO_CR, @@ -411,23 +424,17 @@ struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = { .mask_reset_mask = BIT(6), }, [STPMIC1_BOOST] = { - .desc = REG_SWITCH(BOOST, boost, BST_SW_CR, - BOOST_ENABLED, - BOOST_ENABLED), + .desc = REG_BOOST(BOOST, boost), .icc_reg = BUCKS_ICCTO_CR, .icc_mask = BIT(6), }, [STPMIC1_VBUS_OTG] = { - .desc = REG_SWITCH(VBUS_OTG, pwr_sw1, BST_SW_CR, - USBSW_OTG_SWITCH_ENABLED, - USBSW_OTG_SWITCH_ENABLED), + .desc = REG_VBUS_OTG(VBUS_OTG, pwr_sw1), .icc_reg = BUCKS_ICCTO_CR, .icc_mask = BIT(4), }, [STPMIC1_SW_OUT] = { - .desc = REG_SWITCH(SW_OUT, pwr_sw2, BST_SW_CR, - SWIN_SWOUT_ENABLED, - SWIN_SWOUT_ENABLED), + .desc = REG_SW_OUT(SW_OUT, pwr_sw2), .icc_reg = BUCKS_ICCTO_CR, .icc_mask = BIT(5), }, @@ -448,8 +455,9 @@ static unsigned int stpmic1_map_mode(unsigned int mode) static unsigned int stpmic1_get_mode(struct regulator_dev *rdev) { int value; + struct regmap *regmap = rdev_get_regmap(rdev); - regmap_read(rdev->regmap, rdev->desc->enable_reg, &value); + regmap_read(regmap, rdev->desc->enable_reg, &value); if (value & STPMIC1_BUCK_MODE_LP) return REGULATOR_MODE_STANDBY; @@ -460,6 +468,7 @@ static unsigned int stpmic1_get_mode(struct regulator_dev *rdev) static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode) { int value; + struct regmap *regmap = rdev_get_regmap(rdev); switch (mode) { case REGULATOR_MODE_NORMAL: @@ -472,17 +481,18 @@ static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode) return -EINVAL; } - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + return regmap_update_bits(regmap, rdev->desc->enable_reg, STPMIC1_BUCK_MODE_LP, value); } static int stpmic1_set_icc(struct regulator_dev *rdev) { - struct stpmic1_regulator *regul = rdev_get_drvdata(rdev); + struct stpmic1_regulator_cfg *cfg = rdev_get_drvdata(rdev); + struct regmap *regmap = rdev_get_regmap(rdev); /* enable switch off in case of over current */ - return regmap_update_bits(regul->regmap, regul->cfg->icc_reg, - regul->cfg->icc_mask, regul->cfg->icc_mask); + return regmap_update_bits(regmap, cfg->icc_reg, cfg->icc_mask, + cfg->icc_mask); } static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data) @@ -501,46 +511,13 @@ static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static int stpmic1_regulator_init(struct platform_device *pdev, - struct regulator_dev *rdev) -{ - struct stpmic1_regulator *regul = rdev_get_drvdata(rdev); - int ret = 0; - - /* set mask reset */ - if (regul->mask_reset && regul->cfg->mask_reset_reg != 0) { - ret = regmap_update_bits(regul->regmap, - regul->cfg->mask_reset_reg, - regul->cfg->mask_reset_mask, - regul->cfg->mask_reset_mask); - if (ret) { - dev_err(&pdev->dev, "set mask reset failed\n"); - return ret; - } - } - - /* setup an irq handler for over-current detection */ - if (regul->irq_curlim > 0) { - ret = devm_request_threaded_irq(&pdev->dev, - regul->irq_curlim, NULL, - stpmic1_curlim_irq_handler, - IRQF_ONESHOT | IRQF_SHARED, - pdev->name, rdev); - if (ret) { - dev_err(&pdev->dev, "Request IRQ failed\n"); - return ret; - } - } - return 0; -} - #define MATCH(_name, _id) \ [STPMIC1_##_id] = { \ .name = #_name, \ .desc = &stpmic1_regulator_cfgs[STPMIC1_##_id].desc, \ } -static struct of_regulator_match stpmic1_regulators_matches[] = { +static struct of_regulator_match stpmic1_matches[] = { MATCH(buck1, BUCK1), MATCH(buck2, BUCK2), MATCH(buck3, BUCK3), @@ -557,94 +534,75 @@ static struct of_regulator_match stpmic1_regulators_matches[] = { MATCH(pwr_sw2, SW_OUT), }; -static int stpmic1_regulator_parse_dt(void *driver_data) -{ - struct stpmic1_regulator *regul = - (struct stpmic1_regulator *)driver_data; - - if (!regul) - return -EINVAL; - - if (of_get_property(regul->reg_node, "st,mask-reset", NULL)) - regul->mask_reset = 1; - - regul->irq_curlim = of_irq_get(regul->reg_node, 0); - - return 0; -} - -static struct -regulator_dev *stpmic1_regulator_register(struct platform_device *pdev, int id, - struct regulator_init_data *init_data, - struct stpmic1_regulator *regul) +static int stpmic1_regulator_register(struct platform_device *pdev, int id, + struct of_regulator_match *match, + const struct stpmic1_regulator_cfg *cfg) { struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent); struct regulator_dev *rdev; struct regulator_config config = {}; + int ret = 0; + int irq; config.dev = &pdev->dev; - config.init_data = init_data; - config.of_node = stpmic1_regulators_matches[id].of_node; + config.init_data = match->init_data; + config.of_node = match->of_node; config.regmap = pmic_dev->regmap; - config.driver_data = regul; - - regul->regul_id = id; - regul->reg_node = config.of_node; - regul->cfg = &stpmic1_regulator_cfgs[id]; - regul->regmap = pmic_dev->regmap; + config.driver_data = (void *)cfg; - rdev = devm_regulator_register(&pdev->dev, ®ul->cfg->desc, &config); + rdev = devm_regulator_register(&pdev->dev, &cfg->desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register %s regulator\n", - regul->cfg->desc.name); + cfg->desc.name); + return PTR_ERR(rdev); + } + + /* set mask reset */ + if (of_get_property(config.of_node, "st,mask-reset", NULL) && + cfg->mask_reset_reg != 0) { + ret = regmap_update_bits(pmic_dev->regmap, + cfg->mask_reset_reg, + cfg->mask_reset_mask, + cfg->mask_reset_mask); + if (ret) { + dev_err(&pdev->dev, "set mask reset failed\n"); + return ret; + } } - return rdev; + /* setup an irq handler for over-current detection */ + irq = of_irq_get(config.of_node, 0); + if (irq > 0) { + ret = devm_request_threaded_irq(&pdev->dev, + irq, NULL, + stpmic1_curlim_irq_handler, + IRQF_ONESHOT | IRQF_SHARED, + pdev->name, rdev); + if (ret) { + dev_err(&pdev->dev, "Request IRQ failed\n"); + return ret; + } + } + return 0; } static int stpmic1_regulator_probe(struct platform_device *pdev) { - struct regulator_dev *rdev; - struct stpmic1_regulator *regul; - struct regulator_init_data *init_data; - struct device_node *np; int i, ret; - np = pdev->dev.of_node; - - ret = of_regulator_match(&pdev->dev, np, - stpmic1_regulators_matches, - ARRAY_SIZE(stpmic1_regulators_matches)); + ret = of_regulator_match(&pdev->dev, pdev->dev.of_node, stpmic1_matches, + ARRAY_SIZE(stpmic1_matches)); if (ret < 0) { dev_err(&pdev->dev, "Error in PMIC regulator device tree node"); return ret; } - regul = devm_kzalloc(&pdev->dev, ARRAY_SIZE(stpmic1_regulator_cfgs) * - sizeof(struct stpmic1_regulator), - GFP_KERNEL); - if (!regul) - return -ENOMEM; - for (i = 0; i < ARRAY_SIZE(stpmic1_regulator_cfgs); i++) { - /* Parse DT & find regulators to register */ - init_data = stpmic1_regulators_matches[i].init_data; - if (init_data) - init_data->regulator_init = &stpmic1_regulator_parse_dt; - - rdev = stpmic1_regulator_register(pdev, i, init_data, regul); - if (IS_ERR(rdev)) - return PTR_ERR(rdev); - - ret = stpmic1_regulator_init(pdev, rdev); - if (ret) { - dev_err(&pdev->dev, - "failed to initialize regulator %d\n", ret); + ret = stpmic1_regulator_register(pdev, i, &stpmic1_matches[i], + &stpmic1_regulator_cfgs[i]); + if (ret < 0) return ret; - } - - regul++; } dev_dbg(&pdev->dev, "stpmic1_regulator driver probed\n"); diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c index 6209beee1018..95708d34876b 100644 --- a/drivers/regulator/tps65218-regulator.c +++ b/drivers/regulator/tps65218-regulator.c @@ -188,7 +188,8 @@ static struct regulator_ops tps65218_ldo1_dcdc34_ops = { .set_suspend_disable = tps65218_pmic_set_suspend_disable, }; -static const int ls3_currents[] = { 100, 200, 500, 1000 }; +static const int ls3_currents[] = { 100000, 200000, 500000, 1000000 }; + static int tps65218_pmic_set_input_current_lim(struct regulator_dev *dev, int lim_uA) @@ -204,7 +205,8 @@ static int tps65218_pmic_set_input_current_lim(struct regulator_dev *dev, return -EINVAL; return tps65218_set_bits(tps, dev->desc->csel_reg, dev->desc->csel_mask, - index << 2, TPS65218_PROTECT_L1); + index << __builtin_ctz(dev->desc->csel_mask), + TPS65218_PROTECT_L1); } static int tps65218_pmic_set_current_limit(struct regulator_dev *dev, @@ -214,7 +216,7 @@ static int tps65218_pmic_set_current_limit(struct regulator_dev *dev, unsigned int num_currents = ARRAY_SIZE(ls3_currents); struct tps65218 *tps = rdev_get_drvdata(dev); - while (index < num_currents && ls3_currents[index] < max_uA) + while (index < num_currents && ls3_currents[index] <= max_uA) index++; index--; @@ -223,7 +225,8 @@ static int tps65218_pmic_set_current_limit(struct regulator_dev *dev, return -EINVAL; return tps65218_set_bits(tps, dev->desc->csel_reg, dev->desc->csel_mask, - index << 2, TPS65218_PROTECT_L1); + index << __builtin_ctz(dev->desc->csel_mask), + TPS65218_PROTECT_L1); } static int tps65218_pmic_get_current_limit(struct regulator_dev *dev) @@ -236,12 +239,13 @@ static int tps65218_pmic_get_current_limit(struct regulator_dev *dev) if (retval < 0) return retval; - index = (index & dev->desc->csel_mask) >> 2; + index = (index & dev->desc->csel_mask) >> + __builtin_ctz(dev->desc->csel_mask); return ls3_currents[index]; } -static struct regulator_ops tps65218_ls3_ops = { +static struct regulator_ops tps65218_ls23_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = tps65218_pmic_enable, .disable = tps65218_pmic_disable, @@ -303,8 +307,13 @@ static const struct regulator_desc regulators[] = { TPS65218_ENABLE2_LDO1_EN, 0, 0, ldo1_dcdc3_ranges, 2, 0, 0, TPS65218_REG_SEQ6, TPS65218_SEQ6_LDO1_SEQ_MASK), + TPS65218_REGULATOR("LS2", "regulator-ls2", TPS65218_LS_2, + REGULATOR_CURRENT, tps65218_ls23_ops, 0, 0, 0, + TPS65218_REG_ENABLE2, TPS65218_ENABLE2_LS2_EN, + TPS65218_REG_CONFIG2, TPS65218_CONFIG2_LS2ILIM_MASK, + NULL, 0, 0, 0, 0, 0), TPS65218_REGULATOR("LS3", "regulator-ls3", TPS65218_LS_3, - REGULATOR_CURRENT, tps65218_ls3_ops, 0, 0, 0, + REGULATOR_CURRENT, tps65218_ls23_ops, 0, 0, 0, TPS65218_REG_ENABLE2, TPS65218_ENABLE2_LS3_EN, TPS65218_REG_CONFIG2, TPS65218_CONFIG2_LS3ILIM_MASK, NULL, 0, 0, 0, 0, 0), diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 884c7505ed91..402ea43c77d1 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -576,14 +576,9 @@ static int twlreg_probe(struct platform_device *pdev) struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; - const struct of_device_id *match; struct regulator_config config = { }; - match = of_match_device(twl_of_match, &pdev->dev); - if (!match) - return -ENODEV; - - template = match->data; + template = of_device_get_match_data(&pdev->dev); if (!template) return -ENODEV; diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c index 219cbd910dbf..15f19df6bc5d 100644 --- a/drivers/regulator/twl6030-regulator.c +++ b/drivers/regulator/twl6030-regulator.c @@ -31,9 +31,6 @@ struct twlreg_info { /* twl resource ID, for resource control state machine */ u8 id; - /* chip constraints on regulator behavior */ - u16 min_mV; - u8 flags; /* used by regulator core */ @@ -247,32 +244,11 @@ static int twl6030coresmps_get_voltage(struct regulator_dev *rdev) return -ENODEV; } -static struct regulator_ops twl6030coresmps_ops = { +static const struct regulator_ops twl6030coresmps_ops = { .set_voltage = twl6030coresmps_set_voltage, .get_voltage = twl6030coresmps_get_voltage, }; -static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned sel) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - - switch (sel) { - case 0: - return 0; - case 1 ... 24: - /* Linear mapping from 00000001 to 00011000: - * Absolute voltage value = 1.0 V + 0.1 V × (sel – 00000001) - */ - return (info->min_mV + 100 * (sel - 1)) * 1000; - case 25 ... 30: - return -EINVAL; - case 31: - return 2750000; - default: - return -EINVAL; - } -} - static int twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { @@ -290,8 +266,8 @@ static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev) return vsel; } -static struct regulator_ops twl6030ldo_ops = { - .list_voltage = twl6030ldo_list_voltage, +static const struct regulator_ops twl6030ldo_ops = { + .list_voltage = regulator_list_voltage_linear_range, .set_voltage_sel = twl6030ldo_set_voltage_sel, .get_voltage_sel = twl6030ldo_get_voltage_sel, @@ -305,7 +281,7 @@ static struct regulator_ops twl6030ldo_ops = { .get_status = twl6030reg_get_status, }; -static struct regulator_ops twl6030fixed_ops = { +static const struct regulator_ops twl6030fixed_ops = { .list_voltage = regulator_list_voltage_linear, .enable = twl6030reg_enable, @@ -496,7 +472,7 @@ static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev) return twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS); } -static struct regulator_ops twlsmps_ops = { +static const struct regulator_ops twlsmps_ops = { .list_voltage = twl6030smps_list_voltage, .map_voltage = twl6030smps_map_voltage, @@ -513,6 +489,11 @@ static struct regulator_ops twlsmps_ops = { }; /*----------------------------------------------------------------------*/ +static const struct regulator_linear_range twl6030ldo_linear_range[] = { + REGULATOR_LINEAR_RANGE(0, 0, 0, 0), + REGULATOR_LINEAR_RANGE(1000000, 1, 24, 100000), + REGULATOR_LINEAR_RANGE(2750000, 31, 31, 0), +}; #define TWL6030_ADJUSTABLE_SMPS(label) \ static const struct twlreg_info TWL6030_INFO_##label = { \ @@ -525,28 +506,30 @@ static const struct twlreg_info TWL6030_INFO_##label = { \ }, \ } -#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts) \ +#define TWL6030_ADJUSTABLE_LDO(label, offset) \ static const struct twlreg_info TWL6030_INFO_##label = { \ .base = offset, \ - .min_mV = min_mVolts, \ .desc = { \ .name = #label, \ .id = TWL6030_REG_##label, \ .n_voltages = 32, \ + .linear_ranges = twl6030ldo_linear_range, \ + .n_linear_ranges = ARRAY_SIZE(twl6030ldo_linear_range), \ .ops = &twl6030ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ }, \ } -#define TWL6032_ADJUSTABLE_LDO(label, offset, min_mVolts) \ +#define TWL6032_ADJUSTABLE_LDO(label, offset) \ static const struct twlreg_info TWL6032_INFO_##label = { \ .base = offset, \ - .min_mV = min_mVolts, \ .desc = { \ .name = #label, \ .id = TWL6032_REG_##label, \ .n_voltages = 32, \ + .linear_ranges = twl6030ldo_linear_range, \ + .n_linear_ranges = ARRAY_SIZE(twl6030ldo_linear_range), \ .ops = &twl6030ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ @@ -557,7 +540,6 @@ static const struct twlreg_info TWL6032_INFO_##label = { \ static const struct twlreg_info TWLFIXED_INFO_##label = { \ .base = offset, \ .id = 0, \ - .min_mV = mVolts, \ .desc = { \ .name = #label, \ .id = TWL6030##_REG_##label, \ @@ -574,7 +556,6 @@ static const struct twlreg_info TWLFIXED_INFO_##label = { \ #define TWL6032_ADJUSTABLE_SMPS(label, offset) \ static const struct twlreg_info TWLSMPS_INFO_##label = { \ .base = offset, \ - .min_mV = 600, \ .desc = { \ .name = #label, \ .id = TWL6032_REG_##label, \ @@ -592,22 +573,22 @@ static const struct twlreg_info TWLSMPS_INFO_##label = { \ TWL6030_ADJUSTABLE_SMPS(VDD1); TWL6030_ADJUSTABLE_SMPS(VDD2); TWL6030_ADJUSTABLE_SMPS(VDD3); -TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000); -TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000); -TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000); -TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000); -TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000); -TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000); +TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54); +TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58); +TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c); +TWL6030_ADJUSTABLE_LDO(VMMC, 0x68); +TWL6030_ADJUSTABLE_LDO(VPP, 0x6c); +TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74); /* 6025 are renamed compared to 6030 versions */ -TWL6032_ADJUSTABLE_LDO(LDO2, 0x54, 1000); -TWL6032_ADJUSTABLE_LDO(LDO4, 0x58, 1000); -TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c, 1000); -TWL6032_ADJUSTABLE_LDO(LDO5, 0x68, 1000); -TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c, 1000); -TWL6032_ADJUSTABLE_LDO(LDO7, 0x74, 1000); -TWL6032_ADJUSTABLE_LDO(LDO6, 0x60, 1000); -TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64, 1000); -TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000); +TWL6032_ADJUSTABLE_LDO(LDO2, 0x54); +TWL6032_ADJUSTABLE_LDO(LDO4, 0x58); +TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c); +TWL6032_ADJUSTABLE_LDO(LDO5, 0x68); +TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c); +TWL6032_ADJUSTABLE_LDO(LDO7, 0x74); +TWL6032_ADJUSTABLE_LDO(LDO6, 0x60); +TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64); +TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70); TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0); TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0); TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0); @@ -687,14 +668,9 @@ static int twlreg_probe(struct platform_device *pdev) struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; - const struct of_device_id *match; struct regulator_config config = { }; - match = of_match_device(twl_of_match, &pdev->dev); - if (!match) - return -ENODEV; - - template = match->data; + template = of_device_get_match_data(&pdev->dev); if (!template) return -ENODEV; diff --git a/drivers/regulator/uniphier-regulator.c b/drivers/regulator/uniphier-regulator.c index abf22acbd13e..9026d5a3e964 100644 --- a/drivers/regulator/uniphier-regulator.c +++ b/drivers/regulator/uniphier-regulator.c @@ -32,7 +32,7 @@ struct uniphier_regulator_priv { const struct uniphier_regulator_soc_data *data; }; -static struct regulator_ops uniphier_regulator_ops = { +static const struct regulator_ops uniphier_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -87,8 +87,10 @@ static int uniphier_regulator_probe(struct platform_device *pdev) } regmap = devm_regmap_init_mmio(dev, base, priv->data->regconf); - if (IS_ERR(regmap)) - return PTR_ERR(regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + goto out_rst_assert; + } config.dev = dev; config.driver_data = priv; diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 5a5bc4bb08d2..12b422373580 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -205,33 +205,10 @@ static irqreturn_t wm831x_dcdc_oc_irq(int irq, void *data) * BUCKV specifics */ -static int wm831x_buckv_list_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - if (selector <= 0x8) - return 600000; - if (selector <= WM831X_BUCKV_MAX_SELECTOR) - return 600000 + ((selector - 0x8) * 12500); - return -EINVAL; -} - -static int wm831x_buckv_map_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - u16 vsel; - - if (min_uV < 600000) - vsel = 0; - else if (min_uV <= 1800000) - vsel = DIV_ROUND_UP(min_uV - 600000, 12500) + 8; - else - return -EINVAL; - - if (wm831x_buckv_list_voltage(rdev, vsel) > max_uV) - return -EINVAL; - - return vsel; -} +static const struct regulator_linear_range wm831x_buckv_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 0x7, 0), + REGULATOR_LINEAR_RANGE(600000, 0x8, 0x68, 12500), +}; static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state) { @@ -309,7 +286,7 @@ static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev, u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL; int vsel; - vsel = wm831x_buckv_map_voltage(rdev, uV, uV); + vsel = regulator_map_voltage_linear_range(rdev, uV, uV); if (vsel < 0) return vsel; @@ -327,52 +304,18 @@ static int wm831x_buckv_get_voltage_sel(struct regulator_dev *rdev) } /* Current limit options */ -static u16 wm831x_dcdc_ilim[] = { - 125, 250, 375, 500, 625, 750, 875, 1000 +static const unsigned int wm831x_dcdc_ilim[] = { + 125000, 250000, 375000, 500000, 625000, 750000, 875000, 1000000 }; -static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev, - int min_uA, int max_uA) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - struct wm831x *wm831x = dcdc->wm831x; - u16 reg = dcdc->base + WM831X_DCDC_CONTROL_2; - int i; - - for (i = ARRAY_SIZE(wm831x_dcdc_ilim) - 1; i >= 0; i--) { - if ((min_uA <= wm831x_dcdc_ilim[i]) && - (wm831x_dcdc_ilim[i] <= max_uA)) - return wm831x_set_bits(wm831x, reg, - WM831X_DC1_HC_THR_MASK, - i << WM831X_DC1_HC_THR_SHIFT); - } - - return -EINVAL; -} - -static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - struct wm831x *wm831x = dcdc->wm831x; - u16 reg = dcdc->base + WM831X_DCDC_CONTROL_2; - int val; - - val = wm831x_reg_read(wm831x, reg); - if (val < 0) - return val; - - val = (val & WM831X_DC1_HC_THR_MASK) >> WM831X_DC1_HC_THR_SHIFT; - return wm831x_dcdc_ilim[val]; -} - static const struct regulator_ops wm831x_buckv_ops = { .set_voltage_sel = wm831x_buckv_set_voltage_sel, .get_voltage_sel = wm831x_buckv_get_voltage_sel, - .list_voltage = wm831x_buckv_list_voltage, - .map_voltage = wm831x_buckv_map_voltage, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .set_suspend_voltage = wm831x_buckv_set_suspend_voltage, - .set_current_limit = wm831x_buckv_set_current_limit, - .get_current_limit = wm831x_buckv_get_current_limit, + .set_current_limit = regulator_set_current_limit_regmap, + .get_current_limit = regulator_get_current_limit_regmap, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, @@ -492,10 +435,16 @@ static int wm831x_buckv_probe(struct platform_device *pdev) dcdc->desc.id = id; dcdc->desc.type = REGULATOR_VOLTAGE; dcdc->desc.n_voltages = WM831X_BUCKV_MAX_SELECTOR + 1; + dcdc->desc.linear_ranges = wm831x_buckv_ranges; + dcdc->desc.n_linear_ranges = ARRAY_SIZE(wm831x_buckv_ranges); dcdc->desc.ops = &wm831x_buckv_ops; dcdc->desc.owner = THIS_MODULE; dcdc->desc.enable_reg = WM831X_DCDC_ENABLE; dcdc->desc.enable_mask = 1 << id; + dcdc->desc.csel_reg = dcdc->base + WM831X_DCDC_CONTROL_2; + dcdc->desc.csel_mask = WM831X_DC1_HC_THR_MASK; + dcdc->desc.n_current_limits = ARRAY_SIZE(wm831x_dcdc_ilim); + dcdc->desc.curr_table = wm831x_dcdc_ilim; ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG); if (ret < 0) { diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index 183fc42a510a..2d7cd344f3bf 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c @@ -153,10 +153,15 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs, const bool * ctx, struct irq_affinity *desc) { - int i, ret; + int i, ret, queue_idx = 0; for (i = 0; i < nvqs; ++i) { - vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i], + if (!names[i]) { + vqs[i] = NULL; + continue; + } + + vqs[i] = rp_find_vq(vdev, queue_idx++, callbacks[i], names[i], ctx ? ctx[i] : false); if (IS_ERR(vqs[i])) { ret = PTR_ERR(vqs[i]); diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index c21da9fe51ec..2e01bd833ffd 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -109,7 +109,7 @@ config RESET_QCOM_PDC config RESET_SIMPLE bool "Simple Reset Controller Driver" if COMPILE_TEST - default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED + default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED help This enables a simple reset controller driver for reset lines that that can be asserted and deasserted by toggling bits in a contiguous, @@ -128,6 +128,14 @@ config RESET_STM32MP157 help This enables the RCC reset controller driver for STM32 MPUs. +config RESET_SOCFPGA + bool "SoCFPGA Reset Driver" if COMPILE_TEST && !ARCH_SOCFPGA + default ARCH_SOCFPGA + select RESET_SIMPLE + help + This enables the reset driver for the SoCFPGA ARMv7 platforms. This + driver gets initialized early during platform init calls. + config RESET_SUNXI bool "Allwinner SoCs Reset Driver" if COMPILE_TEST && !ARCH_SUNXI default ARCH_SUNXI @@ -163,15 +171,15 @@ config RESET_UNIPHIER Say Y if you want to control reset signals provided by System Control block, Media I/O block, Peripheral Block. -config RESET_UNIPHIER_USB3 - tristate "USB3 reset driver for UniPhier SoCs" +config RESET_UNIPHIER_GLUE + tristate "Reset driver in glue layer for UniPhier SoCs" depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF default ARCH_UNIPHIER select RESET_SIMPLE help - Support for the USB3 core reset on UniPhier SoCs. - Say Y if you want to control reset signals provided by - USB3 glue layer. + Support for peripheral core reset included in its own glue layer + on UniPhier SoCs. Say Y if you want to control reset signals + provided by the glue layer. config RESET_ZYNQ bool "ZYNQ Reset Driver" if COMPILE_TEST diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index d08e8b90046a..dc7874df78d9 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -19,10 +19,11 @@ obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o +obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o -obj-$(CONFIG_RESET_UNIPHIER_USB3) += reset-uniphier-usb3.o +obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o diff --git a/drivers/reset/core.c b/drivers/reset/core.c index d1887c0ed5d3..9582efb70025 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -795,3 +795,45 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional) return rstc; } EXPORT_SYMBOL_GPL(devm_reset_control_array_get); + +static int reset_control_get_count_from_lookup(struct device *dev) +{ + const struct reset_control_lookup *lookup; + const char *dev_id; + int count = 0; + + if (!dev) + return -EINVAL; + + dev_id = dev_name(dev); + mutex_lock(&reset_lookup_mutex); + + list_for_each_entry(lookup, &reset_lookup_list, list) { + if (!strcmp(lookup->dev_id, dev_id)) + count++; + } + + mutex_unlock(&reset_lookup_mutex); + + if (count == 0) + count = -ENOENT; + + return count; +} + +/** + * reset_control_get_count - Count number of resets available with a device + * + * @dev: device for which to return the number of resets + * + * Returns positive reset count on success, or error number on failure and + * on count being zero. + */ +int reset_control_get_count(struct device *dev) +{ + if (dev->of_node) + return of_reset_control_get_count(dev->of_node); + + return reset_control_get_count_from_lookup(dev); +} +EXPORT_SYMBOL_GPL(reset_control_get_count); diff --git a/drivers/reset/reset-hsdk.c b/drivers/reset/reset-hsdk.c index 8bce391c6943..4c7b8647b49c 100644 --- a/drivers/reset/reset-hsdk.c +++ b/drivers/reset/reset-hsdk.c @@ -86,6 +86,7 @@ static int hsdk_reset_reset(struct reset_controller_dev *rcdev, static const struct reset_control_ops hsdk_reset_ops = { .reset = hsdk_reset_reset, + .deassert = hsdk_reset_reset, }; static int hsdk_reset_probe(struct platform_device *pdev) diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c index a91107fc9e27..77fbba3100c8 100644 --- a/drivers/reset/reset-simple.c +++ b/drivers/reset/reset-simple.c @@ -109,7 +109,7 @@ struct reset_simple_devdata { #define SOCFPGA_NR_BANKS 8 static const struct reset_simple_devdata reset_simple_socfpga = { - .reg_offset = 0x10, + .reg_offset = 0x20, .nr_resets = SOCFPGA_NR_BANKS * 32, .status_active_low = true, }; @@ -120,7 +120,8 @@ static const struct reset_simple_devdata reset_simple_active_low = { }; static const struct of_device_id reset_simple_dt_ids[] = { - { .compatible = "altr,rst-mgr", .data = &reset_simple_socfpga }, + { .compatible = "altr,stratix10-rst-mgr", + .data = &reset_simple_socfpga }, { .compatible = "st,stm32-rcc", }, { .compatible = "allwinner,sun6i-a31-clock-reset", .data = &reset_simple_active_low }, @@ -166,14 +167,6 @@ static int reset_simple_probe(struct platform_device *pdev) data->status_active_low = devdata->status_active_low; } - if (of_device_is_compatible(dev->of_node, "altr,rst-mgr") && - of_property_read_u32(dev->of_node, "altr,modrst-offset", - ®_offset)) { - dev_warn(dev, - "missing altr,modrst-offset property, assuming 0x%x!\n", - reg_offset); - } - data->membase += reg_offset; return devm_reset_controller_register(dev, &data->rcdev); diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c new file mode 100644 index 000000000000..318cfc51c441 --- /dev/null +++ b/drivers/reset/reset-socfpga.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018, Intel Corporation + * Copied from reset-sunxi.c + */ + +#include <linux/err.h> +#include <linux/io.h> +#include <linux/init.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/reset-controller.h> +#include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/types.h> + +#include "reset-simple.h" + +#define SOCFPGA_NR_BANKS 8 +void __init socfpga_reset_init(void); + +static int a10_reset_init(struct device_node *np) +{ + struct reset_simple_data *data; + struct resource res; + resource_size_t size; + int ret; + u32 reg_offset = 0x10; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = of_address_to_resource(np, 0, &res); + if (ret) + goto err_alloc; + + size = resource_size(&res); + if (!request_mem_region(res.start, size, np->name)) { + ret = -EBUSY; + goto err_alloc; + } + + data->membase = ioremap(res.start, size); + if (!data->membase) { + ret = -ENOMEM; + goto err_alloc; + } + + if (of_property_read_u32(np, "altr,modrst-offset", ®_offset)) + pr_warn("missing altr,modrst-offset property, assuming 0x10\n"); + data->membase += reg_offset; + + spin_lock_init(&data->lock); + + data->rcdev.owner = THIS_MODULE; + data->rcdev.nr_resets = SOCFPGA_NR_BANKS * 32; + data->rcdev.ops = &reset_simple_ops; + data->rcdev.of_node = np; + data->status_active_low = true; + + return reset_controller_register(&data->rcdev); + +err_alloc: + kfree(data); + return ret; +}; + +/* + * These are the reset controller we need to initialize early on in + * our system, before we can even think of using a regular device + * driver for it. + * The controllers that we can register through the regular device + * model are handled by the simple reset driver directly. + */ +static const struct of_device_id socfpga_early_reset_dt_ids[] __initconst = { + { .compatible = "altr,rst-mgr", }, + { /* sentinel */ }, +}; + +void __init socfpga_reset_init(void) +{ + struct device_node *np; + + for_each_matching_node(np, socfpga_early_reset_dt_ids) + a10_reset_init(np); +} diff --git a/drivers/reset/reset-uniphier-usb3.c b/drivers/reset/reset-uniphier-glue.c index ffa1b19b594d..a45923f4df6d 100644 --- a/drivers/reset/reset-uniphier-usb3.c +++ b/drivers/reset/reset-uniphier-glue.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // -// reset-uniphier-usb3.c - USB3 reset driver for UniPhier +// reset-uniphier-glue.c - Glue layer reset driver for UniPhier // Copyright 2018 Socionext Inc. // Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> @@ -15,24 +15,24 @@ #define MAX_CLKS 2 #define MAX_RSTS 2 -struct uniphier_usb3_reset_soc_data { +struct uniphier_glue_reset_soc_data { int nclks; const char * const *clock_names; int nrsts; const char * const *reset_names; }; -struct uniphier_usb3_reset_priv { +struct uniphier_glue_reset_priv { struct clk_bulk_data clk[MAX_CLKS]; struct reset_control *rst[MAX_RSTS]; struct reset_simple_data rdata; - const struct uniphier_usb3_reset_soc_data *data; + const struct uniphier_glue_reset_soc_data *data; }; -static int uniphier_usb3_reset_probe(struct platform_device *pdev) +static int uniphier_glue_reset_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct uniphier_usb3_reset_priv *priv; + struct uniphier_glue_reset_priv *priv; struct resource *res; resource_size_t size; const char *name; @@ -100,9 +100,9 @@ out_rst_assert: return ret; } -static int uniphier_usb3_reset_remove(struct platform_device *pdev) +static int uniphier_glue_reset_remove(struct platform_device *pdev) { - struct uniphier_usb3_reset_priv *priv = platform_get_drvdata(pdev); + struct uniphier_glue_reset_priv *priv = platform_get_drvdata(pdev); int i; for (i = 0; i < priv->data->nrsts; i++) @@ -117,7 +117,7 @@ static const char * const uniphier_pro4_clock_reset_names[] = { "gio", "link", }; -static const struct uniphier_usb3_reset_soc_data uniphier_pro4_data = { +static const struct uniphier_glue_reset_soc_data uniphier_pro4_data = { .nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names), .clock_names = uniphier_pro4_clock_reset_names, .nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names), @@ -128,14 +128,14 @@ static const char * const uniphier_pxs2_clock_reset_names[] = { "link", }; -static const struct uniphier_usb3_reset_soc_data uniphier_pxs2_data = { +static const struct uniphier_glue_reset_soc_data uniphier_pxs2_data = { .nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names), .clock_names = uniphier_pxs2_clock_reset_names, .nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names), .reset_names = uniphier_pxs2_clock_reset_names, }; -static const struct of_device_id uniphier_usb3_reset_match[] = { +static const struct of_device_id uniphier_glue_reset_match[] = { { .compatible = "socionext,uniphier-pro4-usb3-reset", .data = &uniphier_pro4_data, @@ -152,20 +152,32 @@ static const struct of_device_id uniphier_usb3_reset_match[] = { .compatible = "socionext,uniphier-pxs3-usb3-reset", .data = &uniphier_pxs2_data, }, + { + .compatible = "socionext,uniphier-pro4-ahci-reset", + .data = &uniphier_pro4_data, + }, + { + .compatible = "socionext,uniphier-pxs2-ahci-reset", + .data = &uniphier_pxs2_data, + }, + { + .compatible = "socionext,uniphier-pxs3-ahci-reset", + .data = &uniphier_pxs2_data, + }, { /* Sentinel */ } }; -MODULE_DEVICE_TABLE(of, uniphier_usb3_reset_match); +MODULE_DEVICE_TABLE(of, uniphier_glue_reset_match); -static struct platform_driver uniphier_usb3_reset_driver = { - .probe = uniphier_usb3_reset_probe, - .remove = uniphier_usb3_reset_remove, +static struct platform_driver uniphier_glue_reset_driver = { + .probe = uniphier_glue_reset_probe, + .remove = uniphier_glue_reset_remove, .driver = { - .name = "uniphier-usb3-reset", - .of_match_table = uniphier_usb3_reset_match, + .name = "uniphier-glue-reset", + .of_match_table = uniphier_glue_reset_match, }, }; -module_platform_driver(uniphier_usb3_reset_driver); +module_platform_driver(uniphier_glue_reset_driver); MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"); -MODULE_DESCRIPTION("UniPhier USB3 Reset Driver"); +MODULE_DESCRIPTION("UniPhier Glue layer reset driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 4e7b55a14b1a..6e294b4d3635 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -4469,6 +4469,14 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) usrparm.psf_data &= 0x7fffffffULL; usrparm.rssd_result &= 0x7fffffffULL; } + /* at least 2 bytes are accessed and should be allocated */ + if (usrparm.psf_data_len < 2) { + DBF_DEV_EVENT(DBF_WARNING, device, + "Symmetrix ioctl invalid data length %d", + usrparm.psf_data_len); + rc = -EINVAL; + goto out; + } /* alloc I/O data area */ psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA); rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA); diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c index 194ffd5c8580..039b2074db7e 100644 --- a/drivers/s390/char/sclp_config.c +++ b/drivers/s390/char/sclp_config.c @@ -60,7 +60,9 @@ static void sclp_cpu_capability_notify(struct work_struct *work) static void __ref sclp_cpu_change_notify(struct work_struct *work) { + lock_device_hotplug(); smp_rescan_cpus(); + unlock_device_hotplug(); } static void sclp_conf_receiver_fn(struct evbuf_header *evbuf) diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 48ea0004a56d..5a699746c357 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -248,7 +248,8 @@ static inline int ap_test_config(unsigned int *field, unsigned int nr) static inline int ap_test_config_card_id(unsigned int id) { if (!ap_configuration) /* QCI not supported */ - return 1; + /* only ids 0...3F may be probed */ + return id < 0x40 ? 1 : 0; return ap_test_config(ap_configuration->apm, id); } diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c index dcbf5c857743..ed8e58f09054 100644 --- a/drivers/s390/net/ism_drv.c +++ b/drivers/s390/net/ism_drv.c @@ -89,8 +89,8 @@ static int register_sba(struct ism_dev *ism) dma_addr_t dma_handle; struct ism_sba *sba; - sba = dma_zalloc_coherent(&ism->pdev->dev, PAGE_SIZE, - &dma_handle, GFP_KERNEL); + sba = dma_alloc_coherent(&ism->pdev->dev, PAGE_SIZE, &dma_handle, + GFP_KERNEL); if (!sba) return -ENOMEM; @@ -116,8 +116,8 @@ static int register_ieq(struct ism_dev *ism) dma_addr_t dma_handle; struct ism_eq *ieq; - ieq = dma_zalloc_coherent(&ism->pdev->dev, PAGE_SIZE, - &dma_handle, GFP_KERNEL); + ieq = dma_alloc_coherent(&ism->pdev->dev, PAGE_SIZE, &dma_handle, + GFP_KERNEL); if (!ieq) return -ENOMEM; @@ -234,10 +234,9 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct smcd_dmb *dmb) test_and_set_bit(dmb->sba_idx, ism->sba_bitmap)) return -EINVAL; - dmb->cpu_addr = dma_zalloc_coherent(&ism->pdev->dev, dmb->dmb_len, - &dmb->dma_addr, GFP_KERNEL | - __GFP_NOWARN | __GFP_NOMEMALLOC | - __GFP_COMP | __GFP_NORETRY); + dmb->cpu_addr = dma_alloc_coherent(&ism->pdev->dev, dmb->dmb_len, + &dmb->dma_addr, + GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC | __GFP_COMP | __GFP_NORETRY); if (!dmb->cpu_addr) clear_bit(dmb->sba_idx, ism->sba_bitmap); diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 0ee026947f20..122059ecad84 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -22,6 +22,7 @@ #include <linux/hashtable.h> #include <linux/ip.h> #include <linux/refcount.h> +#include <linux/workqueue.h> #include <net/ipv6.h> #include <net/if_inet6.h> @@ -789,6 +790,7 @@ struct qeth_card { struct qeth_seqno seqno; struct qeth_card_options options; + struct workqueue_struct *event_wq; wait_queue_head_t wait_q; spinlock_t mclock; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; @@ -962,7 +964,6 @@ extern const struct attribute_group *qeth_osn_attr_groups[]; extern const struct attribute_group qeth_device_attr_group; extern const struct attribute_group qeth_device_blkt_group; extern const struct device_type qeth_generic_devtype; -extern struct workqueue_struct *qeth_wq; int qeth_card_hw_is_reachable(struct qeth_card *); const char *qeth_get_cardname_short(struct qeth_card *); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index e63e03143ca7..89f912213e62 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -74,8 +74,7 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue, static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf); static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int); -struct workqueue_struct *qeth_wq; -EXPORT_SYMBOL_GPL(qeth_wq); +static struct workqueue_struct *qeth_wq; int qeth_card_hw_is_reachable(struct qeth_card *card) { @@ -566,6 +565,7 @@ static int __qeth_issue_next_read(struct qeth_card *card) QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n", rc, CARD_DEVID(card)); atomic_set(&channel->irq_pending, 0); + qeth_release_buffer(channel, iob); card->read_or_write_problem = 1; qeth_schedule_recovery(card); wake_up(&card->wait_q); @@ -1127,6 +1127,8 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, rc = qeth_get_problem(card, cdev, irb); if (rc) { card->read_or_write_problem = 1; + if (iob) + qeth_release_buffer(iob->channel, iob); qeth_clear_ipacmd_list(card); qeth_schedule_recovery(card); goto out; @@ -1466,6 +1468,10 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev) CARD_RDEV(card) = gdev->cdev[0]; CARD_WDEV(card) = gdev->cdev[1]; CARD_DDEV(card) = gdev->cdev[2]; + + card->event_wq = alloc_ordered_workqueue("%s", 0, dev_name(&gdev->dev)); + if (!card->event_wq) + goto out_wq; if (qeth_setup_channel(&card->read, true)) goto out_ip; if (qeth_setup_channel(&card->write, true)) @@ -1481,6 +1487,8 @@ out_data: out_channel: qeth_clean_channel(&card->read); out_ip: + destroy_workqueue(card->event_wq); +out_wq: dev_set_drvdata(&gdev->dev, NULL); kfree(card); out: @@ -1809,6 +1817,7 @@ static int qeth_idx_activate_get_answer(struct qeth_card *card, QETH_DBF_MESSAGE(2, "Error2 in activating channel rc=%d\n", rc); QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); atomic_set(&channel->irq_pending, 0); + qeth_release_buffer(channel, iob); wake_up(&card->wait_q); return rc; } @@ -1878,6 +1887,7 @@ static int qeth_idx_activate_channel(struct qeth_card *card, rc); QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); atomic_set(&channel->irq_pending, 0); + qeth_release_buffer(channel, iob); wake_up(&card->wait_q); return rc; } @@ -2058,6 +2068,7 @@ int qeth_send_control_data(struct qeth_card *card, int len, } reply = qeth_alloc_reply(card); if (!reply) { + qeth_release_buffer(channel, iob); return -ENOMEM; } reply->callback = reply_cb; @@ -2389,11 +2400,12 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx) return 0; } -static void qeth_free_qdio_out_buf(struct qeth_qdio_out_q *q) +static void qeth_free_output_queue(struct qeth_qdio_out_q *q) { if (!q) return; + qeth_clear_outq_buffers(q, 1); qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q); kfree(q); } @@ -2467,10 +2479,8 @@ out_freeoutqbufs: card->qdio.out_qs[i]->bufs[j] = NULL; } out_freeoutq: - while (i > 0) { - qeth_free_qdio_out_buf(card->qdio.out_qs[--i]); - qeth_clear_outq_buffers(card->qdio.out_qs[i], 1); - } + while (i > 0) + qeth_free_output_queue(card->qdio.out_qs[--i]); kfree(card->qdio.out_qs); card->qdio.out_qs = NULL; out_freepool: @@ -2503,10 +2513,8 @@ static void qeth_free_qdio_buffers(struct qeth_card *card) qeth_free_buffer_pool(card); /* free outbound qdio_qs */ if (card->qdio.out_qs) { - for (i = 0; i < card->qdio.no_out_queues; ++i) { - qeth_clear_outq_buffers(card->qdio.out_qs[i], 1); - qeth_free_qdio_out_buf(card->qdio.out_qs[i]); - } + for (i = 0; i < card->qdio.no_out_queues; i++) + qeth_free_output_queue(card->qdio.out_qs[i]); kfree(card->qdio.out_qs); card->qdio.out_qs = NULL; } @@ -5028,6 +5036,7 @@ static void qeth_core_free_card(struct qeth_card *card) qeth_clean_channel(&card->read); qeth_clean_channel(&card->write); qeth_clean_channel(&card->data); + destroy_workqueue(card->event_wq); qeth_free_qdio_buffers(card); unregister_service_level(&card->qeth_service_level); dev_set_drvdata(&card->gdev->dev, NULL); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index f108d4b44605..a43de2f9bcac 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -369,6 +369,8 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) qeth_clear_cmd_buffers(&card->read); qeth_clear_cmd_buffers(&card->write); } + + flush_workqueue(card->event_wq); } static int qeth_l2_process_inbound_buffer(struct qeth_card *card, @@ -801,6 +803,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) if (cgdev->state == CCWGROUP_ONLINE) qeth_l2_set_offline(cgdev); + + cancel_work_sync(&card->close_dev_work); if (qeth_netdev_is_registered(card->dev)) unregister_netdev(card->dev); } @@ -1434,7 +1438,7 @@ static void qeth_bridge_state_change(struct qeth_card *card, data->card = card; memcpy(&data->qports, qports, sizeof(struct qeth_sbp_state_change) + extrasize); - queue_work(qeth_wq, &data->worker); + queue_work(card->event_wq, &data->worker); } struct qeth_bridge_host_data { @@ -1506,7 +1510,7 @@ static void qeth_bridge_host_event(struct qeth_card *card, data->card = card; memcpy(&data->hostevs, hostevs, sizeof(struct qeth_ipacmd_addr_change) + extrasize); - queue_work(qeth_wq, &data->worker); + queue_work(card->event_wq, &data->worker); } /* SETBRIDGEPORT support; sending commands */ diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 42a7cdc59b76..df34bff4ac31 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1433,6 +1433,8 @@ static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) qeth_clear_cmd_buffers(&card->read); qeth_clear_cmd_buffers(&card->write); } + + flush_workqueue(card->event_wq); } /* @@ -2338,6 +2340,7 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) if (cgdev->state == CCWGROUP_ONLINE) qeth_l3_set_offline(cgdev); + cancel_work_sync(&card->close_dev_work); if (qeth_netdev_is_registered(card->dev)) unregister_netdev(card->dev); qeth_l3_clear_ip_htable(card, 0); diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 9cf30d124b9e..e390f8c6d5f3 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -403,7 +403,6 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) goto failed; /* report size limit per scatter-gather segment */ - adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN; adapter->ccw_device->dev.dma_parms = &adapter->dma_parms; adapter->stat_read_buf_num = FSF_STATUS_READS_RECOM; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 00acc7144bbc..f4f6a07c5222 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -428,6 +428,8 @@ static struct scsi_host_template zfcp_scsi_host_template = { .max_sectors = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1) * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2) * 8, /* GCD, adjusted later */ + /* report size limit per scatter-gather segment */ + .max_segment_size = ZFCP_QDIO_SBALE_LEN, .dma_boundary = ZFCP_QDIO_SBALE_LEN - 1, .shost_attrs = zfcp_sysfs_shost_attrs, .sdev_attrs = zfcp_sysfs_sdev_attrs, diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index fc9dbad476c0..ae1d56da671d 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -635,7 +635,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, { struct virtio_ccw_device *vcdev = to_vc_device(vdev); unsigned long *indicatorp = NULL; - int ret, i; + int ret, i, queue_idx = 0; struct ccw1 *ccw; ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); @@ -643,8 +643,14 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, return -ENOMEM; for (i = 0; i < nvqs; ++i) { - vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i], - ctx ? ctx[i] : false, ccw); + if (!names[i]) { + vqs[i] = NULL; + continue; + } + + vqs[i] = virtio_ccw_setup_vq(vdev, queue_idx++, callbacks[i], + names[i], ctx ? ctx[i] : false, + ccw); if (IS_ERR(vqs[i])) { ret = PTR_ERR(vqs[i]); vqs[i] = NULL; diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index a3c20e3a8b7c..3337b1e80412 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -2009,7 +2009,7 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) struct Scsi_Host *host = NULL; TW_Device_Extension *tw_dev; unsigned long mem_addr, mem_len; - int retval = -ENODEV; + int retval; retval = pci_enable_device(pdev); if (retval) { @@ -2020,8 +2020,10 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) pci_set_master(pdev); pci_try_set_mwi(pdev); - if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) || - dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { + retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (retval) + retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (retval) { TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); retval = -ENODEV; goto out_disable_device; @@ -2240,8 +2242,10 @@ static int twa_resume(struct pci_dev *pdev) pci_set_master(pdev); pci_try_set_mwi(pdev); - if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) || - dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { + retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (retval) + retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (retval) { TW_PRINTK(host, TW_DRIVER, 0x40, "Failed to set dma mask during resume"); retval = -ENODEV; goto out_disable_device; diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c index e8f5f7c63190..dda6fa857709 100644 --- a/drivers/scsi/3w-sas.c +++ b/drivers/scsi/3w-sas.c @@ -646,8 +646,9 @@ static int twl_allocate_memory(TW_Device_Extension *tw_dev, int size, int which) unsigned long *cpu_addr; int retval = 1; - cpu_addr = dma_zalloc_coherent(&tw_dev->tw_pci_dev->dev, - size * TW_Q_LENGTH, &dma_handle, GFP_KERNEL); + cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, + size * TW_Q_LENGTH, &dma_handle, + GFP_KERNEL); if (!cpu_addr) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed"); goto out; @@ -1572,8 +1573,10 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) pci_set_master(pdev); pci_try_set_mwi(pdev); - if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) || - dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { + retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (retval) + retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (retval) { TW_PRINTK(host, TW_DRIVER, 0x18, "Failed to set dma mask"); retval = -ENODEV; goto out_disable_device; @@ -1804,8 +1807,10 @@ static int twl_resume(struct pci_dev *pdev) pci_set_master(pdev); pci_try_set_mwi(pdev); - if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) || - dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { + retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (retval) + retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (retval) { TW_PRINTK(host, TW_DRIVER, 0x25, "Failed to set dma mask during resume"); retval = -ENODEV; goto out_disable_device; diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 128d658d472a..16957d7ac414 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -295,7 +295,7 @@ NCR_700_detect(struct scsi_host_template *tpnt, if(tpnt->sdev_attrs == NULL) tpnt->sdev_attrs = NCR_700_dev_attrs; - memory = dma_alloc_attrs(hostdata->dev, TOTAL_MEM_SIZE, &pScript, + memory = dma_alloc_attrs(dev, TOTAL_MEM_SIZE, &pScript, GFP_KERNEL, DMA_ATTR_NON_CONSISTENT); if(memory == NULL) { printk(KERN_ERR "53c700: Failed to allocate memory for driver, detaching\n"); diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index ff53fd0d12f2..66c514310f3c 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -1123,8 +1123,8 @@ static int inia100_probe_one(struct pci_dev *pdev, /* Get total memory needed for SCB */ sz = ORC_MAXQUEUE * sizeof(struct orc_scb); - host->scb_virt = dma_zalloc_coherent(&pdev->dev, sz, &host->scb_phys, - GFP_KERNEL); + host->scb_virt = dma_alloc_coherent(&pdev->dev, sz, &host->scb_phys, + GFP_KERNEL); if (!host->scb_virt) { printk("inia100: SCB memory allocation error\n"); goto out_host_put; @@ -1132,8 +1132,8 @@ static int inia100_probe_one(struct pci_dev *pdev, /* Get total memory needed for ESCB */ sz = ORC_MAXQUEUE * sizeof(struct orc_extended_scb); - host->escb_virt = dma_zalloc_coherent(&pdev->dev, sz, &host->escb_phys, - GFP_KERNEL); + host->escb_virt = dma_alloc_coherent(&pdev->dev, sz, &host->escb_phys, + GFP_KERNEL); if (!host->escb_virt) { printk("inia100: ESCB memory allocation error\n"); goto out_free_scb_array; diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 634ddb90e7aa..7e56a11836c1 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1747,11 +1747,10 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) shost->max_sectors = (shost->sg_tablesize * 8) + 112; } - error = dma_set_max_seg_size(&pdev->dev, - (aac->adapter_info.options & AAC_OPT_NEW_COMM) ? - (shost->max_sectors << 9) : 65536); - if (error) - goto out_deinit; + if (aac->adapter_info.options & AAC_OPT_NEW_COMM) + shost->max_segment_size = shost->max_sectors << 9; + else + shost->max_segment_size = 65536; /* * Firmware printf works only with older firmware. diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index f83f79b07b50..bbdae67774f0 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -280,7 +280,7 @@ static ssize_t asd_show_dev_rev(struct device *dev, return snprintf(buf, PAGE_SIZE, "%s\n", asd_dev_rev[asd_ha->revision_id]); } -static DEVICE_ATTR(revision, S_IRUGO, asd_show_dev_rev, NULL); +static DEVICE_ATTR(aic_revision, S_IRUGO, asd_show_dev_rev, NULL); static ssize_t asd_show_dev_bios_build(struct device *dev, struct device_attribute *attr,char *buf) @@ -477,7 +477,7 @@ static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha) { int err; - err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_revision); + err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision); if (err) return err; @@ -499,13 +499,13 @@ err_update_bios: err_biosb: device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build); err_rev: - device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision); + device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision); return err; } static void asd_remove_dev_attrs(struct asd_ha_struct *asd_ha) { - device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision); + device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision); device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build); device_remove_file(&asd_ha->pcidev->dev, &dev_attr_pcba_sn); device_remove_file(&asd_ha->pcidev->dev, &dev_attr_update_bios); @@ -769,9 +769,11 @@ static int asd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) if (err) goto Err_remove; - err = -ENODEV; - if (dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(64)) || - dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32))) { + err = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(64)); + if (err) + err = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32)); + if (err) { + err = -ENODEV; asd_printk("no suitable DMA mask for %s\n", pci_name(dev)); goto Err_remove; } diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 0f6751b0a633..57c6fa388bf6 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -587,8 +587,10 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg; acb->roundup_ccbsize = roundup(sizeof(struct MessageUnit_B), 32); - dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize, - &dma_coherent_handle, GFP_KERNEL); + dma_coherent = dma_alloc_coherent(&pdev->dev, + acb->roundup_ccbsize, + &dma_coherent_handle, + GFP_KERNEL); if (!dma_coherent) { pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no); return false; @@ -617,8 +619,10 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb) struct MessageUnit_D *reg; acb->roundup_ccbsize = roundup(sizeof(struct MessageUnit_D), 32); - dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize, - &dma_coherent_handle, GFP_KERNEL); + dma_coherent = dma_alloc_coherent(&pdev->dev, + acb->roundup_ccbsize, + &dma_coherent_handle, + GFP_KERNEL); if (!dma_coherent) { pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no); return false; @@ -659,8 +663,10 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb) uint32_t completeQ_size; completeQ_size = sizeof(struct deliver_completeQ) * ARCMSR_MAX_HBE_DONEQUEUE + 128; acb->roundup_ccbsize = roundup(completeQ_size, 32); - dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize, - &dma_coherent_handle, GFP_KERNEL); + dma_coherent = dma_alloc_coherent(&pdev->dev, + acb->roundup_ccbsize, + &dma_coherent_handle, + GFP_KERNEL); if (!dma_coherent){ pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no); return false; diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 39f3820572b4..74e260027c7d 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3321,8 +3321,8 @@ static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q, q->len = len; q->entry_size = entry_size; mem->size = len * entry_size; - mem->va = dma_zalloc_coherent(&phba->pcidev->dev, mem->size, &mem->dma, - GFP_KERNEL); + mem->va = dma_alloc_coherent(&phba->pcidev->dev, mem->size, &mem->dma, + GFP_KERNEL); if (!mem->va) return -ENOMEM; return 0; diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index ca7b7bbc8371..d4febaadfaa3 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -293,8 +293,8 @@ static int beiscsi_prep_nemb_cmd(struct beiscsi_hba *phba, struct be_dma_mem *cmd, u8 subsystem, u8 opcode, u32 size) { - cmd->va = dma_zalloc_coherent(&phba->ctrl.pdev->dev, size, &cmd->dma, - GFP_KERNEL); + cmd->va = dma_alloc_coherent(&phba->ctrl.pdev->dev, size, &cmd->dma, + GFP_KERNEL); if (!cmd->va) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, "BG_%d : Failed to allocate memory for if info\n"); @@ -1510,10 +1510,9 @@ int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba, return -EINVAL; nonemb_cmd.size = sizeof(union be_invldt_cmds_params); - nonemb_cmd.va = dma_zalloc_coherent(&phba->ctrl.pdev->dev, - nonemb_cmd.size, - &nonemb_cmd.dma, - GFP_KERNEL); + nonemb_cmd.va = dma_alloc_coherent(&phba->ctrl.pdev->dev, + nonemb_cmd.size, &nonemb_cmd.dma, + GFP_KERNEL); if (!nonemb_cmd.va) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, "BM_%d : invldt_cmds_params alloc failed\n"); diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 42a0caf6740d..88880a66a189 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -727,7 +727,7 @@ bfad_init_timer(struct bfad_s *bfad) int bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad) { - int rc = -ENODEV; + int rc = -ENODEV; if (pci_enable_device(pdev)) { printk(KERN_ERR "pci_enable_device fail %p\n", pdev); @@ -739,8 +739,12 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad) pci_set_master(pdev); - if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) || - dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (rc) + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + + if (rc) { + rc = -ENODEV; printk(KERN_ERR "dma_set_mask_and_coherent fail %p\n", pdev); goto out_release_region; } @@ -1534,6 +1538,7 @@ bfad_pci_slot_reset(struct pci_dev *pdev) { struct bfad_s *bfad = pci_get_drvdata(pdev); u8 byte; + int rc; dev_printk(KERN_ERR, &pdev->dev, "bfad_pci_slot_reset flags: 0x%x\n", bfad->bfad_flags); @@ -1561,8 +1566,11 @@ bfad_pci_slot_reset(struct pci_dev *pdev) pci_save_state(pdev); pci_set_master(pdev); - if (dma_set_mask_and_coherent(&bfad->pcidev->dev, DMA_BIT_MASK(64)) || - dma_set_mask_and_coherent(&bfad->pcidev->dev, DMA_BIT_MASK(32))) + rc = dma_set_mask_and_coherent(&bfad->pcidev->dev, DMA_BIT_MASK(64)); + if (rc) + rc = dma_set_mask_and_coherent(&bfad->pcidev->dev, + DMA_BIT_MASK(32)); + if (rc) goto out_disable_device; if (restart_bfa(bfad) == -1) diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 5d163ca1b366..d8e6d7480f35 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -3264,9 +3264,9 @@ bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf, /* Allocate dma coherent memory */ buf_info = buf_base; buf_info->size = payload_len; - buf_info->virt = dma_zalloc_coherent(&bfad->pcidev->dev, - buf_info->size, &buf_info->phys, - GFP_KERNEL); + buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev, + buf_info->size, &buf_info->phys, + GFP_KERNEL); if (!buf_info->virt) goto out_free_mem; diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index e8ae4d671d23..039328d9ef13 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c @@ -1857,10 +1857,10 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba) * entries. Hence the limit with one page is 8192 task context * entries. */ - hba->task_ctx_bd_tbl = dma_zalloc_coherent(&hba->pcidev->dev, - PAGE_SIZE, - &hba->task_ctx_bd_dma, - GFP_KERNEL); + hba->task_ctx_bd_tbl = dma_alloc_coherent(&hba->pcidev->dev, + PAGE_SIZE, + &hba->task_ctx_bd_dma, + GFP_KERNEL); if (!hba->task_ctx_bd_tbl) { printk(KERN_ERR PFX "unable to allocate task context BDT\n"); rc = -1; @@ -1894,10 +1894,10 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba) task_ctx_bdt = (struct regpair *)hba->task_ctx_bd_tbl; for (i = 0; i < task_ctx_arr_sz; i++) { - hba->task_ctx[i] = dma_zalloc_coherent(&hba->pcidev->dev, - PAGE_SIZE, - &hba->task_ctx_dma[i], - GFP_KERNEL); + hba->task_ctx[i] = dma_alloc_coherent(&hba->pcidev->dev, + PAGE_SIZE, + &hba->task_ctx_dma[i], + GFP_KERNEL); if (!hba->task_ctx[i]) { printk(KERN_ERR PFX "unable to alloc task context\n"); rc = -1; @@ -2031,19 +2031,19 @@ static int bnx2fc_allocate_hash_table(struct bnx2fc_hba *hba) } for (i = 0; i < segment_count; ++i) { - hba->hash_tbl_segments[i] = dma_zalloc_coherent(&hba->pcidev->dev, - BNX2FC_HASH_TBL_CHUNK_SIZE, - &dma_segment_array[i], - GFP_KERNEL); + hba->hash_tbl_segments[i] = dma_alloc_coherent(&hba->pcidev->dev, + BNX2FC_HASH_TBL_CHUNK_SIZE, + &dma_segment_array[i], + GFP_KERNEL); if (!hba->hash_tbl_segments[i]) { printk(KERN_ERR PFX "hash segment alloc failed\n"); goto cleanup_dma; } } - hba->hash_tbl_pbl = dma_zalloc_coherent(&hba->pcidev->dev, PAGE_SIZE, - &hba->hash_tbl_pbl_dma, - GFP_KERNEL); + hba->hash_tbl_pbl = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE, + &hba->hash_tbl_pbl_dma, + GFP_KERNEL); if (!hba->hash_tbl_pbl) { printk(KERN_ERR PFX "hash table pbl alloc failed\n"); goto cleanup_dma; @@ -2104,10 +2104,9 @@ int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba) return -ENOMEM; mem_size = BNX2FC_NUM_MAX_SESS * sizeof(struct regpair); - hba->t2_hash_tbl_ptr = dma_zalloc_coherent(&hba->pcidev->dev, - mem_size, - &hba->t2_hash_tbl_ptr_dma, - GFP_KERNEL); + hba->t2_hash_tbl_ptr = dma_alloc_coherent(&hba->pcidev->dev, mem_size, + &hba->t2_hash_tbl_ptr_dma, + GFP_KERNEL); if (!hba->t2_hash_tbl_ptr) { printk(KERN_ERR PFX "unable to allocate t2 hash table ptr\n"); bnx2fc_free_fw_resc(hba); @@ -2116,9 +2115,9 @@ int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba) mem_size = BNX2FC_NUM_MAX_SESS * sizeof(struct fcoe_t2_hash_table_entry); - hba->t2_hash_tbl = dma_zalloc_coherent(&hba->pcidev->dev, mem_size, - &hba->t2_hash_tbl_dma, - GFP_KERNEL); + hba->t2_hash_tbl = dma_alloc_coherent(&hba->pcidev->dev, mem_size, + &hba->t2_hash_tbl_dma, + GFP_KERNEL); if (!hba->t2_hash_tbl) { printk(KERN_ERR PFX "unable to allocate t2 hash table\n"); bnx2fc_free_fw_resc(hba); @@ -2140,9 +2139,9 @@ int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba) return -ENOMEM; } - hba->stats_buffer = dma_zalloc_coherent(&hba->pcidev->dev, PAGE_SIZE, - &hba->stats_buf_dma, - GFP_KERNEL); + hba->stats_buffer = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE, + &hba->stats_buf_dma, + GFP_KERNEL); if (!hba->stats_buffer) { printk(KERN_ERR PFX "unable to alloc Stats Buffer\n"); bnx2fc_free_fw_resc(hba); diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index 350257c13a5b..bc9f2a2365f4 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c @@ -240,6 +240,7 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba) return NULL; } + cmgr->hba = hba; cmgr->free_list = kcalloc(arr_sz, sizeof(*cmgr->free_list), GFP_KERNEL); if (!cmgr->free_list) { @@ -256,7 +257,6 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba) goto mem_err; } - cmgr->hba = hba; cmgr->cmds = (struct bnx2fc_cmd **)(cmgr + 1); for (i = 0; i < arr_sz; i++) { @@ -295,7 +295,7 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba) /* Allocate pool of io_bdts - one for each bnx2fc_cmd */ mem_size = num_ios * sizeof(struct io_bdt *); - cmgr->io_bdt_pool = kmalloc(mem_size, GFP_KERNEL); + cmgr->io_bdt_pool = kzalloc(mem_size, GFP_KERNEL); if (!cmgr->io_bdt_pool) { printk(KERN_ERR PFX "failed to alloc io_bdt_pool\n"); goto mem_err; diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c index e3d1c7c440c8..d735e87e416a 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c +++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c @@ -672,8 +672,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba, tgt->sq_mem_size = (tgt->sq_mem_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK; - tgt->sq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size, - &tgt->sq_dma, GFP_KERNEL); + tgt->sq = dma_alloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size, + &tgt->sq_dma, GFP_KERNEL); if (!tgt->sq) { printk(KERN_ERR PFX "unable to allocate SQ memory %d\n", tgt->sq_mem_size); @@ -685,8 +685,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba, tgt->cq_mem_size = (tgt->cq_mem_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK; - tgt->cq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size, - &tgt->cq_dma, GFP_KERNEL); + tgt->cq = dma_alloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size, + &tgt->cq_dma, GFP_KERNEL); if (!tgt->cq) { printk(KERN_ERR PFX "unable to allocate CQ memory %d\n", tgt->cq_mem_size); @@ -698,8 +698,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba, tgt->rq_mem_size = (tgt->rq_mem_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK; - tgt->rq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size, - &tgt->rq_dma, GFP_KERNEL); + tgt->rq = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size, + &tgt->rq_dma, GFP_KERNEL); if (!tgt->rq) { printk(KERN_ERR PFX "unable to allocate RQ memory %d\n", tgt->rq_mem_size); @@ -710,8 +710,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba, tgt->rq_pbl_size = (tgt->rq_pbl_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK; - tgt->rq_pbl = dma_zalloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size, - &tgt->rq_pbl_dma, GFP_KERNEL); + tgt->rq_pbl = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size, + &tgt->rq_pbl_dma, GFP_KERNEL); if (!tgt->rq_pbl) { printk(KERN_ERR PFX "unable to allocate RQ PBL %d\n", tgt->rq_pbl_size); @@ -735,9 +735,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba, tgt->xferq_mem_size = (tgt->xferq_mem_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK; - tgt->xferq = dma_zalloc_coherent(&hba->pcidev->dev, - tgt->xferq_mem_size, &tgt->xferq_dma, - GFP_KERNEL); + tgt->xferq = dma_alloc_coherent(&hba->pcidev->dev, + tgt->xferq_mem_size, &tgt->xferq_dma, + GFP_KERNEL); if (!tgt->xferq) { printk(KERN_ERR PFX "unable to allocate XFERQ %d\n", tgt->xferq_mem_size); @@ -749,9 +749,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba, tgt->confq_mem_size = (tgt->confq_mem_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK; - tgt->confq = dma_zalloc_coherent(&hba->pcidev->dev, - tgt->confq_mem_size, &tgt->confq_dma, - GFP_KERNEL); + tgt->confq = dma_alloc_coherent(&hba->pcidev->dev, + tgt->confq_mem_size, &tgt->confq_dma, + GFP_KERNEL); if (!tgt->confq) { printk(KERN_ERR PFX "unable to allocate CONFQ %d\n", tgt->confq_mem_size); @@ -763,9 +763,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba, tgt->confq_pbl_size = (tgt->confq_pbl_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK; - tgt->confq_pbl = dma_zalloc_coherent(&hba->pcidev->dev, - tgt->confq_pbl_size, - &tgt->confq_pbl_dma, GFP_KERNEL); + tgt->confq_pbl = dma_alloc_coherent(&hba->pcidev->dev, + tgt->confq_pbl_size, + &tgt->confq_pbl_dma, GFP_KERNEL); if (!tgt->confq_pbl) { printk(KERN_ERR PFX "unable to allocate CONFQ PBL %d\n", tgt->confq_pbl_size); @@ -787,9 +787,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba, /* Allocate and map ConnDB */ tgt->conn_db_mem_size = sizeof(struct fcoe_conn_db); - tgt->conn_db = dma_zalloc_coherent(&hba->pcidev->dev, - tgt->conn_db_mem_size, - &tgt->conn_db_dma, GFP_KERNEL); + tgt->conn_db = dma_alloc_coherent(&hba->pcidev->dev, + tgt->conn_db_mem_size, + &tgt->conn_db_dma, GFP_KERNEL); if (!tgt->conn_db) { printk(KERN_ERR PFX "unable to allocate conn_db %d\n", tgt->conn_db_mem_size); @@ -802,8 +802,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba, tgt->lcq_mem_size = (tgt->lcq_mem_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK; - tgt->lcq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->lcq_mem_size, - &tgt->lcq_dma, GFP_KERNEL); + tgt->lcq = dma_alloc_coherent(&hba->pcidev->dev, tgt->lcq_mem_size, + &tgt->lcq_dma, GFP_KERNEL); if (!tgt->lcq) { printk(KERN_ERR PFX "unable to allocate lcq %d\n", diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 91f5316aa3ab..fae6f71e677d 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1070,8 +1070,8 @@ int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) /* Allocate memory area for actual SQ element */ ep->qp.sq_virt = - dma_zalloc_coherent(&hba->pcidev->dev, ep->qp.sq_mem_size, - &ep->qp.sq_phys, GFP_KERNEL); + dma_alloc_coherent(&hba->pcidev->dev, ep->qp.sq_mem_size, + &ep->qp.sq_phys, GFP_KERNEL); if (!ep->qp.sq_virt) { printk(KERN_ALERT "bnx2i: unable to alloc SQ BD memory %d\n", ep->qp.sq_mem_size); @@ -1106,8 +1106,8 @@ int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) /* Allocate memory area for actual CQ element */ ep->qp.cq_virt = - dma_zalloc_coherent(&hba->pcidev->dev, ep->qp.cq_mem_size, - &ep->qp.cq_phys, GFP_KERNEL); + dma_alloc_coherent(&hba->pcidev->dev, ep->qp.cq_mem_size, + &ep->qp.cq_phys, GFP_KERNEL); if (!ep->qp.cq_virt) { printk(KERN_ALERT "bnx2i: unable to alloc CQ BD memory %d\n", ep->qp.cq_mem_size); diff --git a/drivers/scsi/csiostor/csio_attr.c b/drivers/scsi/csiostor/csio_attr.c index 8a004036e3d7..9bd2bd8dc2be 100644 --- a/drivers/scsi/csiostor/csio_attr.c +++ b/drivers/scsi/csiostor/csio_attr.c @@ -594,12 +594,12 @@ csio_vport_create(struct fc_vport *fc_vport, bool disable) } fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING); + ln->fc_vport = fc_vport; if (csio_fcoe_alloc_vnp(hw, ln)) goto error; *(struct csio_lnode **)fc_vport->dd_data = ln; - ln->fc_vport = fc_vport; if (!fc_vport->node_name) fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln)); if (!fc_vport->port_name) diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c index cf629380a981..616b25bf7941 100644 --- a/drivers/scsi/csiostor/csio_init.c +++ b/drivers/scsi/csiostor/csio_init.c @@ -210,8 +210,11 @@ csio_pci_init(struct pci_dev *pdev, int *bars) pci_set_master(pdev); pci_try_set_mwi(pdev); - if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) || - dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { + rv = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (rv) + rv = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (rv) { + rv = -ENODEV; dev_err(&pdev->dev, "No suitable DMA available.\n"); goto err_release_regions; } diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c index dc12933533d5..66bbd21819ae 100644 --- a/drivers/scsi/csiostor/csio_wr.c +++ b/drivers/scsi/csiostor/csio_wr.c @@ -233,8 +233,8 @@ csio_wr_alloc_q(struct csio_hw *hw, uint32_t qsize, uint32_t wrsize, q = wrm->q_arr[free_idx]; - q->vstart = dma_zalloc_coherent(&hw->pdev->dev, qsz, &q->pstart, - GFP_KERNEL); + q->vstart = dma_alloc_coherent(&hw->pdev->dev, qsz, &q->pstart, + GFP_KERNEL); if (!q->vstart) { csio_err(hw, "Failed to allocate DMA memory for " diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c index 8a20411699d9..75e1273a44b3 100644 --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c @@ -1144,7 +1144,7 @@ static void ddp_clear_map(struct cxgbi_device *cdev, struct cxgbi_ppm *ppm, } static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, - unsigned int tid, int pg_idx, bool reply) + unsigned int tid, int pg_idx) { struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0, GFP_KERNEL); @@ -1160,7 +1160,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, req = (struct cpl_set_tcb_field *)skb->head; req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); - req->reply = V_NO_REPLY(reply ? 0 : 1); + req->reply = V_NO_REPLY(1); req->cpu_idx = 0; req->word = htons(31); req->mask = cpu_to_be64(0xF0000000); @@ -1177,11 +1177,10 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, * @tid: connection id * @hcrc: header digest enabled * @dcrc: data digest enabled - * @reply: request reply from h/w * set up the iscsi digest settings for a connection identified by tid */ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, - int hcrc, int dcrc, int reply) + int hcrc, int dcrc) { struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0, GFP_KERNEL); @@ -1197,7 +1196,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, req = (struct cpl_set_tcb_field *)skb->head; req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); - req->reply = V_NO_REPLY(reply ? 0 : 1); + req->reply = V_NO_REPLY(1); req->cpu_idx = 0; req->word = htons(31); req->mask = cpu_to_be64(0x0F000000); diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 49f8028ac524..d26f50af00ea 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -1548,16 +1548,22 @@ static void do_set_tcb_rpl(struct cxgbi_device *cdev, struct sk_buff *skb) struct cxgbi_sock *csk; csk = lookup_tid(t, tid); - if (!csk) + if (!csk) { pr_err("can't find conn. for tid %u.\n", tid); + return; + } log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,%lx,%u, status 0x%x.\n", csk, csk->state, csk->flags, csk->tid, rpl->status); - if (rpl->status != CPL_ERR_NONE) + if (rpl->status != CPL_ERR_NONE) { pr_err("csk 0x%p,%u, SET_TCB_RPL status %u.\n", csk, tid, rpl->status); + csk->err = -EINVAL; + } + + complete(&csk->cmpl); __kfree_skb(skb); } @@ -1983,7 +1989,7 @@ static int ddp_set_map(struct cxgbi_ppm *ppm, struct cxgbi_sock *csk, } static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid, - int pg_idx, bool reply) + int pg_idx) { struct sk_buff *skb; struct cpl_set_tcb_field *req; @@ -1999,7 +2005,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid, req = (struct cpl_set_tcb_field *)skb->head; INIT_TP_WR(req, csk->tid); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid)); - req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid)); + req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid)); req->word_cookie = htons(0); req->mask = cpu_to_be64(0x3 << 8); req->val = cpu_to_be64(pg_idx << 8); @@ -2008,12 +2014,15 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid, log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, "csk 0x%p, tid 0x%x, pg_idx %u.\n", csk, csk->tid, pg_idx); + reinit_completion(&csk->cmpl); cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb); - return 0; + wait_for_completion(&csk->cmpl); + + return csk->err; } static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, - int hcrc, int dcrc, int reply) + int hcrc, int dcrc) { struct sk_buff *skb; struct cpl_set_tcb_field *req; @@ -2031,7 +2040,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, req = (struct cpl_set_tcb_field *)skb->head; INIT_TP_WR(req, tid); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); - req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid)); + req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid)); req->word_cookie = htons(0); req->mask = cpu_to_be64(0x3 << 4); req->val = cpu_to_be64(((hcrc ? ULP_CRC_HEADER : 0) | @@ -2041,8 +2050,11 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, "csk 0x%p, tid 0x%x, crc %d,%d.\n", csk, csk->tid, hcrc, dcrc); + reinit_completion(&csk->cmpl); cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb); - return 0; + wait_for_completion(&csk->cmpl); + + return csk->err; } static struct cxgbi_ppm *cdev2ppm(struct cxgbi_device *cdev) diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 75f876409fb9..245742557c03 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -573,6 +573,7 @@ static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev) skb_queue_head_init(&csk->receive_queue); skb_queue_head_init(&csk->write_queue); timer_setup(&csk->retry_timer, NULL, 0); + init_completion(&csk->cmpl); rwlock_init(&csk->callback_lock); csk->cdev = cdev; csk->flags = 0; @@ -2251,14 +2252,14 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn, if (!err && conn->hdrdgst_en) err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid, conn->hdrdgst_en, - conn->datadgst_en, 0); + conn->datadgst_en); break; case ISCSI_PARAM_DATADGST_EN: err = iscsi_set_param(cls_conn, param, buf, buflen); if (!err && conn->datadgst_en) err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid, conn->hdrdgst_en, - conn->datadgst_en, 0); + conn->datadgst_en); break; case ISCSI_PARAM_MAX_R2T: return iscsi_tcp_set_max_r2t(conn, buf); @@ -2384,7 +2385,7 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session, ppm = csk->cdev->cdev2ppm(csk->cdev); err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid, - ppm->tformat.pgsz_idx_dflt, 0); + ppm->tformat.pgsz_idx_dflt); if (err < 0) return err; diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 5d5d8b50d842..1917ff57651d 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -149,6 +149,7 @@ struct cxgbi_sock { struct sk_buff_head receive_queue; struct sk_buff_head write_queue; struct timer_list retry_timer; + struct completion cmpl; int err; rwlock_t callback_lock; void *user_data; @@ -490,9 +491,9 @@ struct cxgbi_device { struct cxgbi_ppm *, struct cxgbi_task_tag_info *); int (*csk_ddp_setup_digest)(struct cxgbi_sock *, - unsigned int, int, int, int); + unsigned int, int, int); int (*csk_ddp_setup_pgidx)(struct cxgbi_sock *, - unsigned int, int, bool); + unsigned int, int); void (*csk_release_offload_resources)(struct cxgbi_sock *); int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *); diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index bfa13e3b191c..c8bad2c093b8 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -3687,6 +3687,7 @@ static int cxlflash_probe(struct pci_dev *pdev, host->max_cmd_len = CXLFLASH_MAX_CDB_LEN; cfg = shost_priv(host); + cfg->state = STATE_PROBING; cfg->host = host; rc = alloc_mem(cfg); if (rc) { @@ -3775,6 +3776,7 @@ out: return rc; out_remove: + cfg->state = STATE_PROBED; cxlflash_remove(pdev); goto out; } diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index eed7fc5b3389..bc17fa0d8375 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2323,6 +2323,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev, struct Scsi_Host *shost; struct hisi_hba *hisi_hba; struct device *dev = &pdev->dev; + int error; shost = scsi_host_alloc(hw->sht, sizeof(*hisi_hba)); if (!shost) { @@ -2343,8 +2344,11 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev, if (hisi_sas_get_fw_info(hisi_hba) < 0) goto err_out; - if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) && - dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { + error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + if (error) + error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + + if (error) { dev_err(dev, "No usable DMA addressing method\n"); goto err_out; } diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index e2420a810e99..e0570fd8466e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2447,10 +2447,12 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) goto err_out_disable_device; - if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) || - dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (rc) + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (rc) { dev_err(dev, "No usable DMA addressing method\n"); - rc = -EIO; + rc = -ENODEV; goto err_out_regions; } @@ -2507,6 +2509,12 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) sha->sas_port[i] = &hisi_hba->port[i].sas_port; } + if (hisi_hba->prot_mask) { + dev_info(dev, "Registering for DIF/DIX prot_mask=0x%x\n", + prot_mask); + scsi_host_set_prot(hisi_hba->shost, prot_mask); + } + rc = scsi_add_host(shost, dev); if (rc) goto err_out_ha; @@ -2519,12 +2527,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) goto err_out_register_ha; - if (hisi_hba->prot_mask) { - dev_info(dev, "Registering for DIF/DIX prot_mask=0x%x\n", - prot_mask); - scsi_host_set_prot(hisi_hba->shost, prot_mask); - } - scsi_scan_host(shost); return 0; diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 3eedfd4f8f57..251c084a6ff0 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -1292,6 +1292,7 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id) dma_addr_t start_phy; void *start_virt; u32 offset, i, req_size; + int rc; dprintk("hptiop_probe(%p)\n", pcidev); @@ -1308,9 +1309,12 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id) /* Enable 64bit DMA if possible */ iop_ops = (struct hptiop_adapter_ops *)id->driver_data; - if (dma_set_mask(&pcidev->dev, - DMA_BIT_MASK(iop_ops->hw_dma_bit_mask)) || - dma_set_mask(&pcidev->dev, DMA_BIT_MASK(32))) { + rc = dma_set_mask(&pcidev->dev, + DMA_BIT_MASK(iop_ops->hw_dma_bit_mask)); + if (rc) + rc = dma_set_mask(&pcidev->dev, DMA_BIT_MASK(32)); + + if (rc) { printk(KERN_ERR "hptiop: fail to set dma_mask\n"); goto disable_pci_device; } diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 68b90c4f79a3..1727d0c71b12 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -576,6 +576,13 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) shost->max_lun = ~0; shost->max_cmd_len = MAX_COMMAND_SIZE; + /* turn on DIF support */ + scsi_host_set_prot(shost, + SHOST_DIF_TYPE1_PROTECTION | + SHOST_DIF_TYPE2_PROTECTION | + SHOST_DIF_TYPE3_PROTECTION); + scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); + err = scsi_add_host(shost, &pdev->dev); if (err) goto err_shost; @@ -663,13 +670,6 @@ static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_host_alloc; } pci_info->hosts[i] = h; - - /* turn on DIF support */ - scsi_host_set_prot(to_shost(h), - SHOST_DIF_TYPE1_PROTECTION | - SHOST_DIF_TYPE2_PROTECTION | - SHOST_DIF_TYPE3_PROTECTION); - scsi_host_set_guard(to_shost(h), SHOST_DIX_GUARD_CRC); } err = isci_setup_interrupts(pdev); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index be83590ed955..ff943f477d6f 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1726,14 +1726,14 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, fc_frame_payload_op(fp) != ELS_LS_ACC) { FC_LPORT_DBG(lport, "FLOGI not accepted or bad response\n"); fc_lport_error(lport, fp); - goto err; + goto out; } flp = fc_frame_payload_get(fp, sizeof(*flp)); if (!flp) { FC_LPORT_DBG(lport, "FLOGI bad response\n"); fc_lport_error(lport, fp); - goto err; + goto out; } mfs = ntohs(flp->fl_csp.sp_bb_data) & @@ -1743,7 +1743,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, FC_LPORT_DBG(lport, "FLOGI bad mfs:%hu response, " "lport->mfs:%hu\n", mfs, lport->mfs); fc_lport_error(lport, fp); - goto err; + goto out; } if (mfs <= lport->mfs) { diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 9192a1d9dec6..dfba4921b265 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -184,7 +184,6 @@ void fc_rport_destroy(struct kref *kref) struct fc_rport_priv *rdata; rdata = container_of(kref, struct fc_rport_priv, kref); - WARN_ON(!list_empty(&rdata->peers)); kfree_rcu(rdata, rcu); } EXPORT_SYMBOL(fc_rport_destroy); diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index b8d325ce8754..120fc520f27a 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1459,7 +1459,13 @@ static int iscsi_xmit_task(struct iscsi_conn *conn) if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) return -ENODATA; + spin_lock_bh(&conn->session->back_lock); + if (conn->task == NULL) { + spin_unlock_bh(&conn->session->back_lock); + return -ENODATA; + } __iscsi_get_task(task); + spin_unlock_bh(&conn->session->back_lock); spin_unlock_bh(&conn->session->frwd_lock); rc = conn->session->tt->xmit_task(task); spin_lock_bh(&conn->session->frwd_lock); diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 17eb4185f29d..f21c93bbb35c 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -828,6 +828,7 @@ static struct domain_device *sas_ex_discover_end_dev( rphy = sas_end_device_alloc(phy->port); if (!rphy) goto out_free; + rphy->identify.phy_identifier = phy_id; child->rphy = rphy; get_device(&rphy->dev); @@ -854,6 +855,7 @@ static struct domain_device *sas_ex_discover_end_dev( child->rphy = rphy; get_device(&rphy->dev); + rphy->identify.phy_identifier = phy_id; sas_fill_in_rphy(child, rphy); list_add_tail(&child->disco_list_node, &parent->port->disco_list); diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 8698af86485d..2dc564e59430 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -2730,8 +2730,8 @@ lpfc_bsg_dma_page_alloc(struct lpfc_hba *phba) INIT_LIST_HEAD(&dmabuf->list); /* now, allocate dma buffer */ - dmabuf->virt = dma_zalloc_coherent(&pcidev->dev, BSG_MBOX_SIZE, - &(dmabuf->phys), GFP_KERNEL); + dmabuf->virt = dma_alloc_coherent(&pcidev->dev, BSG_MBOX_SIZE, + &(dmabuf->phys), GFP_KERNEL); if (!dmabuf->virt) { kfree(dmabuf); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index c1c36812c3d2..e1129260ed18 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -6973,9 +6973,9 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) if (!dmabuf) return NULL; - dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev, - LPFC_HDR_TEMPLATE_SIZE, - &dmabuf->phys, GFP_KERNEL); + dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, + LPFC_HDR_TEMPLATE_SIZE, + &dmabuf->phys, GFP_KERNEL); if (!dmabuf->virt) { rpi_hdr = NULL; goto err_free_dmabuf; @@ -7361,15 +7361,18 @@ lpfc_sli_pci_mem_setup(struct lpfc_hba *phba) unsigned long bar0map_len, bar2map_len; int i, hbq_count; void *ptr; - int error = -ENODEV; + int error; if (!pdev) - return error; + return -ENODEV; /* Set the device DMA mask size */ - if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) || - dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) + error = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (error) + error = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (error) return error; + error = -ENODEV; /* Get the bus address of Bar0 and Bar2 and the number of bytes * required by each mapping. @@ -7397,8 +7400,8 @@ lpfc_sli_pci_mem_setup(struct lpfc_hba *phba) } /* Allocate memory for SLI-2 structures */ - phba->slim2p.virt = dma_zalloc_coherent(&pdev->dev, SLI2_SLIM_SIZE, - &phba->slim2p.phys, GFP_KERNEL); + phba->slim2p.virt = dma_alloc_coherent(&pdev->dev, SLI2_SLIM_SIZE, + &phba->slim2p.phys, GFP_KERNEL); if (!phba->slim2p.virt) goto out_iounmap; @@ -7816,8 +7819,8 @@ lpfc_create_bootstrap_mbox(struct lpfc_hba *phba) * plus an alignment restriction of 16 bytes. */ bmbx_size = sizeof(struct lpfc_bmbx_create) + (LPFC_ALIGN_16_BYTE - 1); - dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev, bmbx_size, - &dmabuf->phys, GFP_KERNEL); + dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, bmbx_size, + &dmabuf->phys, GFP_KERNEL); if (!dmabuf->virt) { kfree(dmabuf); return -ENOMEM; @@ -9742,11 +9745,13 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) uint32_t if_type; if (!pdev) - return error; + return -ENODEV; /* Set the device DMA mask size */ - if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) || - dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) + error = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (error) + error = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (error) return error; /* diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index f6a5083a621e..4d3b94317515 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -1827,9 +1827,9 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox, * page, this is used as a priori size of SLI4_PAGE_SIZE for * the later DMA memory free. */ - viraddr = dma_zalloc_coherent(&phba->pcidev->dev, - SLI4_PAGE_SIZE, &phyaddr, - GFP_KERNEL); + viraddr = dma_alloc_coherent(&phba->pcidev->dev, + SLI4_PAGE_SIZE, &phyaddr, + GFP_KERNEL); /* In case of malloc fails, proceed with whatever we have */ if (!viraddr) break; diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 4c66b19e6199..8c9f79042228 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -297,7 +297,8 @@ lpfc_nvme_localport_delete(struct nvme_fc_local_port *localport) lport); /* release any threads waiting for the unreg to complete */ - complete(&lport->lport_unreg_done); + if (lport->vport->localport) + complete(lport->lport_unreg_cmp); } /* lpfc_nvme_remoteport_delete @@ -2545,7 +2546,8 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport) */ void lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport, - struct lpfc_nvme_lport *lport) + struct lpfc_nvme_lport *lport, + struct completion *lport_unreg_cmp) { #if (IS_ENABLED(CONFIG_NVME_FC)) u32 wait_tmo; @@ -2557,8 +2559,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport, */ wait_tmo = msecs_to_jiffies(LPFC_NVME_WAIT_TMO * 1000); while (true) { - ret = wait_for_completion_timeout(&lport->lport_unreg_done, - wait_tmo); + ret = wait_for_completion_timeout(lport_unreg_cmp, wait_tmo); if (unlikely(!ret)) { lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR, "6176 Lport %p Localport %p wait " @@ -2592,12 +2593,12 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport) struct lpfc_nvme_lport *lport; struct lpfc_nvme_ctrl_stat *cstat; int ret; + DECLARE_COMPLETION_ONSTACK(lport_unreg_cmp); if (vport->nvmei_support == 0) return; localport = vport->localport; - vport->localport = NULL; lport = (struct lpfc_nvme_lport *)localport->private; cstat = lport->cstat; @@ -2608,13 +2609,14 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport) /* lport's rport list is clear. Unregister * lport and release resources. */ - init_completion(&lport->lport_unreg_done); + lport->lport_unreg_cmp = &lport_unreg_cmp; ret = nvme_fc_unregister_localport(localport); /* Wait for completion. This either blocks * indefinitely or succeeds */ - lpfc_nvme_lport_unreg_wait(vport, lport); + lpfc_nvme_lport_unreg_wait(vport, lport, &lport_unreg_cmp); + vport->localport = NULL; kfree(cstat); /* Regardless of the unregister upcall response, clear diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h index cfd4719be25c..b234d0298994 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.h +++ b/drivers/scsi/lpfc/lpfc_nvme.h @@ -50,7 +50,7 @@ struct lpfc_nvme_ctrl_stat { /* Declare nvme-based local and remote port definitions. */ struct lpfc_nvme_lport { struct lpfc_vport *vport; - struct completion lport_unreg_done; + struct completion *lport_unreg_cmp; /* Add stats counters here */ struct lpfc_nvme_ctrl_stat *cstat; atomic_t fc4NvmeLsRequests; diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 6245f442d784..95fee83090eb 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1003,7 +1003,8 @@ lpfc_nvmet_targetport_delete(struct nvmet_fc_target_port *targetport) struct lpfc_nvmet_tgtport *tport = targetport->private; /* release any threads waiting for the unreg to complete */ - complete(&tport->tport_unreg_done); + if (tport->phba->targetport) + complete(tport->tport_unreg_cmp); } static void @@ -1692,6 +1693,7 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba) struct lpfc_nvmet_tgtport *tgtp; struct lpfc_queue *wq; uint32_t qidx; + DECLARE_COMPLETION_ONSTACK(tport_unreg_cmp); if (phba->nvmet_support == 0) return; @@ -1701,9 +1703,9 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba) wq = phba->sli4_hba.nvme_wq[qidx]; lpfc_nvmet_wqfull_flush(phba, wq, NULL); } - init_completion(&tgtp->tport_unreg_done); + tgtp->tport_unreg_cmp = &tport_unreg_cmp; nvmet_fc_unregister_targetport(phba->targetport); - wait_for_completion_timeout(&tgtp->tport_unreg_done, 5); + wait_for_completion_timeout(&tport_unreg_cmp, 5); lpfc_nvmet_cleanup_io_context(phba); } phba->targetport = NULL; diff --git a/drivers/scsi/lpfc/lpfc_nvmet.h b/drivers/scsi/lpfc/lpfc_nvmet.h index 1aaff63f1f41..0ec1082ce7ef 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.h +++ b/drivers/scsi/lpfc/lpfc_nvmet.h @@ -34,7 +34,7 @@ /* Used for NVME Target */ struct lpfc_nvmet_tgtport { struct lpfc_hba *phba; - struct completion tport_unreg_done; + struct completion *tport_unreg_cmp; /* Stats counters - lpfc_nvmet_unsol_ls_buffer */ atomic_t rcv_ls_req_in; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 30734caf77e1..2242e9b3ca12 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -5362,8 +5362,8 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, * mailbox command. */ dma_size = *vpd_size; - dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev, dma_size, - &dmabuf->phys, GFP_KERNEL); + dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, dma_size, + &dmabuf->phys, GFP_KERNEL); if (!dmabuf->virt) { kfree(dmabuf); return -ENOMEM; @@ -6300,10 +6300,9 @@ lpfc_sli4_ras_dma_alloc(struct lpfc_hba *phba, goto free_mem; } - dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev, + dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, LPFC_RAS_MAX_ENTRY_SIZE, - &dmabuf->phys, - GFP_KERNEL); + &dmabuf->phys, GFP_KERNEL); if (!dmabuf->virt) { kfree(dmabuf); rc = -ENOMEM; @@ -9408,6 +9407,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, cmnd = CMD_XMIT_SEQUENCE64_CR; if (phba->link_flag & LS_LOOPBACK_MODE) bf_set(wqe_xo, &wqe->xmit_sequence.wge_ctl, 1); + /* fall through */ case CMD_XMIT_SEQUENCE64_CR: /* word3 iocb=io_tag32 wqe=reserved */ wqe->xmit_sequence.rsvd3 = 0; @@ -13529,6 +13529,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe) case FC_STATUS_RQ_BUF_LEN_EXCEEDED: lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "2537 Receive Frame Truncated!!\n"); + /* fall through */ case FC_STATUS_RQ_SUCCESS: spin_lock_irqsave(&phba->hbalock, iflags); lpfc_sli4_rq_release(hrq, drq); @@ -13938,7 +13939,7 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, case FC_STATUS_RQ_BUF_LEN_EXCEEDED: lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "6126 Receive Frame Truncated!!\n"); - /* Drop thru */ + /* fall through */ case FC_STATUS_RQ_SUCCESS: spin_lock_irqsave(&phba->hbalock, iflags); lpfc_sli4_rq_release(hrq, drq); @@ -14613,9 +14614,9 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t page_size, dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); if (!dmabuf) goto out_fail; - dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev, - hw_page_size, &dmabuf->phys, - GFP_KERNEL); + dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, + hw_page_size, &dmabuf->phys, + GFP_KERNEL); if (!dmabuf->virt) { kfree(dmabuf); goto out_fail; @@ -14850,7 +14851,7 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax) eq->entry_count); if (eq->entry_count < 256) return -EINVAL; - /* otherwise default to smallest count (drop through) */ + /* fall through - otherwise default to smallest count */ case 256: bf_set(lpfc_eq_context_count, &eq_create->u.request.context, LPFC_EQ_CNT_256); @@ -14981,7 +14982,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, LPFC_CQ_CNT_WORD7); break; } - /* Fall Thru */ + /* fall through */ default: lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "0361 Unsupported CQ count: " @@ -14992,7 +14993,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, status = -EINVAL; goto out; } - /* otherwise default to smallest count (drop through) */ + /* fall through - otherwise default to smallest count */ case 256: bf_set(lpfc_cq_context_count, &cq_create->u.request.context, LPFC_CQ_CNT_256); @@ -15152,7 +15153,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, LPFC_CQ_CNT_WORD7); break; } - /* Fall Thru */ + /* fall through */ default: lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "3118 Bad CQ count. (%d)\n", @@ -15161,7 +15162,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, status = -EINVAL; goto out; } - /* otherwise default to smallest (drop thru) */ + /* fall through - otherwise default to smallest */ case 256: bf_set(lpfc_mbx_cq_create_set_cqe_cnt, &cq_set->u.request, LPFC_CQ_CNT_256); @@ -15433,7 +15434,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq, status = -EINVAL; goto out; } - /* otherwise default to smallest count (drop through) */ + /* fall through - otherwise default to smallest count */ case 16: bf_set(lpfc_mq_context_ring_size, &mq_create_ext->u.request.context, @@ -15852,7 +15853,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, status = -EINVAL; goto out; } - /* otherwise default to smallest count (drop through) */ + /* fall through - otherwise default to smallest count */ case 512: bf_set(lpfc_rq_context_rqe_count, &rq_create->u.request.context, @@ -15989,7 +15990,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, status = -EINVAL; goto out; } - /* otherwise default to smallest count (drop through) */ + /* fall through - otherwise default to smallest count */ case 512: bf_set(lpfc_rq_context_rqe_count, &rq_create->u.request.context, diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index e836392b75e8..f112458023ff 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -967,9 +967,10 @@ megaraid_alloc_cmd_packets(adapter_t *adapter) * Allocate the common 16-byte aligned memory for the handshake * mailbox. */ - raid_dev->una_mbox64 = dma_zalloc_coherent(&adapter->pdev->dev, - sizeof(mbox64_t), &raid_dev->una_mbox64_dma, - GFP_KERNEL); + raid_dev->una_mbox64 = dma_alloc_coherent(&adapter->pdev->dev, + sizeof(mbox64_t), + &raid_dev->una_mbox64_dma, + GFP_KERNEL); if (!raid_dev->una_mbox64) { con_log(CL_ANN, (KERN_WARNING @@ -995,8 +996,8 @@ megaraid_alloc_cmd_packets(adapter_t *adapter) align; // Allocate memory for commands issued internally - adapter->ibuf = dma_zalloc_coherent(&pdev->dev, MBOX_IBUF_SIZE, - &adapter->ibuf_dma_h, GFP_KERNEL); + adapter->ibuf = dma_alloc_coherent(&pdev->dev, MBOX_IBUF_SIZE, + &adapter->ibuf_dma_h, GFP_KERNEL); if (!adapter->ibuf) { con_log(CL_ANN, (KERN_WARNING @@ -2897,8 +2898,8 @@ megaraid_mbox_product_info(adapter_t *adapter) * Issue an ENQUIRY3 command to find out certain adapter parameters, * e.g., max channels, max commands etc. */ - pinfo = dma_zalloc_coherent(&adapter->pdev->dev, sizeof(mraid_pinfo_t), - &pinfo_dma_h, GFP_KERNEL); + pinfo = dma_alloc_coherent(&adapter->pdev->dev, sizeof(mraid_pinfo_t), + &pinfo_dma_h, GFP_KERNEL); if (pinfo == NULL) { con_log(CL_ANN, (KERN_WARNING "megaraid: out of memory, %s %d\n", __func__, diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index f7bdd783360a..fcbff83c0097 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -2273,9 +2273,9 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance, sizeof(struct MR_LD_VF_AFFILIATION_111)); else { new_affiliation_111 = - dma_zalloc_coherent(&instance->pdev->dev, - sizeof(struct MR_LD_VF_AFFILIATION_111), - &new_affiliation_111_h, GFP_KERNEL); + dma_alloc_coherent(&instance->pdev->dev, + sizeof(struct MR_LD_VF_AFFILIATION_111), + &new_affiliation_111_h, GFP_KERNEL); if (!new_affiliation_111) { dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate " "memory for new affiliation for scsi%d\n", @@ -2380,10 +2380,9 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance, sizeof(struct MR_LD_VF_AFFILIATION)); else { new_affiliation = - dma_zalloc_coherent(&instance->pdev->dev, - (MAX_LOGICAL_DRIVES + 1) * - sizeof(struct MR_LD_VF_AFFILIATION), - &new_affiliation_h, GFP_KERNEL); + dma_alloc_coherent(&instance->pdev->dev, + (MAX_LOGICAL_DRIVES + 1) * sizeof(struct MR_LD_VF_AFFILIATION), + &new_affiliation_h, GFP_KERNEL); if (!new_affiliation) { dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate " "memory for new affiliation for scsi%d\n", @@ -2546,9 +2545,10 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance, if (initial) { instance->hb_host_mem = - dma_zalloc_coherent(&instance->pdev->dev, - sizeof(struct MR_CTRL_HB_HOST_MEM), - &instance->hb_host_mem_h, GFP_KERNEL); + dma_alloc_coherent(&instance->pdev->dev, + sizeof(struct MR_CTRL_HB_HOST_MEM), + &instance->hb_host_mem_h, + GFP_KERNEL); if (!instance->hb_host_mem) { dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate" " memory for heartbeat host memory for scsi%d\n", @@ -5816,9 +5816,9 @@ megasas_get_seq_num(struct megasas_instance *instance, } dcmd = &cmd->frame->dcmd; - el_info = dma_zalloc_coherent(&instance->pdev->dev, - sizeof(struct megasas_evt_log_info), &el_info_h, - GFP_KERNEL); + el_info = dma_alloc_coherent(&instance->pdev->dev, + sizeof(struct megasas_evt_log_info), + &el_info_h, GFP_KERNEL); if (!el_info) { megasas_return_cmd(instance, cmd); return -ENOMEM; @@ -6236,7 +6236,7 @@ megasas_set_dma_mask(struct megasas_instance *instance) instance->consistent_mask_64bit = true; dev_info(&pdev->dev, "%s bit DMA mask and %s bit consistent mask\n", - ((*pdev->dev.dma_mask == DMA_BIT_MASK(64)) ? "63" : "32"), + ((*pdev->dev.dma_mask == DMA_BIT_MASK(63)) ? "63" : "32"), (instance->consistent_mask_64bit ? "63" : "32")); return 0; diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 211c17c33aa0..647f48a28f85 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -175,7 +175,8 @@ megasas_clear_intr_fusion(struct megasas_instance *instance) /* * Check if it is our interrupt */ - status = readl(®s->outbound_intr_status); + status = megasas_readl(instance, + ®s->outbound_intr_status); if (status & 1) { writel(status, ®s->outbound_intr_status); @@ -689,8 +690,9 @@ megasas_alloc_rdpq_fusion(struct megasas_instance *instance) array_size = sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) * MAX_MSIX_QUEUES_FUSION; - fusion->rdpq_virt = dma_zalloc_coherent(&instance->pdev->dev, - array_size, &fusion->rdpq_phys, GFP_KERNEL); + fusion->rdpq_virt = dma_alloc_coherent(&instance->pdev->dev, + array_size, &fusion->rdpq_phys, + GFP_KERNEL); if (!fusion->rdpq_virt) { dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index f3e182eb0970..c9dc7740e9e7 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -1915,8 +1915,9 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match) /* We use the PCI APIs for now until the generic one gets fixed * enough or until we get some macio-specific versions */ - dma_cmd_space = dma_zalloc_coherent(&macio_get_pci_dev(mdev)->dev, - ms->dma_cmd_size, &dma_cmd_bus, GFP_KERNEL); + dma_cmd_space = dma_alloc_coherent(&macio_get_pci_dev(mdev)->dev, + ms->dma_cmd_size, &dma_cmd_bus, + GFP_KERNEL); if (dma_cmd_space == NULL) { printk(KERN_ERR "mesh: can't allocate DMA table\n"); goto out_unmap; diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c index dbe753fba486..36f64205ecfa 100644 --- a/drivers/scsi/mvumi.c +++ b/drivers/scsi/mvumi.c @@ -143,8 +143,9 @@ static struct mvumi_res *mvumi_alloc_mem_resource(struct mvumi_hba *mhba, case RESOURCE_UNCACHED_MEMORY: size = round_up(size, 8); - res->virt_addr = dma_zalloc_coherent(&mhba->pdev->dev, size, - &res->bus_addr, GFP_KERNEL); + res->virt_addr = dma_alloc_coherent(&mhba->pdev->dev, size, + &res->bus_addr, + GFP_KERNEL); if (!res->virt_addr) { dev_err(&mhba->pdev->dev, "unable to allocate consistent mem," @@ -246,8 +247,8 @@ static int mvumi_internal_cmd_sgl(struct mvumi_hba *mhba, struct mvumi_cmd *cmd, if (size == 0) return 0; - virt_addr = dma_zalloc_coherent(&mhba->pdev->dev, size, &phy_addr, - GFP_KERNEL); + virt_addr = dma_alloc_coherent(&mhba->pdev->dev, size, &phy_addr, + GFP_KERNEL); if (!virt_addr) return -1; diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index b3be49d41375..084f2fcced0a 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -116,8 +116,8 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr, u64 align_offset = 0; if (align) align_offset = (dma_addr_t)align - 1; - mem_virt_alloc = dma_zalloc_coherent(&pdev->dev, mem_size + align, - &mem_dma_handle, GFP_KERNEL); + mem_virt_alloc = dma_alloc_coherent(&pdev->dev, mem_size + align, + &mem_dma_handle, GFP_KERNEL); if (!mem_virt_alloc) { pm8001_printk("memory allocation error\n"); return -1; @@ -657,7 +657,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev) if (dev->dev_type == SAS_SATA_DEV) { pm8001_device->attached_phy = dev->rphy->identify.phy_identifier; - flag = 1; /* directly sata*/ + flag = 1; /* directly sata */ } } /*register this device to HBA*/ PM8001_DISC_DBG(pm8001_ha, pm8001_printk("Found device\n")); diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index edcaf4b0cb0b..9bbc19fc190b 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -1050,16 +1050,17 @@ static int qedf_alloc_sq(struct qedf_ctx *qedf, struct qedf_rport *fcport) sizeof(void *); fcport->sq_pbl_size = fcport->sq_pbl_size + QEDF_PAGE_SIZE; - fcport->sq = dma_zalloc_coherent(&qedf->pdev->dev, - fcport->sq_mem_size, &fcport->sq_dma, GFP_KERNEL); + fcport->sq = dma_alloc_coherent(&qedf->pdev->dev, fcport->sq_mem_size, + &fcport->sq_dma, GFP_KERNEL); if (!fcport->sq) { QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate send queue.\n"); rval = 1; goto out; } - fcport->sq_pbl = dma_zalloc_coherent(&qedf->pdev->dev, - fcport->sq_pbl_size, &fcport->sq_pbl_dma, GFP_KERNEL); + fcport->sq_pbl = dma_alloc_coherent(&qedf->pdev->dev, + fcport->sq_pbl_size, + &fcport->sq_pbl_dma, GFP_KERNEL); if (!fcport->sq_pbl) { QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate send queue PBL.\n"); rval = 1; @@ -2680,8 +2681,10 @@ static int qedf_alloc_bdq(struct qedf_ctx *qedf) } /* Allocate list of PBL pages */ - qedf->bdq_pbl_list = dma_zalloc_coherent(&qedf->pdev->dev, - QEDF_PAGE_SIZE, &qedf->bdq_pbl_list_dma, GFP_KERNEL); + qedf->bdq_pbl_list = dma_alloc_coherent(&qedf->pdev->dev, + QEDF_PAGE_SIZE, + &qedf->bdq_pbl_list_dma, + GFP_KERNEL); if (!qedf->bdq_pbl_list) { QEDF_ERR(&(qedf->dbg_ctx), "Could not allocate list of PBL pages.\n"); return -ENOMEM; @@ -2770,9 +2773,10 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf) ALIGN(qedf->global_queues[i]->cq_pbl_size, QEDF_PAGE_SIZE); qedf->global_queues[i]->cq = - dma_zalloc_coherent(&qedf->pdev->dev, - qedf->global_queues[i]->cq_mem_size, - &qedf->global_queues[i]->cq_dma, GFP_KERNEL); + dma_alloc_coherent(&qedf->pdev->dev, + qedf->global_queues[i]->cq_mem_size, + &qedf->global_queues[i]->cq_dma, + GFP_KERNEL); if (!qedf->global_queues[i]->cq) { QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate cq.\n"); @@ -2781,9 +2785,10 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf) } qedf->global_queues[i]->cq_pbl = - dma_zalloc_coherent(&qedf->pdev->dev, - qedf->global_queues[i]->cq_pbl_size, - &qedf->global_queues[i]->cq_pbl_dma, GFP_KERNEL); + dma_alloc_coherent(&qedf->pdev->dev, + qedf->global_queues[i]->cq_pbl_size, + &qedf->global_queues[i]->cq_pbl_dma, + GFP_KERNEL); if (!qedf->global_queues[i]->cq_pbl) { QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate cq PBL.\n"); diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 4da660c1c431..6d6d6013e35b 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -953,6 +953,7 @@ static int qedi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) qedi_ep = ep->dd_data; if (qedi_ep->state == EP_STATE_IDLE || + qedi_ep->state == EP_STATE_OFLDCONN_NONE || qedi_ep->state == EP_STATE_OFLDCONN_FAILED) return -1; @@ -1035,6 +1036,7 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep) switch (qedi_ep->state) { case EP_STATE_OFLDCONN_START: + case EP_STATE_OFLDCONN_NONE: goto ep_release_conn; case EP_STATE_OFLDCONN_FAILED: break; @@ -1225,6 +1227,7 @@ static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data) if (!is_valid_ether_addr(&path_data->mac_addr[0])) { QEDI_NOTICE(&qedi->dbg_ctx, "dst mac NOT VALID\n"); + qedi_ep->state = EP_STATE_OFLDCONN_NONE; ret = -EIO; goto set_path_exit; } diff --git a/drivers/scsi/qedi/qedi_iscsi.h b/drivers/scsi/qedi/qedi_iscsi.h index 11260776212f..892d70d54553 100644 --- a/drivers/scsi/qedi/qedi_iscsi.h +++ b/drivers/scsi/qedi/qedi_iscsi.h @@ -59,6 +59,7 @@ enum { EP_STATE_OFLDCONN_FAILED = 0x2000, EP_STATE_CONNECT_FAILED = 0x4000, EP_STATE_DISCONN_TIMEDOUT = 0x8000, + EP_STATE_OFLDCONN_NONE = 0x10000, }; struct qedi_conn; diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 5c53409a8cea..e74a62448ba4 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -1394,10 +1394,9 @@ static int qedi_alloc_nvm_iscsi_cfg(struct qedi_ctx *qedi) { struct qedi_nvm_iscsi_image nvm_image; - qedi->iscsi_image = dma_zalloc_coherent(&qedi->pdev->dev, - sizeof(nvm_image), - &qedi->nvm_buf_dma, - GFP_KERNEL); + qedi->iscsi_image = dma_alloc_coherent(&qedi->pdev->dev, + sizeof(nvm_image), + &qedi->nvm_buf_dma, GFP_KERNEL); if (!qedi->iscsi_image) { QEDI_ERR(&qedi->dbg_ctx, "Could not allocate NVM BUF.\n"); return -ENOMEM; @@ -1510,10 +1509,10 @@ static int qedi_alloc_bdq(struct qedi_ctx *qedi) } /* Allocate list of PBL pages */ - qedi->bdq_pbl_list = dma_zalloc_coherent(&qedi->pdev->dev, - QEDI_PAGE_SIZE, - &qedi->bdq_pbl_list_dma, - GFP_KERNEL); + qedi->bdq_pbl_list = dma_alloc_coherent(&qedi->pdev->dev, + QEDI_PAGE_SIZE, + &qedi->bdq_pbl_list_dma, + GFP_KERNEL); if (!qedi->bdq_pbl_list) { QEDI_ERR(&qedi->dbg_ctx, "Could not allocate list of PBL pages.\n"); @@ -1609,10 +1608,10 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi) (qedi->global_queues[i]->cq_pbl_size + (QEDI_PAGE_SIZE - 1)); - qedi->global_queues[i]->cq = dma_zalloc_coherent(&qedi->pdev->dev, - qedi->global_queues[i]->cq_mem_size, - &qedi->global_queues[i]->cq_dma, - GFP_KERNEL); + qedi->global_queues[i]->cq = dma_alloc_coherent(&qedi->pdev->dev, + qedi->global_queues[i]->cq_mem_size, + &qedi->global_queues[i]->cq_dma, + GFP_KERNEL); if (!qedi->global_queues[i]->cq) { QEDI_WARN(&qedi->dbg_ctx, @@ -1620,10 +1619,10 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi) status = -ENOMEM; goto mem_alloc_failure; } - qedi->global_queues[i]->cq_pbl = dma_zalloc_coherent(&qedi->pdev->dev, - qedi->global_queues[i]->cq_pbl_size, - &qedi->global_queues[i]->cq_pbl_dma, - GFP_KERNEL); + qedi->global_queues[i]->cq_pbl = dma_alloc_coherent(&qedi->pdev->dev, + qedi->global_queues[i]->cq_pbl_size, + &qedi->global_queues[i]->cq_pbl_dma, + GFP_KERNEL); if (!qedi->global_queues[i]->cq_pbl) { QEDI_WARN(&qedi->dbg_ctx, @@ -1691,16 +1690,16 @@ int qedi_alloc_sq(struct qedi_ctx *qedi, struct qedi_endpoint *ep) ep->sq_pbl_size = (ep->sq_mem_size / QEDI_PAGE_SIZE) * sizeof(void *); ep->sq_pbl_size = ep->sq_pbl_size + QEDI_PAGE_SIZE; - ep->sq = dma_zalloc_coherent(&qedi->pdev->dev, ep->sq_mem_size, - &ep->sq_dma, GFP_KERNEL); + ep->sq = dma_alloc_coherent(&qedi->pdev->dev, ep->sq_mem_size, + &ep->sq_dma, GFP_KERNEL); if (!ep->sq) { QEDI_WARN(&qedi->dbg_ctx, "Could not allocate send queue.\n"); rval = -ENOMEM; goto out; } - ep->sq_pbl = dma_zalloc_coherent(&qedi->pdev->dev, ep->sq_pbl_size, - &ep->sq_pbl_dma, GFP_KERNEL); + ep->sq_pbl = dma_alloc_coherent(&qedi->pdev->dev, ep->sq_pbl_size, + &ep->sq_pbl_dma, GFP_KERNEL); if (!ep->sq_pbl) { QEDI_WARN(&qedi->dbg_ctx, "Could not allocate send queue PBL.\n"); diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index a414f51302b7..6856dfdfa473 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -4248,7 +4248,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->devnum = devnum; /* specifies microcode load address */ #ifdef QLA_64BIT_PTR - if (dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) { + if (dma_set_mask_and_coherent(&ha->pdev->dev, DMA_BIT_MASK(64))) { if (dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(32))) { printk(KERN_WARNING "scsi(%li): Unable to set a " "suitable DMA mask - aborting\n", ha->host_no); diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 00444dc79756..ac504a1ff0ff 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -2415,8 +2415,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) if (qla2x00_chip_is_down(vha)) goto done; - stats = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*stats), - &stats_dma, GFP_KERNEL); + stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma, + GFP_KERNEL); if (!stats) { ql_log(ql_log_warn, vha, 0x707d, "Failed to allocate memory for stats.\n"); diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 4a9fd8d944d6..17d42658ad9a 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -2312,8 +2312,8 @@ qla2x00_get_priv_stats(struct bsg_job *bsg_job) if (!IS_FWI2_CAPABLE(ha)) return -EPERM; - stats = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*stats), - &stats_dma, GFP_KERNEL); + stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma, + GFP_KERNEL); if (!stats) { ql_log(ql_log_warn, vha, 0x70e2, "Failed to allocate memory for stats.\n"); diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 26b93c563f92..d1fc4958222a 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -4394,6 +4394,8 @@ typedef struct scsi_qla_host { uint16_t n2n_id; struct list_head gpnid_list; struct fab_scan scan; + + unsigned int irq_offset; } scsi_qla_host_t; struct qla27xx_image_status { diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 90cfa394f942..cbc3bc49d4d1 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -4147,9 +4147,10 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) return rval; } - sp->u.iocb_cmd.u.ctarg.req = dma_zalloc_coherent( - &vha->hw->pdev->dev, sizeof(struct ct_sns_pkt), - &sp->u.iocb_cmd.u.ctarg.req_dma, GFP_KERNEL); + sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev, + sizeof(struct ct_sns_pkt), + &sp->u.iocb_cmd.u.ctarg.req_dma, + GFP_KERNEL); sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt); if (!sp->u.iocb_cmd.u.ctarg.req) { ql_log(ql_log_warn, vha, 0xffff, @@ -4165,9 +4166,10 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) ((vha->hw->max_fibre_devices - 1) * sizeof(struct ct_sns_gpn_ft_data)); - sp->u.iocb_cmd.u.ctarg.rsp = dma_zalloc_coherent( - &vha->hw->pdev->dev, rspsz, - &sp->u.iocb_cmd.u.ctarg.rsp_dma, GFP_KERNEL); + sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev, + rspsz, + &sp->u.iocb_cmd.u.ctarg.rsp_dma, + GFP_KERNEL); sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt); if (!sp->u.iocb_cmd.u.ctarg.rsp) { ql_log(ql_log_warn, vha, 0xffff, diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 364bb52ed2a6..8d1acc802a67 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1785,13 +1785,13 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, /* Issue Marker IOCB */ qla2x00_marker(vha, vha->hw->req_q_map[0], - vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun, + vha->hw->rsp_q_map[0], fcport->loop_id, lun, flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); } done_free_sp: sp->free(sp); - sp->fcport->flags &= ~FCF_ASYNC_SENT; + fcport->flags &= ~FCF_ASYNC_SENT; done: return rval; } @@ -3099,8 +3099,8 @@ qla2x00_alloc_offload_mem(scsi_qla_host_t *vha) FCE_SIZE, ha->fce, ha->fce_dma); /* Allocate memory for Fibre Channel Event Buffer. */ - tc = dma_zalloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, - GFP_KERNEL); + tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, + GFP_KERNEL); if (!tc) { ql_log(ql_log_warn, vha, 0x00be, "Unable to allocate (%d KB) for FCE.\n", @@ -3131,8 +3131,8 @@ try_eft: EFT_SIZE, ha->eft, ha->eft_dma); /* Allocate memory for Extended Trace Buffer. */ - tc = dma_zalloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, - GFP_KERNEL); + tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, + GFP_KERNEL); if (!tc) { ql_log(ql_log_warn, vha, 0x00c1, "Unable to allocate (%d KB) for EFT.\n", diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 30d3090842f8..8507c43b918c 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3446,6 +3446,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) "Adjusted Max no of queues pairs: %d.\n", ha->max_qpairs); } } + vha->irq_offset = desc.pre_vectors; ha->msix_entries = kcalloc(ha->msix_count, sizeof(struct qla_msix_entry), GFP_KERNEL); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index ea69dafc9774..c6ef83d0d99b 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -6939,7 +6939,7 @@ static int qla2xxx_map_queues(struct Scsi_Host *shost) if (USER_CTRL_IRQ(vha->hw)) rc = blk_mq_map_queues(qmap); else - rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, 0); + rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, vha->irq_offset); return rc; } diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 1ef74aa2d00a..2bf5e3e639e1 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -153,8 +153,8 @@ int qla4xxx_get_sys_info(struct scsi_qla_host *ha) dma_addr_t sys_info_dma; int status = QLA_ERROR; - sys_info = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*sys_info), - &sys_info_dma, GFP_KERNEL); + sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info), + &sys_info_dma, GFP_KERNEL); if (sys_info == NULL) { DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", ha->host_no, __func__)); diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 5d56904687b9..dac9a7013208 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -625,9 +625,9 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha) uint32_t mbox_sts[MBOX_REG_COUNT]; int status = QLA_ERROR; - init_fw_cb = dma_zalloc_coherent(&ha->pdev->dev, - sizeof(struct addr_ctrl_blk), - &init_fw_cb_dma, GFP_KERNEL); + init_fw_cb = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct addr_ctrl_blk), + &init_fw_cb_dma, GFP_KERNEL); if (init_fw_cb == NULL) { DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no, __func__)); @@ -709,9 +709,9 @@ int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha) uint32_t mbox_cmd[MBOX_REG_COUNT]; uint32_t mbox_sts[MBOX_REG_COUNT]; - init_fw_cb = dma_zalloc_coherent(&ha->pdev->dev, - sizeof(struct addr_ctrl_blk), - &init_fw_cb_dma, GFP_KERNEL); + init_fw_cb = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct addr_ctrl_blk), + &init_fw_cb_dma, GFP_KERNEL); if (init_fw_cb == NULL) { printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no, __func__); @@ -1340,9 +1340,9 @@ int qla4xxx_about_firmware(struct scsi_qla_host *ha) uint32_t mbox_sts[MBOX_REG_COUNT]; int status = QLA_ERROR; - about_fw = dma_zalloc_coherent(&ha->pdev->dev, - sizeof(struct about_fw_info), - &about_fw_dma, GFP_KERNEL); + about_fw = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct about_fw_info), + &about_fw_dma, GFP_KERNEL); if (!about_fw) { DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory " "for about_fw\n", __func__)); diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index d2b333d629be..5a31877c9d04 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -4052,8 +4052,8 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha) dma_addr_t sys_info_dma; int status = QLA_ERROR; - sys_info = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*sys_info), - &sys_info_dma, GFP_KERNEL); + sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info), + &sys_info_dma, GFP_KERNEL); if (sys_info == NULL) { DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", ha->host_no, __func__)); diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 949e186cc5d7..a77bfb224248 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -2704,9 +2704,9 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len) uint32_t rem = len; struct nlattr *attr; - init_fw_cb = dma_zalloc_coherent(&ha->pdev->dev, - sizeof(struct addr_ctrl_blk), - &init_fw_cb_dma, GFP_KERNEL); + init_fw_cb = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct addr_ctrl_blk), + &init_fw_cb_dma, GFP_KERNEL); if (!init_fw_cb) { ql4_printk(KERN_ERR, ha, "%s: Unable to alloc init_cb\n", __func__); @@ -4206,8 +4206,8 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha) sizeof(struct shadow_regs) + MEM_ALIGN_VALUE + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); - ha->queues = dma_zalloc_coherent(&ha->pdev->dev, ha->queues_len, - &ha->queues_dma, GFP_KERNEL); + ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len, + &ha->queues_dma, GFP_KERNEL); if (ha->queues == NULL) { ql4_printk(KERN_WARNING, ha, "Memory Allocation failed - queues.\n"); @@ -7232,6 +7232,8 @@ static int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha, rc = qla4xxx_copy_from_fwddb_param(fnode_sess, fnode_conn, fw_ddb_entry); + if (rc) + goto free_sess; ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n", __func__, fnode_sess->dev.kobj.name); diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 661512bec3ac..e27f4df24021 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -62,7 +62,7 @@ /* make sure inq_product_rev string corresponds to this version */ #define SDEBUG_VERSION "0188" /* format to fit INQUIRY revision field */ -static const char *sdebug_version_date = "20180128"; +static const char *sdebug_version_date = "20190125"; #define MY_NAME "scsi_debug" @@ -735,7 +735,7 @@ static inline bool scsi_debug_lbp(void) (sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10); } -static void *fake_store(unsigned long long lba) +static void *lba2fake_store(unsigned long long lba) { lba = do_div(lba, sdebug_store_sectors); @@ -2514,8 +2514,8 @@ static int do_device_access(struct scsi_cmnd *scmd, u32 sg_skip, u64 lba, return ret; } -/* If fake_store(lba,num) compares equal to arr(num), then copy top half of - * arr into fake_store(lba,num) and return true. If comparison fails then +/* If lba2fake_store(lba,num) compares equal to arr(num), then copy top half of + * arr into lba2fake_store(lba,num) and return true. If comparison fails then * return false. */ static bool comp_write_worker(u64 lba, u32 num, const u8 *arr) { @@ -2643,7 +2643,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, if (sdt->app_tag == cpu_to_be16(0xffff)) continue; - ret = dif_verify(sdt, fake_store(sector), sector, ei_lba); + ret = dif_verify(sdt, lba2fake_store(sector), sector, ei_lba); if (ret) { dif_errors++; return ret; @@ -3261,10 +3261,12 @@ err_out: static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba, bool unmap, bool ndob) { + int ret; unsigned long iflags; unsigned long long i; - int ret; - u64 lba_off; + u32 lb_size = sdebug_sector_size; + u64 block, lbaa; + u8 *fs1p; ret = check_device_access_params(scp, lba, num); if (ret) @@ -3276,31 +3278,30 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, unmap_region(lba, num); goto out; } - - lba_off = lba * sdebug_sector_size; + lbaa = lba; + block = do_div(lbaa, sdebug_store_sectors); /* if ndob then zero 1 logical block, else fetch 1 logical block */ + fs1p = fake_storep + (block * lb_size); if (ndob) { - memset(fake_storep + lba_off, 0, sdebug_sector_size); + memset(fs1p, 0, lb_size); ret = 0; } else - ret = fetch_to_dev_buffer(scp, fake_storep + lba_off, - sdebug_sector_size); + ret = fetch_to_dev_buffer(scp, fs1p, lb_size); if (-1 == ret) { write_unlock_irqrestore(&atomic_rw, iflags); return DID_ERROR << 16; - } else if (sdebug_verbose && !ndob && (ret < sdebug_sector_size)) + } else if (sdebug_verbose && !ndob && (ret < lb_size)) sdev_printk(KERN_INFO, scp->device, "%s: %s: lb size=%u, IO sent=%d bytes\n", - my_name, "write same", - sdebug_sector_size, ret); + my_name, "write same", lb_size, ret); /* Copy first sector to remaining blocks */ - for (i = 1 ; i < num ; i++) - memcpy(fake_storep + ((lba + i) * sdebug_sector_size), - fake_storep + lba_off, - sdebug_sector_size); - + for (i = 1 ; i < num ; i++) { + lbaa = lba + i; + block = do_div(lbaa, sdebug_store_sectors); + memmove(fake_storep + (block * lb_size), fs1p, lb_size); + } if (scsi_debug_lbp()) map_region(lba, num); out: diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b13cc9288ba0..a6828391d6b3 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -655,6 +655,7 @@ static blk_status_t scsi_result_to_blk_status(struct scsi_cmnd *cmd, int result) set_host_byte(cmd, DID_OK); return BLK_STS_TARGET; case DID_NEXUS_FAILURE: + set_host_byte(cmd, DID_OK); return BLK_STS_NEXUS; case DID_ALLOC_FAILURE: set_host_byte(cmd, DID_OK); @@ -1842,8 +1843,8 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q) blk_queue_segment_boundary(q, shost->dma_boundary); dma_set_seg_boundary(dev, shost->dma_boundary); - blk_queue_max_segment_size(q, - min(shost->max_segment_size, dma_get_max_seg_size(dev))); + blk_queue_max_segment_size(q, shost->max_segment_size); + dma_set_max_seg_size(dev, shost->max_segment_size); /* * Set a reasonable default alignment: The larger of 32-byte (dword), @@ -2597,7 +2598,6 @@ void scsi_device_resume(struct scsi_device *sdev) * device deleted during suspend) */ mutex_lock(&sdev->state_mutex); - WARN_ON_ONCE(!sdev->quiesced_by); sdev->quiesced_by = NULL; blk_clear_pm_only(sdev->request_queue); if (sdev->sdev_state == SDEV_QUIESCE) diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index a2b4179bfdf7..7639df91b110 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c @@ -80,8 +80,22 @@ static int scsi_dev_type_resume(struct device *dev, if (err == 0) { pm_runtime_disable(dev); - pm_runtime_set_active(dev); + err = pm_runtime_set_active(dev); pm_runtime_enable(dev); + + /* + * Forcibly set runtime PM status of request queue to "active" + * to make sure we can again get requests from the queue + * (see also blk_pm_peek_request()). + * + * The resume hook will correct runtime PM status of the disk. + */ + if (!err && scsi_is_sdev_device(dev)) { + struct scsi_device *sdev = to_scsi_device(dev); + + if (sdev->request_queue->dev) + blk_set_runtime_active(sdev->request_queue); + } } return err; @@ -140,16 +154,6 @@ static int scsi_bus_resume_common(struct device *dev, else fn = NULL; - /* - * Forcibly set runtime PM status of request queue to "active" to - * make sure we can again get requests from the queue (see also - * blk_pm_peek_request()). - * - * The resume hook will correct runtime PM status of the disk. - */ - if (scsi_is_sdev_device(dev) && pm_runtime_suspended(dev)) - blk_set_runtime_active(to_scsi_device(dev)->request_queue); - if (fn) { async_schedule_domain(fn, dev, &scsi_sd_pm_domain); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a1a44f52e0e8..5464d467e23e 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -206,6 +206,12 @@ cache_type_store(struct device *dev, struct device_attribute *attr, sp = buffer_data[0] & 0x80 ? 1 : 0; buffer_data[0] &= ~0x80; + /* + * Ensure WP, DPOFUA, and RESERVED fields are cleared in + * received mode parameter buffer before doing MODE SELECT. + */ + data.device_specific = 0; + if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT, SD_MAX_RETRIES, &data, &sshdr)) { if (scsi_sense_valid(&sshdr)) @@ -2945,9 +2951,6 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) if (rot == 1) { blk_queue_flag_set(QUEUE_FLAG_NONROT, q); blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q); - } else { - blk_queue_flag_clear(QUEUE_FLAG_NONROT, q); - blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q); } if (sdkp->device->type == TYPE_ZBC) { @@ -3084,6 +3087,15 @@ static int sd_revalidate_disk(struct gendisk *disk) if (sdkp->media_present) { sd_read_capacity(sdkp, buffer); + /* + * set the default to rotational. All non-rotational devices + * support the block characteristics VPD page, which will + * cause this to be updated correctly and any device which + * doesn't support it should be treated as rotational. + */ + blk_queue_flag_clear(QUEUE_FLAG_NONROT, q); + blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q); + if (scsi_device_supports_vpd(sdp)) { sd_read_block_provisioning(sdkp); sd_read_block_limits(sdkp); diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index 83365b29a4d8..a340af797a85 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -142,10 +142,12 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector, return -EOPNOTSUPP; /* - * Get a reply buffer for the number of requested zones plus a header. - * For ATA, buffers must be aligned to 512B. + * Get a reply buffer for the number of requested zones plus a header, + * without exceeding the device maximum command size. For ATA disks, + * buffers must be aligned to 512B. */ - buflen = roundup((nrz + 1) * 64, 512); + buflen = min(queue_max_hw_sectors(disk->queue) << 9, + roundup((nrz + 1) * 64, 512)); buf = kmalloc(buflen, gfp_mask); if (!buf) return -ENOMEM; @@ -462,12 +464,16 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf) sdkp->device->use_10_for_rw = 0; /* - * If something changed, revalidate the disk zone bitmaps once we have - * the capacity, that is on the second revalidate execution during disk - * scan and always during normal revalidate. + * Revalidate the disk zone bitmaps once the block device capacity is + * set on the second revalidate execution during disk scan and if + * something changed when executing a normal revalidate. */ - if (sdkp->first_scan) + if (sdkp->first_scan) { + sdkp->zone_blocks = zone_blocks; + sdkp->nr_zones = nr_zones; return 0; + } + if (sdkp->zone_blocks != zone_blocks || sdkp->nr_zones != nr_zones || disk->queue->nr_zones != nr_zones) { diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index e2fa3f476227..f564af8949e8 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -323,7 +323,7 @@ static inline void pqi_device_remove_start(struct pqi_scsi_dev *device) static inline bool pqi_device_in_remove(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device) { - return device->in_remove & !ctrl_info->in_shutdown; + return device->in_remove && !ctrl_info->in_shutdown; } static inline void pqi_schedule_rescan_worker_with_delay( @@ -3576,9 +3576,9 @@ static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info) alloc_length += PQI_EXTRA_SGL_MEMORY; ctrl_info->queue_memory_base = - dma_zalloc_coherent(&ctrl_info->pci_dev->dev, - alloc_length, - &ctrl_info->queue_memory_base_dma_handle, GFP_KERNEL); + dma_alloc_coherent(&ctrl_info->pci_dev->dev, alloc_length, + &ctrl_info->queue_memory_base_dma_handle, + GFP_KERNEL); if (!ctrl_info->queue_memory_base) return -ENOMEM; @@ -3715,10 +3715,9 @@ static int pqi_alloc_admin_queues(struct pqi_ctrl_info *ctrl_info) PQI_QUEUE_ELEMENT_ARRAY_ALIGNMENT; ctrl_info->admin_queue_memory_base = - dma_zalloc_coherent(&ctrl_info->pci_dev->dev, - alloc_length, - &ctrl_info->admin_queue_memory_base_dma_handle, - GFP_KERNEL); + dma_alloc_coherent(&ctrl_info->pci_dev->dev, alloc_length, + &ctrl_info->admin_queue_memory_base_dma_handle, + GFP_KERNEL); if (!ctrl_info->admin_queue_memory_base) return -ENOMEM; @@ -4602,9 +4601,10 @@ static void pqi_free_all_io_requests(struct pqi_ctrl_info *ctrl_info) static inline int pqi_alloc_error_buffer(struct pqi_ctrl_info *ctrl_info) { - ctrl_info->error_buffer = dma_zalloc_coherent(&ctrl_info->pci_dev->dev, - ctrl_info->error_buffer_length, - &ctrl_info->error_buffer_dma_handle, GFP_KERNEL); + ctrl_info->error_buffer = dma_alloc_coherent(&ctrl_info->pci_dev->dev, + ctrl_info->error_buffer_length, + &ctrl_info->error_buffer_dma_handle, + GFP_KERNEL); if (!ctrl_info->error_buffer) return -ENOMEM; @@ -7487,8 +7487,8 @@ static int pqi_ofa_alloc_mem(struct pqi_ctrl_info *ctrl_info, dma_addr_t dma_handle; ctrl_info->pqi_ofa_chunk_virt_addr[i] = - dma_zalloc_coherent(dev, chunk_size, &dma_handle, - GFP_KERNEL); + dma_alloc_coherent(dev, chunk_size, &dma_handle, + GFP_KERNEL); if (!ctrl_info->pqi_ofa_chunk_virt_addr[i]) break; @@ -7545,10 +7545,10 @@ static void pqi_ofa_setup_host_buffer(struct pqi_ctrl_info *ctrl_info, struct device *dev; dev = &ctrl_info->pci_dev->dev; - pqi_ofa_memory = dma_zalloc_coherent(dev, - PQI_OFA_MEMORY_DESCRIPTOR_LENGTH, - &ctrl_info->pqi_ofa_mem_dma_handle, - GFP_KERNEL); + pqi_ofa_memory = dma_alloc_coherent(dev, + PQI_OFA_MEMORY_DESCRIPTOR_LENGTH, + &ctrl_info->pqi_ofa_mem_dma_handle, + GFP_KERNEL); if (!pqi_ofa_memory) return; diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index dd65fea07687..6d176815e6ce 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -195,7 +195,7 @@ enum ufs_desc_def_size { QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90, QUERY_DESC_UNIT_DEF_SIZE = 0x23, QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06, - QUERY_DESC_GEOMETRY_DEF_SIZE = 0x44, + QUERY_DESC_GEOMETRY_DEF_SIZE = 0x48, QUERY_DESC_POWER_DEF_SIZE = 0x62, QUERY_DESC_HEALTH_DEF_SIZE = 0x25, }; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9ba7671b84f8..2ddf24466a62 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -108,13 +108,19 @@ int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len, const char *prefix) { - u8 *regs; + u32 *regs; + size_t pos; + + if (offset % 4 != 0 || len % 4 != 0) /* keep readl happy */ + return -EINVAL; regs = kzalloc(len, GFP_KERNEL); if (!regs) return -ENOMEM; - memcpy_fromio(regs, hba->mmio_base + offset, len); + for (pos = 0; pos < len; pos += 4) + regs[pos / 4] = ufshcd_readl(hba, offset + pos); + ufshcd_hex_dump(prefix, regs, len); kfree(regs); @@ -8001,6 +8007,8 @@ out: trace_ufshcd_system_resume(dev_name(hba->dev), ret, ktime_to_us(ktime_sub(ktime_get(), start)), hba->curr_dev_pwr_mode, hba->uic_link_state); + if (!ret) + hba->is_sys_suspended = false; return ret; } EXPORT_SYMBOL(ufshcd_system_resume); diff --git a/drivers/soc/fsl/qbman/dpaa_sys.c b/drivers/soc/fsl/qbman/dpaa_sys.c index 9436aa83ff1b..e6d48dccb8d5 100644 --- a/drivers/soc/fsl/qbman/dpaa_sys.c +++ b/drivers/soc/fsl/qbman/dpaa_sys.c @@ -62,7 +62,7 @@ int qbman_init_private_mem(struct device *dev, int idx, dma_addr_t *addr, return -ENODEV; } - if (!dma_zalloc_coherent(dev, *size, addr, 0)) { + if (!dma_alloc_coherent(dev, *size, addr, 0)) { dev_err(dev, "DMA Alloc memory failed\n"); return -ENODEV; } diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c index 52c153cd795a..636f83f781f5 100644 --- a/drivers/soc/fsl/qbman/qman.c +++ b/drivers/soc/fsl/qbman/qman.c @@ -1143,18 +1143,19 @@ static void qm_mr_process_task(struct work_struct *work); static irqreturn_t portal_isr(int irq, void *ptr) { struct qman_portal *p = ptr; - - u32 clear = QM_DQAVAIL_MASK | p->irq_sources; u32 is = qm_in(&p->p, QM_REG_ISR) & p->irq_sources; + u32 clear = 0; if (unlikely(!is)) return IRQ_NONE; /* DQRR-handling if it's interrupt-driven */ - if (is & QM_PIRQ_DQRI) + if (is & QM_PIRQ_DQRI) { __poll_portal_fast(p, QMAN_POLL_LIMIT); + clear = QM_DQAVAIL_MASK | QM_PIRQ_DQRI; + } /* Handling of anything else that's interrupt-driven */ - clear |= __poll_portal_slow(p, is); + clear |= __poll_portal_slow(p, is) & QM_PIRQ_SLOW; qm_out(&p->p, QM_REG_ISR, clear); return IRQ_HANDLED; } diff --git a/drivers/soc/fsl/qe/qe_tdm.c b/drivers/soc/fsl/qe/qe_tdm.c index f78c34647ca2..76480df195a8 100644 --- a/drivers/soc/fsl/qe/qe_tdm.c +++ b/drivers/soc/fsl/qe/qe_tdm.c @@ -44,10 +44,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm, const char *sprop; int ret = 0; u32 val; - struct resource *res; - struct device_node *np2; - static int siram_init_flag; - struct platform_device *pdev; sprop = of_get_property(np, "fsl,rx-sync-clock", NULL); if (sprop) { @@ -124,57 +120,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm, utdm->siram_entry_id = val; set_si_param(utdm, ut_info); - - np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-si"); - if (!np2) - return -EINVAL; - - pdev = of_find_device_by_node(np2); - if (!pdev) { - pr_err("%pOFn: failed to lookup pdev\n", np2); - of_node_put(np2); - return -EINVAL; - } - - of_node_put(np2); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - utdm->si_regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(utdm->si_regs)) { - ret = PTR_ERR(utdm->si_regs); - goto err_miss_siram_property; - } - - np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-siram"); - if (!np2) { - ret = -EINVAL; - goto err_miss_siram_property; - } - - pdev = of_find_device_by_node(np2); - if (!pdev) { - ret = -EINVAL; - pr_err("%pOFn: failed to lookup pdev\n", np2); - of_node_put(np2); - goto err_miss_siram_property; - } - - of_node_put(np2); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - utdm->siram = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(utdm->siram)) { - ret = PTR_ERR(utdm->siram); - goto err_miss_siram_property; - } - - if (siram_init_flag == 0) { - memset_io(utdm->siram, 0, resource_size(res)); - siram_init_flag = 1; - } - - return ret; - -err_miss_siram_property: - devm_iounmap(&pdev->dev, utdm->si_regs); return ret; } EXPORT_SYMBOL(ucc_of_parse_tdm); diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 4d8012e1205c..68bfca6f20dd 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -44,7 +44,7 @@ config ARCH_RZN1 bool select ARM_AMBA -if ARM +if ARM && ARCH_RENESAS #comment "Renesas ARM SoCs System Type" diff --git a/drivers/soc/renesas/r8a774c0-sysc.c b/drivers/soc/renesas/r8a774c0-sysc.c index e1ac4c0f6640..11050e17ea81 100644 --- a/drivers/soc/renesas/r8a774c0-sysc.c +++ b/drivers/soc/renesas/r8a774c0-sysc.c @@ -28,19 +28,6 @@ static struct rcar_sysc_area r8a774c0_areas[] __initdata = { { "3dg-b", 0x100, 1, R8A774C0_PD_3DG_B, R8A774C0_PD_3DG_A }, }; -static void __init rcar_sysc_fix_parent(struct rcar_sysc_area *areas, - unsigned int num_areas, u8 id, - int new_parent) -{ - unsigned int i; - - for (i = 0; i < num_areas; i++) - if (areas[i].isr_bit == id) { - areas[i].parent = new_parent; - return; - } -} - /* Fixups for RZ/G2E ES1.0 revision */ static const struct soc_device_attribute r8a774c0[] __initconst = { { .soc_id = "r8a774c0", .revision = "ES1.0" }, @@ -50,12 +37,10 @@ static const struct soc_device_attribute r8a774c0[] __initconst = { static int __init r8a774c0_sysc_init(void) { if (soc_device_match(r8a774c0)) { - rcar_sysc_fix_parent(r8a774c0_areas, - ARRAY_SIZE(r8a774c0_areas), - R8A774C0_PD_3DG_A, R8A774C0_PD_3DG_B); - rcar_sysc_fix_parent(r8a774c0_areas, - ARRAY_SIZE(r8a774c0_areas), - R8A774C0_PD_3DG_B, R8A774C0_PD_ALWAYS_ON); + /* Fix incorrect 3DG hierarchy */ + swap(r8a774c0_areas[6], r8a774c0_areas[7]); + r8a774c0_areas[6].parent = R8A774C0_PD_ALWAYS_ON; + r8a774c0_areas[7].parent = R8A774C0_PD_3DG_B; } return 0; diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 9f89cb134549..f761655e2a36 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -63,7 +63,7 @@ config SPI_ALTERA config SPI_ATH79 tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver" - depends on ATH79 && GPIOLIB + depends on ATH79 || COMPILE_TEST select SPI_BITBANG help This enables support for the SPI controller present on the @@ -268,6 +268,27 @@ config SPI_FSL_LPSPI help This enables Freescale i.MX LPSPI controllers in master mode. +config SPI_FSL_QUADSPI + tristate "Freescale QSPI controller" + depends on ARCH_MXC || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST + depends on HAS_IOMEM + help + This enables support for the Quad SPI controller in master mode. + Up to four flash chips can be connected on two buses with two + chipselects each. + This controller does not support generic SPI messages. It only + supports the high-level SPI memory interface. + +config SPI_NXP_FLEXSPI + tristate "NXP Flex SPI controller" + depends on ARCH_LAYERSCAPE || HAS_IOMEM + help + This enables support for the Flex SPI controller in master mode. + Up to four slave devices can be connected on two buses with two + chipselects each. + This controller does not support generic SPI messages and only + supports the high-level SPI memory interface. + config SPI_GPIO tristate "GPIO-based bitbanging SPI Master" depends on GPIOLIB || COMPILE_TEST @@ -296,8 +317,7 @@ config SPI_IMX depends on ARCH_MXC || COMPILE_TEST select SPI_BITBANG help - This enables using the Freescale i.MX SPI controllers in master - mode. + This enables support for the Freescale i.MX SPI controllers. config SPI_JCORE tristate "J-Core SPI Master" @@ -372,7 +392,7 @@ config SPI_FSL_DSPI depends on SOC_VF610 || SOC_LS1021A || ARCH_LAYERSCAPE || M5441x || COMPILE_TEST help This enables support for the Freescale DSPI controller in master - mode. VF610 platform uses the controller. + mode. VF610, LS1021A and ColdFire platforms uses the controller. config SPI_FSL_ESPI tristate "Freescale eSPI controller" @@ -631,6 +651,12 @@ config SPI_SH_HSPI help SPI driver for SuperH HSPI blocks. +config SPI_SIFIVE + tristate "SiFive SPI controller" + depends on HAS_IOMEM + help + This exposes the SPI controller IP from SiFive. + config SPI_SIRF tristate "CSR SiRFprimaII SPI controller" depends on SIRF_DMA @@ -665,7 +691,7 @@ config SPI_STM32 tristate "STMicroelectronics STM32 SPI controller" depends on ARCH_STM32 || COMPILE_TEST help - SPI driver for STMicroelectonics STM32 SoCs. + SPI driver for STMicroelectronics STM32 SoCs. STM32 SPI controller supports DMA and PIO modes. When DMA is not available, the driver automatically falls back to diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index f29627040dfb..d8fc03c9faa2 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o obj-$(CONFIG_SPI_FSL_LPSPI) += spi-fsl-lpspi.o +obj-$(CONFIG_SPI_FSL_QUADSPI) += spi-fsl-qspi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_GPIO) += spi-gpio.o obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o @@ -63,6 +64,7 @@ obj-$(CONFIG_SPI_MXIC) += spi-mxic.o obj-$(CONFIG_SPI_MXS) += spi-mxs.o obj-$(CONFIG_SPI_NPCM_PSPI) += spi-npcm-pspi.o obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o +obj-$(CONFIG_SPI_NXP_FLEXSPI) += spi-nxp-fspi.o obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o spi-octeon-objs := spi-cavium.o spi-cavium-octeon.o obj-$(CONFIG_SPI_OCTEON) += spi-octeon.o @@ -93,6 +95,7 @@ obj-$(CONFIG_SPI_SH) += spi-sh.o obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o +obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o obj-$(CONFIG_SPI_SIRF) += spi-sirf.o obj-$(CONFIG_SPI_SLAVE_MT27XX) += spi-slave-mt27xx.o obj-$(CONFIG_SPI_SPRD) += spi-sprd.o diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index ddc712410812..fffc21cd5f79 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Driver for Atmel QSPI Controller * @@ -7,31 +8,19 @@ * Author: Cyrille Pitchen <cyrille.pitchen@atmel.com> * Author: Piotr Bugalski <bugalski.piotr@gmail.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. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - * * This driver is based on drivers/mtd/spi-nor/fsl-quadspi.c from Freescale. */ -#include <linux/kernel.h> #include <linux/clk.h> -#include <linux/module.h> -#include <linux/platform_device.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/interrupt.h> -#include <linux/of.h> - #include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/spi/spi-mem.h> /* QSPI register offsets */ @@ -47,7 +36,9 @@ #define QSPI_IAR 0x0030 /* Instruction Address Register */ #define QSPI_ICR 0x0034 /* Instruction Code Register */ +#define QSPI_WICR 0x0034 /* Write Instruction Code Register */ #define QSPI_IFR 0x0038 /* Instruction Frame Register */ +#define QSPI_RICR 0x003C /* Read Instruction Code Register */ #define QSPI_SMR 0x0040 /* Scrambling Mode Register */ #define QSPI_SKR 0x0044 /* Scrambling Key Register */ @@ -100,7 +91,7 @@ #define QSPI_SCR_DLYBS_MASK GENMASK(23, 16) #define QSPI_SCR_DLYBS(n) (((n) << 16) & QSPI_SCR_DLYBS_MASK) -/* Bitfields in QSPI_ICR (Instruction Code Register) */ +/* Bitfields in QSPI_ICR (Read/Write Instruction Code Register) */ #define QSPI_ICR_INST_MASK GENMASK(7, 0) #define QSPI_ICR_INST(inst) (((inst) << 0) & QSPI_ICR_INST_MASK) #define QSPI_ICR_OPT_MASK GENMASK(23, 16) @@ -125,14 +116,12 @@ #define QSPI_IFR_OPTL_4BIT (2 << 8) #define QSPI_IFR_OPTL_8BIT (3 << 8) #define QSPI_IFR_ADDRL BIT(10) -#define QSPI_IFR_TFRTYP_MASK GENMASK(13, 12) -#define QSPI_IFR_TFRTYP_TRSFR_READ (0 << 12) -#define QSPI_IFR_TFRTYP_TRSFR_READ_MEM (1 << 12) -#define QSPI_IFR_TFRTYP_TRSFR_WRITE (2 << 12) -#define QSPI_IFR_TFRTYP_TRSFR_WRITE_MEM (3 << 13) +#define QSPI_IFR_TFRTYP_MEM BIT(12) +#define QSPI_IFR_SAMA5D2_WRITE_TRSFR BIT(13) #define QSPI_IFR_CRM BIT(14) #define QSPI_IFR_NBDUM_MASK GENMASK(20, 16) #define QSPI_IFR_NBDUM(n) (((n) << 16) & QSPI_IFR_NBDUM_MASK) +#define QSPI_IFR_APBTFRTYP_READ BIT(24) /* Defined in SAM9X60 */ /* Bitfields in QSPI_SMR (Scrambling Mode Register) */ #define QSPI_SMR_SCREN BIT(0) @@ -148,24 +137,31 @@ #define QSPI_WPSR_WPVSRC_MASK GENMASK(15, 8) #define QSPI_WPSR_WPVSRC(src) (((src) << 8) & QSPI_WPSR_WPVSRC) +struct atmel_qspi_caps { + bool has_qspick; + bool has_ricr; +}; struct atmel_qspi { void __iomem *regs; void __iomem *mem; - struct clk *clk; + struct clk *pclk; + struct clk *qspick; struct platform_device *pdev; + const struct atmel_qspi_caps *caps; u32 pending; + u32 mr; struct completion cmd_completion; }; -struct qspi_mode { +struct atmel_qspi_mode { u8 cmd_buswidth; u8 addr_buswidth; u8 data_buswidth; u32 config; }; -static const struct qspi_mode sama5d2_qspi_modes[] = { +static const struct atmel_qspi_mode atmel_qspi_modes[] = { { 1, 1, 1, QSPI_IFR_WIDTH_SINGLE_BIT_SPI }, { 1, 1, 2, QSPI_IFR_WIDTH_DUAL_OUTPUT }, { 1, 1, 4, QSPI_IFR_WIDTH_QUAD_OUTPUT }, @@ -175,19 +171,8 @@ static const struct qspi_mode sama5d2_qspi_modes[] = { { 4, 4, 4, QSPI_IFR_WIDTH_QUAD_CMD }, }; -/* Register access functions */ -static inline u32 qspi_readl(struct atmel_qspi *aq, u32 reg) -{ - return readl_relaxed(aq->regs + reg); -} - -static inline void qspi_writel(struct atmel_qspi *aq, u32 reg, u32 value) -{ - writel_relaxed(value, aq->regs + reg); -} - -static inline bool is_compatible(const struct spi_mem_op *op, - const struct qspi_mode *mode) +static inline bool atmel_qspi_is_compatible(const struct spi_mem_op *op, + const struct atmel_qspi_mode *mode) { if (op->cmd.buswidth != mode->cmd_buswidth) return false; @@ -201,21 +186,21 @@ static inline bool is_compatible(const struct spi_mem_op *op, return true; } -static int find_mode(const struct spi_mem_op *op) +static int atmel_qspi_find_mode(const struct spi_mem_op *op) { u32 i; - for (i = 0; i < ARRAY_SIZE(sama5d2_qspi_modes); i++) - if (is_compatible(op, &sama5d2_qspi_modes[i])) + for (i = 0; i < ARRAY_SIZE(atmel_qspi_modes); i++) + if (atmel_qspi_is_compatible(op, &atmel_qspi_modes[i])) return i; - return -1; + return -ENOTSUPP; } static bool atmel_qspi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) { - if (find_mode(op) < 0) + if (atmel_qspi_find_mode(op) < 0) return false; /* special case not supported by hardware */ @@ -226,29 +211,37 @@ static bool atmel_qspi_supports_op(struct spi_mem *mem, return true; } -static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) +static int atmel_qspi_set_cfg(struct atmel_qspi *aq, + const struct spi_mem_op *op, u32 *offset) { - struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->master); - int mode; + u32 iar, icr, ifr; u32 dummy_cycles = 0; - u32 iar, icr, ifr, sr; - int err = 0; + int mode; iar = 0; icr = QSPI_ICR_INST(op->cmd.opcode); ifr = QSPI_IFR_INSTEN; - qspi_writel(aq, QSPI_MR, QSPI_MR_SMM); - - mode = find_mode(op); + mode = atmel_qspi_find_mode(op); if (mode < 0) - return -ENOTSUPP; - - ifr |= sama5d2_qspi_modes[mode].config; + return mode; + ifr |= atmel_qspi_modes[mode].config; if (op->dummy.buswidth && op->dummy.nbytes) dummy_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth; + /* + * The controller allows 24 and 32-bit addressing while NAND-flash + * requires 16-bit long. Handling 8-bit long addresses is done using + * the option field. For the 16-bit addresses, the workaround depends + * of the number of requested dummy bits. If there are 8 or more dummy + * cycles, the address is shifted and sent with the first dummy byte. + * Otherwise opcode is disabled and the first byte of the address + * contains the command opcode (works only if the opcode and address + * use the same buswidth). The limitation is when the 16-bit address is + * used without enough dummy cycles and the opcode is using a different + * buswidth than the address. + */ if (op->addr.buswidth) { switch (op->addr.nbytes) { case 0: @@ -282,6 +275,9 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) } } + /* offset of the data access in the QSPI memory space */ + *offset = iar; + /* Set number of dummy cycles */ if (dummy_cycles) ifr |= QSPI_IFR_NBDUM(dummy_cycles); @@ -290,49 +286,82 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) if (op->data.nbytes) ifr |= QSPI_IFR_DATAEN; - if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes) - ifr |= QSPI_IFR_TFRTYP_TRSFR_READ; - else - ifr |= QSPI_IFR_TFRTYP_TRSFR_WRITE; + /* + * If the QSPI controller is set in regular SPI mode, set it in + * Serial Memory Mode (SMM). + */ + if (aq->mr != QSPI_MR_SMM) { + writel_relaxed(QSPI_MR_SMM, aq->regs + QSPI_MR); + aq->mr = QSPI_MR_SMM; + } /* Clear pending interrupts */ - (void)qspi_readl(aq, QSPI_SR); + (void)readl_relaxed(aq->regs + QSPI_SR); + + if (aq->caps->has_ricr) { + if (!op->addr.nbytes && op->data.dir == SPI_MEM_DATA_IN) + ifr |= QSPI_IFR_APBTFRTYP_READ; - /* Set QSPI Instruction Frame registers */ - qspi_writel(aq, QSPI_IAR, iar); - qspi_writel(aq, QSPI_ICR, icr); - qspi_writel(aq, QSPI_IFR, ifr); + /* Set QSPI Instruction Frame registers */ + writel_relaxed(iar, aq->regs + QSPI_IAR); + if (op->data.dir == SPI_MEM_DATA_IN) + writel_relaxed(icr, aq->regs + QSPI_RICR); + else + writel_relaxed(icr, aq->regs + QSPI_WICR); + writel_relaxed(ifr, aq->regs + QSPI_IFR); + } else { + if (op->data.dir == SPI_MEM_DATA_OUT) + ifr |= QSPI_IFR_SAMA5D2_WRITE_TRSFR; + + /* Set QSPI Instruction Frame registers */ + writel_relaxed(iar, aq->regs + QSPI_IAR); + writel_relaxed(icr, aq->regs + QSPI_ICR); + writel_relaxed(ifr, aq->regs + QSPI_IFR); + } + + return 0; +} + +static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) +{ + struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->master); + u32 sr, offset; + int err; + + err = atmel_qspi_set_cfg(aq, op, &offset); + if (err) + return err; /* Skip to the final steps if there is no data */ if (op->data.nbytes) { /* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */ - (void)qspi_readl(aq, QSPI_IFR); + (void)readl_relaxed(aq->regs + QSPI_IFR); /* Send/Receive data */ if (op->data.dir == SPI_MEM_DATA_IN) - _memcpy_fromio(op->data.buf.in, - aq->mem + iar, op->data.nbytes); + _memcpy_fromio(op->data.buf.in, aq->mem + offset, + op->data.nbytes); else - _memcpy_toio(aq->mem + iar, - op->data.buf.out, op->data.nbytes); + _memcpy_toio(aq->mem + offset, op->data.buf.out, + op->data.nbytes); /* Release the chip-select */ - qspi_writel(aq, QSPI_CR, QSPI_CR_LASTXFER); + writel_relaxed(QSPI_CR_LASTXFER, aq->regs + QSPI_CR); } /* Poll INSTRuction End status */ - sr = qspi_readl(aq, QSPI_SR); + sr = readl_relaxed(aq->regs + QSPI_SR); if ((sr & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED) return err; /* Wait for INSTRuction End interrupt */ reinit_completion(&aq->cmd_completion); aq->pending = sr & QSPI_SR_CMD_COMPLETED; - qspi_writel(aq, QSPI_IER, QSPI_SR_CMD_COMPLETED); + writel_relaxed(QSPI_SR_CMD_COMPLETED, aq->regs + QSPI_IER); if (!wait_for_completion_timeout(&aq->cmd_completion, msecs_to_jiffies(1000))) err = -ETIMEDOUT; - qspi_writel(aq, QSPI_IDR, QSPI_SR_CMD_COMPLETED); + writel_relaxed(QSPI_SR_CMD_COMPLETED, aq->regs + QSPI_IDR); return err; } @@ -361,7 +390,7 @@ static int atmel_qspi_setup(struct spi_device *spi) if (!spi->max_speed_hz) return -EINVAL; - src_rate = clk_get_rate(aq->clk); + src_rate = clk_get_rate(aq->pclk); if (!src_rate) return -EINVAL; @@ -371,7 +400,7 @@ static int atmel_qspi_setup(struct spi_device *spi) scbr--; scr = QSPI_SCR_SCBR(scbr); - qspi_writel(aq, QSPI_SCR, scr); + writel_relaxed(scr, aq->regs + QSPI_SCR); return 0; } @@ -379,21 +408,25 @@ static int atmel_qspi_setup(struct spi_device *spi) static int atmel_qspi_init(struct atmel_qspi *aq) { /* Reset the QSPI controller */ - qspi_writel(aq, QSPI_CR, QSPI_CR_SWRST); + writel_relaxed(QSPI_CR_SWRST, aq->regs + QSPI_CR); + + /* Set the QSPI controller by default in Serial Memory Mode */ + writel_relaxed(QSPI_MR_SMM, aq->regs + QSPI_MR); + aq->mr = QSPI_MR_SMM; /* Enable the QSPI controller */ - qspi_writel(aq, QSPI_CR, QSPI_CR_QSPIEN); + writel_relaxed(QSPI_CR_QSPIEN, aq->regs + QSPI_CR); return 0; } static irqreturn_t atmel_qspi_interrupt(int irq, void *dev_id) { - struct atmel_qspi *aq = (struct atmel_qspi *)dev_id; + struct atmel_qspi *aq = dev_id; u32 status, mask, pending; - status = qspi_readl(aq, QSPI_SR); - mask = qspi_readl(aq, QSPI_IMR); + status = readl_relaxed(aq->regs + QSPI_SR); + mask = readl_relaxed(aq->regs + QSPI_IMR); pending = status & mask; if (!pending) @@ -449,44 +482,74 @@ static int atmel_qspi_probe(struct platform_device *pdev) } /* Get the peripheral clock */ - aq->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(aq->clk)) { + aq->pclk = devm_clk_get(&pdev->dev, "pclk"); + if (IS_ERR(aq->pclk)) + aq->pclk = devm_clk_get(&pdev->dev, NULL); + + if (IS_ERR(aq->pclk)) { dev_err(&pdev->dev, "missing peripheral clock\n"); - err = PTR_ERR(aq->clk); + err = PTR_ERR(aq->pclk); goto exit; } /* Enable the peripheral clock */ - err = clk_prepare_enable(aq->clk); + err = clk_prepare_enable(aq->pclk); if (err) { dev_err(&pdev->dev, "failed to enable the peripheral clock\n"); goto exit; } + aq->caps = of_device_get_match_data(&pdev->dev); + if (!aq->caps) { + dev_err(&pdev->dev, "Could not retrieve QSPI caps\n"); + err = -EINVAL; + goto exit; + } + + if (aq->caps->has_qspick) { + /* Get the QSPI system clock */ + aq->qspick = devm_clk_get(&pdev->dev, "qspick"); + if (IS_ERR(aq->qspick)) { + dev_err(&pdev->dev, "missing system clock\n"); + err = PTR_ERR(aq->qspick); + goto disable_pclk; + } + + /* Enable the QSPI system clock */ + err = clk_prepare_enable(aq->qspick); + if (err) { + dev_err(&pdev->dev, + "failed to enable the QSPI system clock\n"); + goto disable_pclk; + } + } + /* Request the IRQ */ irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "missing IRQ\n"); err = irq; - goto disable_clk; + goto disable_qspick; } err = devm_request_irq(&pdev->dev, irq, atmel_qspi_interrupt, 0, dev_name(&pdev->dev), aq); if (err) - goto disable_clk; + goto disable_qspick; err = atmel_qspi_init(aq); if (err) - goto disable_clk; + goto disable_qspick; err = spi_register_controller(ctrl); if (err) - goto disable_clk; + goto disable_qspick; return 0; -disable_clk: - clk_disable_unprepare(aq->clk); +disable_qspick: + clk_disable_unprepare(aq->qspick); +disable_pclk: + clk_disable_unprepare(aq->pclk); exit: spi_controller_put(ctrl); @@ -499,8 +562,9 @@ static int atmel_qspi_remove(struct platform_device *pdev) struct atmel_qspi *aq = spi_controller_get_devdata(ctrl); spi_unregister_controller(ctrl); - qspi_writel(aq, QSPI_CR, QSPI_CR_QSPIDIS); - clk_disable_unprepare(aq->clk); + writel_relaxed(QSPI_CR_QSPIDIS, aq->regs + QSPI_CR); + clk_disable_unprepare(aq->qspick); + clk_disable_unprepare(aq->pclk); return 0; } @@ -508,7 +572,8 @@ static int __maybe_unused atmel_qspi_suspend(struct device *dev) { struct atmel_qspi *aq = dev_get_drvdata(dev); - clk_disable_unprepare(aq->clk); + clk_disable_unprepare(aq->qspick); + clk_disable_unprepare(aq->pclk); return 0; } @@ -517,7 +582,8 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev) { struct atmel_qspi *aq = dev_get_drvdata(dev); - clk_prepare_enable(aq->clk); + clk_prepare_enable(aq->pclk); + clk_prepare_enable(aq->qspick); return atmel_qspi_init(aq); } @@ -525,8 +591,22 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(atmel_qspi_pm_ops, atmel_qspi_suspend, atmel_qspi_resume); +static const struct atmel_qspi_caps atmel_sama5d2_qspi_caps = {}; + +static const struct atmel_qspi_caps atmel_sam9x60_qspi_caps = { + .has_qspick = true, + .has_ricr = true, +}; + static const struct of_device_id atmel_qspi_dt_ids[] = { - { .compatible = "atmel,sama5d2-qspi" }, + { + .compatible = "atmel,sama5d2-qspi", + .data = &atmel_sama5d2_qspi_caps, + }, + { + .compatible = "microchip,sam9x60-qspi", + .data = &atmel_sam9x60_qspi_caps, + }, { /* sentinel */ } }; diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 3f6b657394de..847f354ebef1 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -21,18 +21,26 @@ #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> #include <linux/bitops.h> -#include <linux/gpio.h> #include <linux/clk.h> #include <linux/err.h> - -#include <asm/mach-ath79/ar71xx_regs.h> -#include <asm/mach-ath79/ath79_spi_platform.h> +#include <linux/platform_data/spi-ath79.h> #define DRV_NAME "ath79-spi" #define ATH79_SPI_RRW_DELAY_FACTOR 12000 #define MHZ (1000 * 1000) +#define AR71XX_SPI_REG_FS 0x00 /* Function Select */ +#define AR71XX_SPI_REG_CTRL 0x04 /* SPI Control */ +#define AR71XX_SPI_REG_IOC 0x08 /* SPI I/O Control */ +#define AR71XX_SPI_REG_RDS 0x0c /* Read Data Shift */ + +#define AR71XX_SPI_FS_GPIO BIT(0) /* Enable GPIO mode */ + +#define AR71XX_SPI_IOC_DO BIT(0) /* Data Out pin */ +#define AR71XX_SPI_IOC_CLK BIT(8) /* CLK pin */ +#define AR71XX_SPI_IOC_CS(n) BIT(16 + (n)) + struct ath79_spi { struct spi_bitbang bitbang; u32 ioc_base; @@ -67,31 +75,14 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active) { struct ath79_spi *sp = ath79_spidev_to_sp(spi); int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active; + u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); - if (is_active) { - /* set initial clock polarity */ - if (spi->mode & SPI_CPOL) - sp->ioc_base |= AR71XX_SPI_IOC_CLK; - else - sp->ioc_base &= ~AR71XX_SPI_IOC_CLK; - - ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); - } - - if (gpio_is_valid(spi->cs_gpio)) { - /* SPI is normally active-low */ - gpio_set_value_cansleep(spi->cs_gpio, cs_high); - } else { - u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); - - if (cs_high) - sp->ioc_base |= cs_bit; - else - sp->ioc_base &= ~cs_bit; - - ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); - } + if (cs_high) + sp->ioc_base |= cs_bit; + else + sp->ioc_base &= ~cs_bit; + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); } static void ath79_spi_enable(struct ath79_spi *sp) @@ -103,6 +94,9 @@ static void ath79_spi_enable(struct ath79_spi *sp) sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL); sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC); + /* clear clk and mosi in the base state */ + sp->ioc_base &= ~(AR71XX_SPI_IOC_DO | AR71XX_SPI_IOC_CLK); + /* TODO: setup speed? */ ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43); } @@ -115,66 +109,6 @@ static void ath79_spi_disable(struct ath79_spi *sp) ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); } -static int ath79_spi_setup_cs(struct spi_device *spi) -{ - struct ath79_spi *sp = ath79_spidev_to_sp(spi); - int status; - - status = 0; - if (gpio_is_valid(spi->cs_gpio)) { - unsigned long flags; - - flags = GPIOF_DIR_OUT; - if (spi->mode & SPI_CS_HIGH) - flags |= GPIOF_INIT_LOW; - else - flags |= GPIOF_INIT_HIGH; - - status = gpio_request_one(spi->cs_gpio, flags, - dev_name(&spi->dev)); - } else { - u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); - - if (spi->mode & SPI_CS_HIGH) - sp->ioc_base &= ~cs_bit; - else - sp->ioc_base |= cs_bit; - - ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); - } - - return status; -} - -static void ath79_spi_cleanup_cs(struct spi_device *spi) -{ - if (gpio_is_valid(spi->cs_gpio)) - gpio_free(spi->cs_gpio); -} - -static int ath79_spi_setup(struct spi_device *spi) -{ - int status = 0; - - if (!spi->controller_state) { - status = ath79_spi_setup_cs(spi); - if (status) - return status; - } - - status = spi_bitbang_setup(spi); - if (status && !spi->controller_state) - ath79_spi_cleanup_cs(spi); - - return status; -} - -static void ath79_spi_cleanup(struct spi_device *spi) -{ - ath79_spi_cleanup_cs(spi); - spi_bitbang_cleanup(spi); -} - static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs, u32 word, u8 bits, unsigned flags) { @@ -225,9 +159,10 @@ static int ath79_spi_probe(struct platform_device *pdev) pdata = dev_get_platdata(&pdev->dev); + master->use_gpio_descriptors = true; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); - master->setup = ath79_spi_setup; - master->cleanup = ath79_spi_cleanup; + master->setup = spi_bitbang_setup; + master->cleanup = spi_bitbang_cleanup; if (pdata) { master->bus_num = pdata->bus_num; master->num_chipselect = pdata->num_chipselect; @@ -236,7 +171,6 @@ static int ath79_spi_probe(struct platform_device *pdev) sp->bitbang.master = master; sp->bitbang.chipselect = ath79_spi_chipselect; sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0; - sp->bitbang.setup_transfer = spi_bitbang_setup_transfer; sp->bitbang.flags = SPI_CS_HIGH; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 74fddcd3282b..4954f0ab1606 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -23,8 +23,7 @@ #include <linux/of.h> #include <linux/io.h> -#include <linux/gpio.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> @@ -312,7 +311,7 @@ struct atmel_spi { /* Controller-specific per-slave state */ struct atmel_spi_device { - unsigned int npcs_pin; + struct gpio_desc *npcs_pin; u32 csr; }; @@ -355,7 +354,6 @@ static bool atmel_spi_is_v2(struct atmel_spi *as) static void cs_activate(struct atmel_spi *as, struct spi_device *spi) { struct atmel_spi_device *asd = spi->controller_state; - unsigned active = spi->mode & SPI_CS_HIGH; u32 mr; if (atmel_spi_is_v2(as)) { @@ -379,7 +377,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi) mr = spi_readl(as, MR); if (as->use_cs_gpios) - gpio_set_value(asd->npcs_pin, active); + gpiod_set_value(asd->npcs_pin, 1); } else { u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0; int i; @@ -396,19 +394,16 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi) mr = spi_readl(as, MR); mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr); if (as->use_cs_gpios && spi->chip_select != 0) - gpio_set_value(asd->npcs_pin, active); + gpiod_set_value(asd->npcs_pin, 1); spi_writel(as, MR, mr); } - dev_dbg(&spi->dev, "activate %u%s, mr %08x\n", - asd->npcs_pin, active ? " (high)" : "", - mr); + dev_dbg(&spi->dev, "activate NPCS, mr %08x\n", mr); } static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) { struct atmel_spi_device *asd = spi->controller_state; - unsigned active = spi->mode & SPI_CS_HIGH; u32 mr; /* only deactivate *this* device; sometimes transfers to @@ -420,14 +415,12 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) spi_writel(as, MR, mr); } - dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n", - asd->npcs_pin, active ? " (low)" : "", - mr); + dev_dbg(&spi->dev, "DEactivate NPCS, mr %08x\n", mr); if (!as->use_cs_gpios) spi_writel(as, CR, SPI_BIT(LASTXFER)); else if (atmel_spi_is_v2(as) || spi->chip_select != 0) - gpio_set_value(asd->npcs_pin, !active); + gpiod_set_value(asd->npcs_pin, 0); } static void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock) @@ -1188,7 +1181,6 @@ static int atmel_spi_setup(struct spi_device *spi) struct atmel_spi_device *asd; u32 csr; unsigned int bits = spi->bits_per_word; - unsigned int npcs_pin; as = spi_master_get_devdata(spi->master); @@ -1209,21 +1201,14 @@ static int atmel_spi_setup(struct spi_device *spi) csr |= SPI_BIT(CSAAT); /* DLYBS is mostly irrelevant since we manage chipselect using GPIOs. - * - * DLYBCT would add delays between words, slowing down transfers. - * It could potentially be useful to cope with DMA bottlenecks, but - * in those cases it's probably best to just use a lower bitrate. */ csr |= SPI_BF(DLYBS, 0); - csr |= SPI_BF(DLYBCT, 0); - - /* chipselect must have been muxed as GPIO (e.g. in board setup) */ - npcs_pin = (unsigned long)spi->controller_data; - if (!as->use_cs_gpios) - npcs_pin = spi->chip_select; - else if (gpio_is_valid(spi->cs_gpio)) - npcs_pin = spi->cs_gpio; + /* DLYBCT adds delays between words. This is useful for slow devices + * that need a bit of time to setup the next transfer. + */ + csr |= SPI_BF(DLYBCT, + (as->spi_clk / 1000000 * spi->word_delay_usecs) >> 5); asd = spi->controller_state; if (!asd) { @@ -1231,11 +1216,21 @@ static int atmel_spi_setup(struct spi_device *spi) if (!asd) return -ENOMEM; - if (as->use_cs_gpios) - gpio_direction_output(npcs_pin, - !(spi->mode & SPI_CS_HIGH)); + /* + * If use_cs_gpios is true this means that we have "cs-gpios" + * defined in the device tree node so we should have + * gotten the GPIO lines from the device tree inside the + * SPI core. Warn if this is not the case but continue since + * CS GPIOs are after all optional. + */ + if (as->use_cs_gpios) { + if (!spi->cs_gpiod) { + dev_err(&spi->dev, + "host claims to use CS GPIOs but no CS found in DT by the SPI core\n"); + } + asd->npcs_pin = spi->cs_gpiod; + } - asd->npcs_pin = npcs_pin; spi->controller_state = asd; } @@ -1473,41 +1468,6 @@ static void atmel_get_caps(struct atmel_spi *as) as->caps.has_pdc_support = version < 0x212; } -/*-------------------------------------------------------------------------*/ -static int atmel_spi_gpio_cs(struct platform_device *pdev) -{ - struct spi_master *master = platform_get_drvdata(pdev); - struct atmel_spi *as = spi_master_get_devdata(master); - struct device_node *np = master->dev.of_node; - int i; - int ret = 0; - int nb = 0; - - if (!as->use_cs_gpios) - return 0; - - if (!np) - return 0; - - nb = of_gpio_named_count(np, "cs-gpios"); - for (i = 0; i < nb; i++) { - int cs_gpio = of_get_named_gpio(pdev->dev.of_node, - "cs-gpios", i); - - if (cs_gpio == -EPROBE_DEFER) - return cs_gpio; - - if (gpio_is_valid(cs_gpio)) { - ret = devm_gpio_request(&pdev->dev, cs_gpio, - dev_name(&pdev->dev)); - if (ret) - return ret; - } - } - - return 0; -} - static void atmel_spi_init(struct atmel_spi *as) { spi_writel(as, CR, SPI_BIT(SWRST)); @@ -1560,6 +1520,7 @@ static int atmel_spi_probe(struct platform_device *pdev) goto out_free; /* the spi->mode bits understood by this driver: */ + master->use_gpio_descriptors = true; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16); master->dev.of_node = pdev->dev.of_node; @@ -1592,6 +1553,11 @@ static int atmel_spi_probe(struct platform_device *pdev) atmel_get_caps(as); + /* + * If there are chip selects in the device tree, those will be + * discovered by the SPI core when registering the SPI master + * and assigned to each SPI device. + */ as->use_cs_gpios = true; if (atmel_spi_is_v2(as) && pdev->dev.of_node && @@ -1600,10 +1566,6 @@ static int atmel_spi_probe(struct platform_device *pdev) master->num_chipselect = 4; } - ret = atmel_spi_gpio_cs(pdev); - if (ret) - goto out_unmap_regs; - as->use_dma = false; as->use_pdc = false; if (as->caps.has_dma_support) { diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 671e374e1b01..f7e054848ca5 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -456,7 +456,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) } bs->clk = devm_clk_get(&pdev->dev, NULL); - if ((!bs->clk) || (IS_ERR(bs->clk))) { + if (IS_ERR(bs->clk)) { err = PTR_ERR(bs->clk); dev_err(&pdev->dev, "could not get clk: %d\n", err); goto out_master_put; diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index f29176000b8d..dd9a8c54a693 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -213,19 +213,6 @@ int spi_bitbang_setup(struct spi_device *spi) dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs); - /* NOTE we _need_ to call chipselect() early, ideally with adapter - * setup, unless the hardware defaults cooperate to avoid confusion - * between normal (active low) and inverted chipselects. - */ - - /* deselect chip (low or high) */ - mutex_lock(&bitbang->lock); - if (!bitbang->busy) { - bitbang->chipselect(spi, BITBANG_CS_INACTIVE); - ndelay(cs->nsecs); - } - mutex_unlock(&bitbang->lock); - return 0; } EXPORT_SYMBOL_GPL(spi_bitbang_setup); diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 7c88f74f7f47..43d0e79842ac 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -13,7 +13,7 @@ #include <linux/clk.h> #include <linux/delay.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> @@ -128,10 +128,6 @@ struct cdns_spi { u32 is_decoded_cs; }; -struct cdns_spi_device_data { - bool gpio_requested; -}; - /* Macros for the SPI controller read/write */ static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset) { @@ -176,16 +172,16 @@ static void cdns_spi_init_hw(struct cdns_spi *xspi) /** * cdns_spi_chipselect - Select or deselect the chip select line * @spi: Pointer to the spi_device structure - * @is_high: Select(0) or deselect (1) the chip select line + * @enable: Select (1) or deselect (0) the chip select line */ -static void cdns_spi_chipselect(struct spi_device *spi, bool is_high) +static void cdns_spi_chipselect(struct spi_device *spi, bool enable) { struct cdns_spi *xspi = spi_master_get_devdata(spi->master); u32 ctrl_reg; ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); - if (is_high) { + if (!enable) { /* Deselect the slave */ ctrl_reg |= CDNS_SPI_CR_SSCTRL; } else { @@ -469,64 +465,6 @@ static int cdns_unprepare_transfer_hardware(struct spi_master *master) return 0; } -static int cdns_spi_setup(struct spi_device *spi) -{ - - int ret = -EINVAL; - struct cdns_spi_device_data *cdns_spi_data = spi_get_ctldata(spi); - - /* this is a pin managed by the controller, leave it alone */ - if (spi->cs_gpio == -ENOENT) - return 0; - - /* this seems to be the first time we're here */ - if (!cdns_spi_data) { - cdns_spi_data = kzalloc(sizeof(*cdns_spi_data), GFP_KERNEL); - if (!cdns_spi_data) - return -ENOMEM; - cdns_spi_data->gpio_requested = false; - spi_set_ctldata(spi, cdns_spi_data); - } - - /* if we haven't done so, grab the gpio */ - if (!cdns_spi_data->gpio_requested && gpio_is_valid(spi->cs_gpio)) { - ret = gpio_request_one(spi->cs_gpio, - (spi->mode & SPI_CS_HIGH) ? - GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, - dev_name(&spi->dev)); - if (ret) - dev_err(&spi->dev, "can't request chipselect gpio %d\n", - spi->cs_gpio); - else - cdns_spi_data->gpio_requested = true; - } else { - if (gpio_is_valid(spi->cs_gpio)) { - int mode = ((spi->mode & SPI_CS_HIGH) ? - GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH); - - ret = gpio_direction_output(spi->cs_gpio, mode); - if (ret) - dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n", - spi->cs_gpio, ret); - } - } - - return ret; -} - -static void cdns_spi_cleanup(struct spi_device *spi) -{ - struct cdns_spi_device_data *cdns_spi_data = spi_get_ctldata(spi); - - if (cdns_spi_data) { - if (cdns_spi_data->gpio_requested) - gpio_free(spi->cs_gpio); - kfree(cdns_spi_data); - spi_set_ctldata(spi, NULL); - } - -} - /** * cdns_spi_probe - Probe method for the SPI driver * @pdev: Pointer to the platform_device structure @@ -584,11 +522,6 @@ static int cdns_spi_probe(struct platform_device *pdev) goto clk_dis_apb; } - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); - ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs); if (ret < 0) master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS; @@ -603,8 +536,10 @@ static int cdns_spi_probe(struct platform_device *pdev) /* SPI controller initializations */ cdns_spi_init_hw(xspi); - pm_runtime_mark_last_busy(&pdev->dev); - pm_runtime_put_autosuspend(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); irq = platform_get_irq(pdev, 0); if (irq <= 0) { @@ -621,13 +556,12 @@ static int cdns_spi_probe(struct platform_device *pdev) goto clk_dis_all; } + master->use_gpio_descriptors = true; master->prepare_transfer_hardware = cdns_prepare_transfer_hardware; master->prepare_message = cdns_prepare_message; master->transfer_one = cdns_transfer_one; master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware; master->set_cs = cdns_spi_chipselect; - master->setup = cdns_spi_setup; - master->cleanup = cdns_spi_cleanup; master->auto_runtime_pm = true; master->mode_bits = SPI_CPOL | SPI_CPHA; diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index 18193df2eba8..8c03c409fc07 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -11,7 +11,7 @@ #include <linux/io.h> #include <linux/clk.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/platform_device.h> @@ -36,25 +36,6 @@ struct spi_clps711x_data { int len; }; -static int spi_clps711x_setup(struct spi_device *spi) -{ - if (!spi->controller_state) { - int ret; - - ret = devm_gpio_request(&spi->master->dev, spi->cs_gpio, - dev_name(&spi->master->dev)); - if (ret) - return ret; - - spi->controller_state = spi; - } - - /* We are expect that SPI-device is not selected */ - gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); - - return 0; -} - static int spi_clps711x_prepare_message(struct spi_master *master, struct spi_message *msg) { @@ -125,11 +106,11 @@ static int spi_clps711x_probe(struct platform_device *pdev) if (!master) return -ENOMEM; + master->use_gpio_descriptors = true; master->bus_num = -1; master->mode_bits = SPI_CPHA | SPI_CS_HIGH; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8); master->dev.of_node = pdev->dev.of_node; - master->setup = spi_clps711x_setup; master->prepare_message = spi_clps711x_prepare_message; master->transfer_one = spi_clps711x_transfer_one; diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 56adec83f8fc..eb246ebcfa3a 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -15,7 +15,7 @@ #include <linux/interrupt.h> #include <linux/io.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/platform_device.h> @@ -25,7 +25,6 @@ #include <linux/dma-mapping.h> #include <linux/of.h> #include <linux/of_device.h> -#include <linux/of_gpio.h> #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> #include <linux/slab.h> @@ -222,12 +221,17 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) * Board specific chip select logic decides the polarity and cs * line for the controller */ - if (spi->cs_gpio >= 0) { + if (spi->cs_gpiod) { + /* + * FIXME: is this code ever executed? This host does not + * set SPI_MASTER_GPIO_SS so this chipselect callback should + * not get called from the SPI core when we are using + * GPIOs for chip select. + */ if (value == BITBANG_CS_ACTIVE) - gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH); + gpiod_set_value(spi->cs_gpiod, 1); else - gpio_set_value(spi->cs_gpio, - !(spi->mode & SPI_CS_HIGH)); + gpiod_set_value(spi->cs_gpiod, 0); } else { if (value == BITBANG_CS_ACTIVE) { if (!(spi->mode & SPI_CS_WORD)) @@ -418,30 +422,18 @@ static int davinci_spi_of_setup(struct spi_device *spi) */ static int davinci_spi_setup(struct spi_device *spi) { - int retval = 0; struct davinci_spi *dspi; - struct spi_master *master = spi->master; struct device_node *np = spi->dev.of_node; bool internal_cs = true; dspi = spi_master_get_devdata(spi->master); if (!(spi->mode & SPI_NO_CS)) { - if (np && (master->cs_gpios != NULL) && (spi->cs_gpio >= 0)) { - retval = gpio_direction_output( - spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); + if (np && spi->cs_gpiod) internal_cs = false; - } - - if (retval) { - dev_err(&spi->dev, "GPIO %d setup failed (%d)\n", - spi->cs_gpio, retval); - return retval; - } - if (internal_cs) { + if (internal_cs) set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select); - } } if (spi->mode & SPI_READY) @@ -962,6 +954,7 @@ static int davinci_spi_probe(struct platform_device *pdev) if (ret) goto free_master; + master->use_gpio_descriptors = true; master->dev.of_node = pdev->dev.of_node; master->bus_num = pdev->id; master->num_chipselect = pdata->num_chipselect; @@ -980,27 +973,6 @@ static int davinci_spi_probe(struct platform_device *pdev) if (dspi->version == SPI_VERSION_2) dspi->bitbang.flags |= SPI_READY; - if (pdev->dev.of_node) { - int i; - - for (i = 0; i < pdata->num_chipselect; i++) { - int cs_gpio = of_get_named_gpio(pdev->dev.of_node, - "cs-gpios", i); - - if (cs_gpio == -EPROBE_DEFER) { - ret = cs_gpio; - goto free_clk; - } - - if (gpio_is_valid(cs_gpio)) { - ret = devm_gpio_request(&pdev->dev, cs_gpio, - dev_name(&pdev->dev)); - if (ret) - goto free_clk; - } - } - } - dspi->bitbang.txrx_bufs = davinci_spi_bufs; ret = davinci_spi_request_dma(dspi); diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index d0dd7814e997..4bd59a93d988 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -18,7 +18,6 @@ #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_gpio.h> #include <linux/of_platform.h> #include <linux/acpi.h> #include <linux/property.h> @@ -185,27 +184,6 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) dws->num_cs = num_cs; - if (pdev->dev.of_node) { - int i; - - for (i = 0; i < dws->num_cs; i++) { - int cs_gpio = of_get_named_gpio(pdev->dev.of_node, - "cs-gpios", i); - - if (cs_gpio == -EPROBE_DEFER) { - ret = cs_gpio; - goto out; - } - - if (gpio_is_valid(cs_gpio)) { - ret = devm_gpio_request(&pdev->dev, cs_gpio, - dev_name(&pdev->dev)); - if (ret) - goto out; - } - } - } - init_func = device_get_match_data(&pdev->dev); if (init_func) { ret = init_func(pdev, dwsmmio); diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 2e822a56576a..ac81025f86ab 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -20,7 +20,6 @@ #include <linux/delay.h> #include <linux/slab.h> #include <linux/spi/spi.h> -#include <linux/gpio.h> #include "spi-dw.h" @@ -54,41 +53,41 @@ static ssize_t dw_spi_show_regs(struct file *file, char __user *user_buf, if (!buf) return 0; - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "%s registers:\n", dev_name(&dws->master->dev)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "=================================\n"); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "CTRL0: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL0)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "CTRL1: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL1)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "SSIENR: \t0x%08x\n", dw_readl(dws, DW_SPI_SSIENR)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "SER: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SER)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "BAUDR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_BAUDR)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "TXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_TXFLTR)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "RXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_RXFLTR)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "TXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_TXFLR)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "RXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_RXFLR)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "SR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SR)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "IMR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_IMR)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "ISR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_ISR)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "DMACR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_DMACR)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "DMATDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMATDLR)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "DMARDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMARDLR)); - len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, + len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, "=================================\n"); ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); @@ -138,11 +137,10 @@ void dw_spi_set_cs(struct spi_device *spi, bool enable) struct dw_spi *dws = spi_controller_get_devdata(spi->controller); struct chip_data *chip = spi_get_ctldata(spi); - /* Chip select logic is inverted from spi_set_cs() */ if (chip && chip->cs_control) - chip->cs_control(!enable); + chip->cs_control(enable); - if (!enable) + if (enable) dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select)); else if (dws->cs_override) dw_writel(dws, DW_SPI_SER, 0); @@ -317,7 +315,8 @@ static int dw_spi_transfer_one(struct spi_controller *master, /* Default SPI mode is SCPOL = 0, SCPH = 0 */ cr0 = (transfer->bits_per_word - 1) | (chip->type << SPI_FRF_OFFSET) - | (spi->mode << SPI_MODE_OFFSET) + | ((((spi->mode & SPI_CPOL) ? 1 : 0) << SPI_SCOL_OFFSET) | + (((spi->mode & SPI_CPHA) ? 1 : 0) << SPI_SCPH_OFFSET)) | (chip->tmode << SPI_TMOD_OFFSET); /* @@ -397,7 +396,6 @@ static int dw_spi_setup(struct spi_device *spi) { struct dw_spi_chip *chip_info = NULL; struct chip_data *chip; - int ret; /* Only alloc on first setup */ chip = spi_get_ctldata(spi); @@ -425,13 +423,6 @@ static int dw_spi_setup(struct spi_device *spi) chip->tmode = SPI_TMOD_TR; - if (gpio_is_valid(spi->cs_gpio)) { - ret = gpio_direction_output(spi->cs_gpio, - !(spi->mode & SPI_CS_HIGH)); - if (ret) - return ret; - } - return 0; } @@ -496,6 +487,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) goto err_free_master; } + master->use_gpio_descriptors = true; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); master->bus_num = dws->bus_num; diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 5e10dc5c93a5..53335ccc98f6 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -67,7 +67,7 @@ #define SPI_SR 0x2c #define SPI_SR_EOQF 0x10000000 #define SPI_SR_TCFQF 0x80000000 -#define SPI_SR_CLEAR 0xdaad0000 +#define SPI_SR_CLEAR 0x9aaf0000 #define SPI_RSER_TFFFE BIT(25) #define SPI_RSER_TFFFD BIT(24) @@ -233,6 +233,9 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi) { u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi); + if (spi_controller_is_slave(dspi->master)) + return data; + if (dspi->len > 0) cmd |= SPI_PUSHR_CMD_CONT; return cmd << 16 | data; @@ -329,6 +332,11 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) dma_async_issue_pending(dma->chan_rx); dma_async_issue_pending(dma->chan_tx); + if (spi_controller_is_slave(dspi->master)) { + wait_for_completion_interruptible(&dspi->dma->cmd_rx_complete); + return 0; + } + time_left = wait_for_completion_timeout(&dspi->dma->cmd_tx_complete, DMA_COMPLETION_TIMEOUT); if (time_left == 0) { @@ -798,14 +806,18 @@ static int dspi_setup(struct spi_device *spi) ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate); chip->ctar_val = SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0) - | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0) - | SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0) - | SPI_CTAR_PCSSCK(pcssck) - | SPI_CTAR_CSSCK(cssck) - | SPI_CTAR_PASC(pasc) - | SPI_CTAR_ASC(asc) - | SPI_CTAR_PBR(pbr) - | SPI_CTAR_BR(br); + | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0); + + if (!spi_controller_is_slave(dspi->master)) { + chip->ctar_val |= SPI_CTAR_LSBFE(spi->mode & + SPI_LSB_FIRST ? 1 : 0) + | SPI_CTAR_PCSSCK(pcssck) + | SPI_CTAR_CSSCK(cssck) + | SPI_CTAR_PASC(pasc) + | SPI_CTAR_ASC(asc) + | SPI_CTAR_PBR(pbr) + | SPI_CTAR_BR(br); + } spi_set_ctldata(spi, chip); @@ -970,8 +982,13 @@ static const struct regmap_config dspi_xspi_regmap_config[] = { static void dspi_init(struct fsl_dspi *dspi) { - regmap_write(dspi->regmap, SPI_MCR, SPI_MCR_MASTER | SPI_MCR_PCSIS | - (dspi->devtype_data->xspi_mode ? SPI_MCR_XSPI : 0)); + unsigned int mcr = SPI_MCR_PCSIS | + (dspi->devtype_data->xspi_mode ? SPI_MCR_XSPI : 0); + + if (!spi_controller_is_slave(dspi->master)) + mcr |= SPI_MCR_MASTER; + + regmap_write(dspi->regmap, SPI_MCR, mcr); regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR); if (dspi->devtype_data->xspi_mode) regmap_write(dspi->regmap, SPI_CTARE(0), @@ -1027,6 +1044,9 @@ static int dspi_probe(struct platform_device *pdev) } master->bus_num = bus_num; + if (of_property_read_bool(np, "spi-slave")) + master->slave = true; + dspi->devtype_data = of_device_get_match_data(&pdev->dev); if (!dspi->devtype_data) { dev_err(&pdev->dev, "can't get devtype_data\n"); diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 08dcc3c22e88..391863914043 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -48,10 +48,13 @@ #define CR_RTF BIT(8) #define CR_RST BIT(1) #define CR_MEN BIT(0) +#define SR_MBF BIT(24) #define SR_TCF BIT(10) +#define SR_FCF BIT(9) #define SR_RDF BIT(1) #define SR_TDF BIT(0) #define IER_TCIE BIT(10) +#define IER_FCIE BIT(9) #define IER_RDIE BIT(1) #define IER_TDIE BIT(0) #define CFGR1_PCSCFG BIT(27) @@ -59,6 +62,7 @@ #define CFGR1_PCSPOL BIT(8) #define CFGR1_NOSTALL BIT(3) #define CFGR1_MASTER BIT(0) +#define FSR_RXCOUNT (BIT(16)|BIT(17)|BIT(18)) #define RSR_RXEMPTY BIT(1) #define TCR_CPOL BIT(31) #define TCR_CPHA BIT(30) @@ -161,28 +165,10 @@ static int lpspi_unprepare_xfer_hardware(struct spi_controller *controller) return 0; } -static int fsl_lpspi_txfifo_empty(struct fsl_lpspi_data *fsl_lpspi) -{ - u32 txcnt; - unsigned long orig_jiffies = jiffies; - - do { - txcnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff; - - if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { - dev_dbg(fsl_lpspi->dev, "txfifo empty timeout\n"); - return -ETIMEDOUT; - } - cond_resched(); - - } while (txcnt); - - return 0; -} - static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi) { u8 txfifo_cnt; + u32 temp; txfifo_cnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff; @@ -193,9 +179,15 @@ static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi) txfifo_cnt++; } - if (!fsl_lpspi->remain && (txfifo_cnt < fsl_lpspi->txfifosize)) - writel(0, fsl_lpspi->base + IMX7ULP_TDR); - else + if (txfifo_cnt < fsl_lpspi->txfifosize) { + if (!fsl_lpspi->is_slave) { + temp = readl(fsl_lpspi->base + IMX7ULP_TCR); + temp &= ~TCR_CONTC; + writel(temp, fsl_lpspi->base + IMX7ULP_TCR); + } + + fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE); + } else fsl_lpspi_intctrl(fsl_lpspi, IER_TDIE); } @@ -276,10 +268,6 @@ static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi) u32 temp; int ret; - temp = CR_RST; - writel(temp, fsl_lpspi->base + IMX7ULP_CR); - writel(0, fsl_lpspi->base + IMX7ULP_CR); - if (!fsl_lpspi->is_slave) { ret = fsl_lpspi_set_bitrate(fsl_lpspi); if (ret) @@ -370,6 +358,24 @@ static int fsl_lpspi_wait_for_completion(struct spi_controller *controller) return 0; } +static int fsl_lpspi_reset(struct fsl_lpspi_data *fsl_lpspi) +{ + u32 temp; + + /* Disable all interrupt */ + fsl_lpspi_intctrl(fsl_lpspi, 0); + + /* W1C for all flags in SR */ + temp = 0x3F << 8; + writel(temp, fsl_lpspi->base + IMX7ULP_SR); + + /* Clear FIFO and disable module */ + temp = CR_RRF | CR_RTF; + writel(temp, fsl_lpspi->base + IMX7ULP_CR); + + return 0; +} + static int fsl_lpspi_transfer_one(struct spi_controller *controller, struct spi_device *spi, struct spi_transfer *t) @@ -391,11 +397,7 @@ static int fsl_lpspi_transfer_one(struct spi_controller *controller, if (ret) return ret; - ret = fsl_lpspi_txfifo_empty(fsl_lpspi); - if (ret) - return ret; - - fsl_lpspi_read_rx_fifo(fsl_lpspi); + fsl_lpspi_reset(fsl_lpspi); return 0; } @@ -408,7 +410,6 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller, struct spi_device *spi = msg->spi; struct spi_transfer *xfer; bool is_first_xfer = true; - u32 temp; int ret = 0; msg->status = 0; @@ -428,13 +429,6 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller, } complete: - if (!fsl_lpspi->is_slave) { - /* de-assert SS, then finalize current message */ - temp = readl(fsl_lpspi->base + IMX7ULP_TCR); - temp &= ~TCR_CONTC; - writel(temp, fsl_lpspi->base + IMX7ULP_TCR); - } - msg->status = ret; spi_finalize_current_message(controller); @@ -443,20 +437,30 @@ complete: static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id) { + u32 temp_SR, temp_IER; struct fsl_lpspi_data *fsl_lpspi = dev_id; - u32 temp; + temp_IER = readl(fsl_lpspi->base + IMX7ULP_IER); fsl_lpspi_intctrl(fsl_lpspi, 0); - temp = readl(fsl_lpspi->base + IMX7ULP_SR); + temp_SR = readl(fsl_lpspi->base + IMX7ULP_SR); fsl_lpspi_read_rx_fifo(fsl_lpspi); - if (temp & SR_TDF) { + if ((temp_SR & SR_TDF) && (temp_IER & IER_TDIE)) { fsl_lpspi_write_tx_fifo(fsl_lpspi); + return IRQ_HANDLED; + } - if (!fsl_lpspi->remain) - complete(&fsl_lpspi->xfer_done); + if (temp_SR & SR_MBF || + readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_RXCOUNT) { + writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR); + fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE); + return IRQ_HANDLED; + } + if (temp_SR & SR_FCF && (temp_IER & IER_FCIE)) { + writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR); + complete(&fsl_lpspi->xfer_done); return IRQ_HANDLED; } diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c new file mode 100644 index 000000000000..6a713f78a62e --- /dev/null +++ b/drivers/spi/spi-fsl-qspi.c @@ -0,0 +1,966 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Freescale QuadSPI driver. + * + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * Copyright (C) 2018 Bootlin + * Copyright (C) 2018 exceet electronics GmbH + * Copyright (C) 2018 Kontron Electronics GmbH + * + * Transition to SPI MEM interface: + * Authors: + * Boris Brezillon <bbrezillon@kernel.org> + * Frieder Schrempf <frieder.schrempf@kontron.de> + * Yogesh Gaur <yogeshnarayan.gaur@nxp.com> + * Suresh Gupta <suresh.gupta@nxp.com> + * + * Based on the original fsl-quadspi.c spi-nor driver: + * Author: Freescale Semiconductor, Inc. + * + */ + +#include <linux/bitops.h> +#include <linux/clk.h> +#include <linux/completion.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_qos.h> +#include <linux/sizes.h> + +#include <linux/spi/spi.h> +#include <linux/spi/spi-mem.h> + +/* + * The driver only uses one single LUT entry, that is updated on + * each call of exec_op(). Index 0 is preset at boot with a basic + * read operation, so let's use the last entry (15). + */ +#define SEQID_LUT 15 + +/* Registers used by the driver */ +#define QUADSPI_MCR 0x00 +#define QUADSPI_MCR_RESERVED_MASK GENMASK(19, 16) +#define QUADSPI_MCR_MDIS_MASK BIT(14) +#define QUADSPI_MCR_CLR_TXF_MASK BIT(11) +#define QUADSPI_MCR_CLR_RXF_MASK BIT(10) +#define QUADSPI_MCR_DDR_EN_MASK BIT(7) +#define QUADSPI_MCR_END_CFG_MASK GENMASK(3, 2) +#define QUADSPI_MCR_SWRSTHD_MASK BIT(1) +#define QUADSPI_MCR_SWRSTSD_MASK BIT(0) + +#define QUADSPI_IPCR 0x08 +#define QUADSPI_IPCR_SEQID(x) ((x) << 24) + +#define QUADSPI_BUF3CR 0x1c +#define QUADSPI_BUF3CR_ALLMST_MASK BIT(31) +#define QUADSPI_BUF3CR_ADATSZ(x) ((x) << 8) +#define QUADSPI_BUF3CR_ADATSZ_MASK GENMASK(15, 8) + +#define QUADSPI_BFGENCR 0x20 +#define QUADSPI_BFGENCR_SEQID(x) ((x) << 12) + +#define QUADSPI_BUF0IND 0x30 +#define QUADSPI_BUF1IND 0x34 +#define QUADSPI_BUF2IND 0x38 +#define QUADSPI_SFAR 0x100 + +#define QUADSPI_SMPR 0x108 +#define QUADSPI_SMPR_DDRSMP_MASK GENMASK(18, 16) +#define QUADSPI_SMPR_FSDLY_MASK BIT(6) +#define QUADSPI_SMPR_FSPHS_MASK BIT(5) +#define QUADSPI_SMPR_HSENA_MASK BIT(0) + +#define QUADSPI_RBCT 0x110 +#define QUADSPI_RBCT_WMRK_MASK GENMASK(4, 0) +#define QUADSPI_RBCT_RXBRD_USEIPS BIT(8) + +#define QUADSPI_TBDR 0x154 + +#define QUADSPI_SR 0x15c +#define QUADSPI_SR_IP_ACC_MASK BIT(1) +#define QUADSPI_SR_AHB_ACC_MASK BIT(2) + +#define QUADSPI_FR 0x160 +#define QUADSPI_FR_TFF_MASK BIT(0) + +#define QUADSPI_SPTRCLR 0x16c +#define QUADSPI_SPTRCLR_IPPTRC BIT(8) +#define QUADSPI_SPTRCLR_BFPTRC BIT(0) + +#define QUADSPI_SFA1AD 0x180 +#define QUADSPI_SFA2AD 0x184 +#define QUADSPI_SFB1AD 0x188 +#define QUADSPI_SFB2AD 0x18c +#define QUADSPI_RBDR(x) (0x200 + ((x) * 4)) + +#define QUADSPI_LUTKEY 0x300 +#define QUADSPI_LUTKEY_VALUE 0x5AF05AF0 + +#define QUADSPI_LCKCR 0x304 +#define QUADSPI_LCKER_LOCK BIT(0) +#define QUADSPI_LCKER_UNLOCK BIT(1) + +#define QUADSPI_RSER 0x164 +#define QUADSPI_RSER_TFIE BIT(0) + +#define QUADSPI_LUT_BASE 0x310 +#define QUADSPI_LUT_OFFSET (SEQID_LUT * 4 * 4) +#define QUADSPI_LUT_REG(idx) \ + (QUADSPI_LUT_BASE + QUADSPI_LUT_OFFSET + (idx) * 4) + +/* Instruction set for the LUT register */ +#define LUT_STOP 0 +#define LUT_CMD 1 +#define LUT_ADDR 2 +#define LUT_DUMMY 3 +#define LUT_MODE 4 +#define LUT_MODE2 5 +#define LUT_MODE4 6 +#define LUT_FSL_READ 7 +#define LUT_FSL_WRITE 8 +#define LUT_JMP_ON_CS 9 +#define LUT_ADDR_DDR 10 +#define LUT_MODE_DDR 11 +#define LUT_MODE2_DDR 12 +#define LUT_MODE4_DDR 13 +#define LUT_FSL_READ_DDR 14 +#define LUT_FSL_WRITE_DDR 15 +#define LUT_DATA_LEARN 16 + +/* + * The PAD definitions for LUT register. + * + * The pad stands for the number of IO lines [0:3]. + * For example, the quad read needs four IO lines, + * so you should use LUT_PAD(4). + */ +#define LUT_PAD(x) (fls(x) - 1) + +/* + * Macro for constructing the LUT entries with the following + * register layout: + * + * --------------------------------------------------- + * | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 | + * --------------------------------------------------- + */ +#define LUT_DEF(idx, ins, pad, opr) \ + ((((ins) << 10) | ((pad) << 8) | (opr)) << (((idx) % 2) * 16)) + +/* Controller needs driver to swap endianness */ +#define QUADSPI_QUIRK_SWAP_ENDIAN BIT(0) + +/* Controller needs 4x internal clock */ +#define QUADSPI_QUIRK_4X_INT_CLK BIT(1) + +/* + * TKT253890, the controller needs the driver to fill the txfifo with + * 16 bytes at least to trigger a data transfer, even though the extra + * data won't be transferred. + */ +#define QUADSPI_QUIRK_TKT253890 BIT(2) + +/* TKT245618, the controller cannot wake up from wait mode */ +#define QUADSPI_QUIRK_TKT245618 BIT(3) + +/* + * Controller adds QSPI_AMBA_BASE (base address of the mapped memory) + * internally. No need to add it when setting SFXXAD and SFAR registers + */ +#define QUADSPI_QUIRK_BASE_INTERNAL BIT(4) + +struct fsl_qspi_devtype_data { + unsigned int rxfifo; + unsigned int txfifo; + unsigned int ahb_buf_size; + unsigned int quirks; + bool little_endian; +}; + +static const struct fsl_qspi_devtype_data vybrid_data = { + .rxfifo = SZ_128, + .txfifo = SZ_64, + .ahb_buf_size = SZ_1K, + .quirks = QUADSPI_QUIRK_SWAP_ENDIAN, + .little_endian = true, +}; + +static const struct fsl_qspi_devtype_data imx6sx_data = { + .rxfifo = SZ_128, + .txfifo = SZ_512, + .ahb_buf_size = SZ_1K, + .quirks = QUADSPI_QUIRK_4X_INT_CLK | QUADSPI_QUIRK_TKT245618, + .little_endian = true, +}; + +static const struct fsl_qspi_devtype_data imx7d_data = { + .rxfifo = SZ_512, + .txfifo = SZ_512, + .ahb_buf_size = SZ_1K, + .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK, + .little_endian = true, +}; + +static const struct fsl_qspi_devtype_data imx6ul_data = { + .rxfifo = SZ_128, + .txfifo = SZ_512, + .ahb_buf_size = SZ_1K, + .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK, + .little_endian = true, +}; + +static const struct fsl_qspi_devtype_data ls1021a_data = { + .rxfifo = SZ_128, + .txfifo = SZ_64, + .ahb_buf_size = SZ_1K, + .quirks = 0, + .little_endian = false, +}; + +static const struct fsl_qspi_devtype_data ls2080a_data = { + .rxfifo = SZ_128, + .txfifo = SZ_64, + .ahb_buf_size = SZ_1K, + .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_BASE_INTERNAL, + .little_endian = true, +}; + +struct fsl_qspi { + void __iomem *iobase; + void __iomem *ahb_addr; + u32 memmap_phy; + struct clk *clk, *clk_en; + struct device *dev; + struct completion c; + const struct fsl_qspi_devtype_data *devtype_data; + struct mutex lock; + struct pm_qos_request pm_qos_req; + int selected; +}; + +static inline int needs_swap_endian(struct fsl_qspi *q) +{ + return q->devtype_data->quirks & QUADSPI_QUIRK_SWAP_ENDIAN; +} + +static inline int needs_4x_clock(struct fsl_qspi *q) +{ + return q->devtype_data->quirks & QUADSPI_QUIRK_4X_INT_CLK; +} + +static inline int needs_fill_txfifo(struct fsl_qspi *q) +{ + return q->devtype_data->quirks & QUADSPI_QUIRK_TKT253890; +} + +static inline int needs_wakeup_wait_mode(struct fsl_qspi *q) +{ + return q->devtype_data->quirks & QUADSPI_QUIRK_TKT245618; +} + +static inline int needs_amba_base_offset(struct fsl_qspi *q) +{ + return !(q->devtype_data->quirks & QUADSPI_QUIRK_BASE_INTERNAL); +} + +/* + * An IC bug makes it necessary to rearrange the 32-bit data. + * Later chips, such as IMX6SLX, have fixed this bug. + */ +static inline u32 fsl_qspi_endian_xchg(struct fsl_qspi *q, u32 a) +{ + return needs_swap_endian(q) ? __swab32(a) : a; +} + +/* + * R/W functions for big- or little-endian registers: + * The QSPI controller's endianness is independent of + * the CPU core's endianness. So far, although the CPU + * core is little-endian the QSPI controller can use + * big-endian or little-endian. + */ +static void qspi_writel(struct fsl_qspi *q, u32 val, void __iomem *addr) +{ + if (q->devtype_data->little_endian) + iowrite32(val, addr); + else + iowrite32be(val, addr); +} + +static u32 qspi_readl(struct fsl_qspi *q, void __iomem *addr) +{ + if (q->devtype_data->little_endian) + return ioread32(addr); + + return ioread32be(addr); +} + +static irqreturn_t fsl_qspi_irq_handler(int irq, void *dev_id) +{ + struct fsl_qspi *q = dev_id; + u32 reg; + + /* clear interrupt */ + reg = qspi_readl(q, q->iobase + QUADSPI_FR); + qspi_writel(q, reg, q->iobase + QUADSPI_FR); + + if (reg & QUADSPI_FR_TFF_MASK) + complete(&q->c); + + dev_dbg(q->dev, "QUADSPI_FR : 0x%.8x:0x%.8x\n", 0, reg); + return IRQ_HANDLED; +} + +static int fsl_qspi_check_buswidth(struct fsl_qspi *q, u8 width) +{ + switch (width) { + case 1: + case 2: + case 4: + return 0; + } + + return -ENOTSUPP; +} + +static bool fsl_qspi_supports_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master); + int ret; + + ret = fsl_qspi_check_buswidth(q, op->cmd.buswidth); + + if (op->addr.nbytes) + ret |= fsl_qspi_check_buswidth(q, op->addr.buswidth); + + if (op->dummy.nbytes) + ret |= fsl_qspi_check_buswidth(q, op->dummy.buswidth); + + if (op->data.nbytes) + ret |= fsl_qspi_check_buswidth(q, op->data.buswidth); + + if (ret) + return false; + + /* + * The number of instructions needed for the op, needs + * to fit into a single LUT entry. + */ + if (op->addr.nbytes + + (op->dummy.nbytes ? 1:0) + + (op->data.nbytes ? 1:0) > 6) + return false; + + /* Max 64 dummy clock cycles supported */ + if (op->dummy.nbytes && + (op->dummy.nbytes * 8 / op->dummy.buswidth > 64)) + return false; + + /* Max data length, check controller limits and alignment */ + if (op->data.dir == SPI_MEM_DATA_IN && + (op->data.nbytes > q->devtype_data->ahb_buf_size || + (op->data.nbytes > q->devtype_data->rxfifo - 4 && + !IS_ALIGNED(op->data.nbytes, 8)))) + return false; + + if (op->data.dir == SPI_MEM_DATA_OUT && + op->data.nbytes > q->devtype_data->txfifo) + return false; + + return true; +} + +static void fsl_qspi_prepare_lut(struct fsl_qspi *q, + const struct spi_mem_op *op) +{ + void __iomem *base = q->iobase; + u32 lutval[4] = {}; + int lutidx = 1, i; + + lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth), + op->cmd.opcode); + + /* + * For some unknown reason, using LUT_ADDR doesn't work in some + * cases (at least with only one byte long addresses), so + * let's use LUT_MODE to write the address bytes one by one + */ + for (i = 0; i < op->addr.nbytes; i++) { + u8 addrbyte = op->addr.val >> (8 * (op->addr.nbytes - i - 1)); + + lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_MODE, + LUT_PAD(op->addr.buswidth), + addrbyte); + lutidx++; + } + + if (op->dummy.nbytes) { + lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY, + LUT_PAD(op->dummy.buswidth), + op->dummy.nbytes * 8 / + op->dummy.buswidth); + lutidx++; + } + + if (op->data.nbytes) { + lutval[lutidx / 2] |= LUT_DEF(lutidx, + op->data.dir == SPI_MEM_DATA_IN ? + LUT_FSL_READ : LUT_FSL_WRITE, + LUT_PAD(op->data.buswidth), + 0); + lutidx++; + } + + lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_STOP, 0, 0); + + /* unlock LUT */ + qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); + qspi_writel(q, QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR); + + /* fill LUT */ + for (i = 0; i < ARRAY_SIZE(lutval); i++) + qspi_writel(q, lutval[i], base + QUADSPI_LUT_REG(i)); + + /* lock LUT */ + qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); + qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR); +} + +static int fsl_qspi_clk_prep_enable(struct fsl_qspi *q) +{ + int ret; + + ret = clk_prepare_enable(q->clk_en); + if (ret) + return ret; + + ret = clk_prepare_enable(q->clk); + if (ret) { + clk_disable_unprepare(q->clk_en); + return ret; + } + + if (needs_wakeup_wait_mode(q)) + pm_qos_add_request(&q->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, 0); + + return 0; +} + +static void fsl_qspi_clk_disable_unprep(struct fsl_qspi *q) +{ + if (needs_wakeup_wait_mode(q)) + pm_qos_remove_request(&q->pm_qos_req); + + clk_disable_unprepare(q->clk); + clk_disable_unprepare(q->clk_en); +} + +/* + * If we have changed the content of the flash by writing or erasing, or if we + * read from flash with a different offset into the page buffer, we need to + * invalidate the AHB buffer. If we do not do so, we may read out the wrong + * data. The spec tells us reset the AHB domain and Serial Flash domain at + * the same time. + */ +static void fsl_qspi_invalidate(struct fsl_qspi *q) +{ + u32 reg; + + reg = qspi_readl(q, q->iobase + QUADSPI_MCR); + reg |= QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK; + qspi_writel(q, reg, q->iobase + QUADSPI_MCR); + + /* + * The minimum delay : 1 AHB + 2 SFCK clocks. + * Delay 1 us is enough. + */ + udelay(1); + + reg &= ~(QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK); + qspi_writel(q, reg, q->iobase + QUADSPI_MCR); +} + +static void fsl_qspi_select_mem(struct fsl_qspi *q, struct spi_device *spi) +{ + unsigned long rate = spi->max_speed_hz; + int ret; + + if (q->selected == spi->chip_select) + return; + + if (needs_4x_clock(q)) + rate *= 4; + + fsl_qspi_clk_disable_unprep(q); + + ret = clk_set_rate(q->clk, rate); + if (ret) + return; + + ret = fsl_qspi_clk_prep_enable(q); + if (ret) + return; + + q->selected = spi->chip_select; + + fsl_qspi_invalidate(q); +} + +static void fsl_qspi_read_ahb(struct fsl_qspi *q, const struct spi_mem_op *op) +{ + memcpy_fromio(op->data.buf.in, + q->ahb_addr + q->selected * q->devtype_data->ahb_buf_size, + op->data.nbytes); +} + +static void fsl_qspi_fill_txfifo(struct fsl_qspi *q, + const struct spi_mem_op *op) +{ + void __iomem *base = q->iobase; + int i; + u32 val; + + for (i = 0; i < ALIGN_DOWN(op->data.nbytes, 4); i += 4) { + memcpy(&val, op->data.buf.out + i, 4); + val = fsl_qspi_endian_xchg(q, val); + qspi_writel(q, val, base + QUADSPI_TBDR); + } + + if (i < op->data.nbytes) { + memcpy(&val, op->data.buf.out + i, op->data.nbytes - i); + val = fsl_qspi_endian_xchg(q, val); + qspi_writel(q, val, base + QUADSPI_TBDR); + } + + if (needs_fill_txfifo(q)) { + for (i = op->data.nbytes; i < 16; i += 4) + qspi_writel(q, 0, base + QUADSPI_TBDR); + } +} + +static void fsl_qspi_read_rxfifo(struct fsl_qspi *q, + const struct spi_mem_op *op) +{ + void __iomem *base = q->iobase; + int i; + u8 *buf = op->data.buf.in; + u32 val; + + for (i = 0; i < ALIGN_DOWN(op->data.nbytes, 4); i += 4) { + val = qspi_readl(q, base + QUADSPI_RBDR(i / 4)); + val = fsl_qspi_endian_xchg(q, val); + memcpy(buf + i, &val, 4); + } + + if (i < op->data.nbytes) { + val = qspi_readl(q, base + QUADSPI_RBDR(i / 4)); + val = fsl_qspi_endian_xchg(q, val); + memcpy(buf + i, &val, op->data.nbytes - i); + } +} + +static int fsl_qspi_do_op(struct fsl_qspi *q, const struct spi_mem_op *op) +{ + void __iomem *base = q->iobase; + int err = 0; + + init_completion(&q->c); + + /* + * Always start the sequence at the same index since we update + * the LUT at each exec_op() call. And also specify the DATA + * length, since it's has not been specified in the LUT. + */ + qspi_writel(q, op->data.nbytes | QUADSPI_IPCR_SEQID(SEQID_LUT), + base + QUADSPI_IPCR); + + /* Wait for the interrupt. */ + if (!wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000))) + err = -ETIMEDOUT; + + if (!err && op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN) + fsl_qspi_read_rxfifo(q, op); + + return err; +} + +static int fsl_qspi_readl_poll_tout(struct fsl_qspi *q, void __iomem *base, + u32 mask, u32 delay_us, u32 timeout_us) +{ + u32 reg; + + if (!q->devtype_data->little_endian) + mask = (u32)cpu_to_be32(mask); + + return readl_poll_timeout(base, reg, !(reg & mask), delay_us, + timeout_us); +} + +static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) +{ + struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master); + void __iomem *base = q->iobase; + u32 addr_offset = 0; + int err = 0; + + mutex_lock(&q->lock); + + /* wait for the controller being ready */ + fsl_qspi_readl_poll_tout(q, base + QUADSPI_SR, (QUADSPI_SR_IP_ACC_MASK | + QUADSPI_SR_AHB_ACC_MASK), 10, 1000); + + fsl_qspi_select_mem(q, mem->spi); + + if (needs_amba_base_offset(q)) + addr_offset = q->memmap_phy; + + qspi_writel(q, + q->selected * q->devtype_data->ahb_buf_size + addr_offset, + base + QUADSPI_SFAR); + + qspi_writel(q, qspi_readl(q, base + QUADSPI_MCR) | + QUADSPI_MCR_CLR_RXF_MASK | QUADSPI_MCR_CLR_TXF_MASK, + base + QUADSPI_MCR); + + qspi_writel(q, QUADSPI_SPTRCLR_BFPTRC | QUADSPI_SPTRCLR_IPPTRC, + base + QUADSPI_SPTRCLR); + + fsl_qspi_prepare_lut(q, op); + + /* + * If we have large chunks of data, we read them through the AHB bus + * by accessing the mapped memory. In all other cases we use + * IP commands to access the flash. + */ + if (op->data.nbytes > (q->devtype_data->rxfifo - 4) && + op->data.dir == SPI_MEM_DATA_IN) { + fsl_qspi_read_ahb(q, op); + } else { + qspi_writel(q, QUADSPI_RBCT_WMRK_MASK | + QUADSPI_RBCT_RXBRD_USEIPS, base + QUADSPI_RBCT); + + if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) + fsl_qspi_fill_txfifo(q, op); + + err = fsl_qspi_do_op(q, op); + } + + /* Invalidate the data in the AHB buffer. */ + fsl_qspi_invalidate(q); + + mutex_unlock(&q->lock); + + return err; +} + +static int fsl_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) +{ + struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master); + + if (op->data.dir == SPI_MEM_DATA_OUT) { + if (op->data.nbytes > q->devtype_data->txfifo) + op->data.nbytes = q->devtype_data->txfifo; + } else { + if (op->data.nbytes > q->devtype_data->ahb_buf_size) + op->data.nbytes = q->devtype_data->ahb_buf_size; + else if (op->data.nbytes > (q->devtype_data->rxfifo - 4)) + op->data.nbytes = ALIGN_DOWN(op->data.nbytes, 8); + } + + return 0; +} + +static int fsl_qspi_default_setup(struct fsl_qspi *q) +{ + void __iomem *base = q->iobase; + u32 reg, addr_offset = 0; + int ret; + + /* disable and unprepare clock to avoid glitch pass to controller */ + fsl_qspi_clk_disable_unprep(q); + + /* the default frequency, we will change it later if necessary. */ + ret = clk_set_rate(q->clk, 66000000); + if (ret) + return ret; + + ret = fsl_qspi_clk_prep_enable(q); + if (ret) + return ret; + + /* Reset the module */ + qspi_writel(q, QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK, + base + QUADSPI_MCR); + udelay(1); + + /* Disable the module */ + qspi_writel(q, QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK, + base + QUADSPI_MCR); + + reg = qspi_readl(q, base + QUADSPI_SMPR); + qspi_writel(q, reg & ~(QUADSPI_SMPR_FSDLY_MASK + | QUADSPI_SMPR_FSPHS_MASK + | QUADSPI_SMPR_HSENA_MASK + | QUADSPI_SMPR_DDRSMP_MASK), base + QUADSPI_SMPR); + + /* We only use the buffer3 for AHB read */ + qspi_writel(q, 0, base + QUADSPI_BUF0IND); + qspi_writel(q, 0, base + QUADSPI_BUF1IND); + qspi_writel(q, 0, base + QUADSPI_BUF2IND); + + qspi_writel(q, QUADSPI_BFGENCR_SEQID(SEQID_LUT), + q->iobase + QUADSPI_BFGENCR); + qspi_writel(q, QUADSPI_RBCT_WMRK_MASK, base + QUADSPI_RBCT); + qspi_writel(q, QUADSPI_BUF3CR_ALLMST_MASK | + QUADSPI_BUF3CR_ADATSZ(q->devtype_data->ahb_buf_size / 8), + base + QUADSPI_BUF3CR); + + if (needs_amba_base_offset(q)) + addr_offset = q->memmap_phy; + + /* + * In HW there can be a maximum of four chips on two buses with + * two chip selects on each bus. We use four chip selects in SW + * to differentiate between the four chips. + * We use ahb_buf_size for each chip and set SFA1AD, SFA2AD, SFB1AD, + * SFB2AD accordingly. + */ + qspi_writel(q, q->devtype_data->ahb_buf_size + addr_offset, + base + QUADSPI_SFA1AD); + qspi_writel(q, q->devtype_data->ahb_buf_size * 2 + addr_offset, + base + QUADSPI_SFA2AD); + qspi_writel(q, q->devtype_data->ahb_buf_size * 3 + addr_offset, + base + QUADSPI_SFB1AD); + qspi_writel(q, q->devtype_data->ahb_buf_size * 4 + addr_offset, + base + QUADSPI_SFB2AD); + + q->selected = -1; + + /* Enable the module */ + qspi_writel(q, QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK, + base + QUADSPI_MCR); + + /* clear all interrupt status */ + qspi_writel(q, 0xffffffff, q->iobase + QUADSPI_FR); + + /* enable the interrupt */ + qspi_writel(q, QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER); + + return 0; +} + +static const char *fsl_qspi_get_name(struct spi_mem *mem) +{ + struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master); + struct device *dev = &mem->spi->dev; + const char *name; + + /* + * In order to keep mtdparts compatible with the old MTD driver at + * mtd/spi-nor/fsl-quadspi.c, we set a custom name derived from the + * platform_device of the controller. + */ + if (of_get_available_child_count(q->dev->of_node) == 1) + return dev_name(q->dev); + + name = devm_kasprintf(dev, GFP_KERNEL, + "%s-%d", dev_name(q->dev), + mem->spi->chip_select); + + if (!name) { + dev_err(dev, "failed to get memory for custom flash name\n"); + return ERR_PTR(-ENOMEM); + } + + return name; +} + +static const struct spi_controller_mem_ops fsl_qspi_mem_ops = { + .adjust_op_size = fsl_qspi_adjust_op_size, + .supports_op = fsl_qspi_supports_op, + .exec_op = fsl_qspi_exec_op, + .get_name = fsl_qspi_get_name, +}; + +static int fsl_qspi_probe(struct platform_device *pdev) +{ + struct spi_controller *ctlr; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct resource *res; + struct fsl_qspi *q; + int ret; + + ctlr = spi_alloc_master(&pdev->dev, sizeof(*q)); + if (!ctlr) + return -ENOMEM; + + ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | + SPI_TX_DUAL | SPI_TX_QUAD; + + q = spi_controller_get_devdata(ctlr); + q->dev = dev; + q->devtype_data = of_device_get_match_data(dev); + if (!q->devtype_data) { + ret = -ENODEV; + goto err_put_ctrl; + } + + platform_set_drvdata(pdev, q); + + /* find the resources */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI"); + q->iobase = devm_ioremap_resource(dev, res); + if (IS_ERR(q->iobase)) { + ret = PTR_ERR(q->iobase); + goto err_put_ctrl; + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "QuadSPI-memory"); + q->ahb_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(q->ahb_addr)) { + ret = PTR_ERR(q->ahb_addr); + goto err_put_ctrl; + } + + q->memmap_phy = res->start; + + /* find the clocks */ + q->clk_en = devm_clk_get(dev, "qspi_en"); + if (IS_ERR(q->clk_en)) { + ret = PTR_ERR(q->clk_en); + goto err_put_ctrl; + } + + q->clk = devm_clk_get(dev, "qspi"); + if (IS_ERR(q->clk)) { + ret = PTR_ERR(q->clk); + goto err_put_ctrl; + } + + ret = fsl_qspi_clk_prep_enable(q); + if (ret) { + dev_err(dev, "can not enable the clock\n"); + goto err_put_ctrl; + } + + /* find the irq */ + ret = platform_get_irq(pdev, 0); + if (ret < 0) { + dev_err(dev, "failed to get the irq: %d\n", ret); + goto err_disable_clk; + } + + ret = devm_request_irq(dev, ret, + fsl_qspi_irq_handler, 0, pdev->name, q); + if (ret) { + dev_err(dev, "failed to request irq: %d\n", ret); + goto err_disable_clk; + } + + mutex_init(&q->lock); + + ctlr->bus_num = -1; + ctlr->num_chipselect = 4; + ctlr->mem_ops = &fsl_qspi_mem_ops; + + fsl_qspi_default_setup(q); + + ctlr->dev.of_node = np; + + ret = spi_register_controller(ctlr); + if (ret) + goto err_destroy_mutex; + + return 0; + +err_destroy_mutex: + mutex_destroy(&q->lock); + +err_disable_clk: + fsl_qspi_clk_disable_unprep(q); + +err_put_ctrl: + spi_controller_put(ctlr); + + dev_err(dev, "Freescale QuadSPI probe failed\n"); + return ret; +} + +static int fsl_qspi_remove(struct platform_device *pdev) +{ + struct fsl_qspi *q = platform_get_drvdata(pdev); + + /* disable the hardware */ + qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); + qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER); + + fsl_qspi_clk_disable_unprep(q); + + mutex_destroy(&q->lock); + + return 0; +} + +static int fsl_qspi_suspend(struct device *dev) +{ + return 0; +} + +static int fsl_qspi_resume(struct device *dev) +{ + struct fsl_qspi *q = dev_get_drvdata(dev); + + fsl_qspi_default_setup(q); + + return 0; +} + +static const struct of_device_id fsl_qspi_dt_ids[] = { + { .compatible = "fsl,vf610-qspi", .data = &vybrid_data, }, + { .compatible = "fsl,imx6sx-qspi", .data = &imx6sx_data, }, + { .compatible = "fsl,imx7d-qspi", .data = &imx7d_data, }, + { .compatible = "fsl,imx6ul-qspi", .data = &imx6ul_data, }, + { .compatible = "fsl,ls1021a-qspi", .data = &ls1021a_data, }, + { .compatible = "fsl,ls2080a-qspi", .data = &ls2080a_data, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids); + +static const struct dev_pm_ops fsl_qspi_pm_ops = { + .suspend = fsl_qspi_suspend, + .resume = fsl_qspi_resume, +}; + +static struct platform_driver fsl_qspi_driver = { + .driver = { + .name = "fsl-quadspi", + .of_match_table = fsl_qspi_dt_ids, + .pm = &fsl_qspi_pm_ops, + }, + .probe = fsl_qspi_probe, + .remove = fsl_qspi_remove, +}; +module_platform_driver(fsl_qspi_driver); + +MODULE_DESCRIPTION("Freescale QuadSPI Controller Driver"); +MODULE_AUTHOR("Freescale Semiconductor Inc."); +MODULE_AUTHOR("Boris Brezillon <bbrezillon@kernel.org>"); +MODULE_AUTHOR("Frieder Schrempf <frieder.schrempf@kontron.de>"); +MODULE_AUTHOR("Yogesh Gaur <yogeshnarayan.gaur@nxp.com>"); +MODULE_AUTHOR("Suresh Gupta <suresh.gupta@nxp.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index fdb7cb88fb56..5f0b0d5bfef4 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -89,9 +89,6 @@ struct spi_geni_master { int irq; }; -static void handle_fifo_timeout(struct spi_master *spi, - struct spi_message *msg); - static int get_spi_clk_cfg(unsigned int speed_hz, struct spi_geni_master *mas, unsigned int *clk_idx, @@ -122,6 +119,32 @@ static int get_spi_clk_cfg(unsigned int speed_hz, return ret; } +static void handle_fifo_timeout(struct spi_master *spi, + struct spi_message *msg) +{ + struct spi_geni_master *mas = spi_master_get_devdata(spi); + unsigned long time_left, flags; + struct geni_se *se = &mas->se; + + spin_lock_irqsave(&mas->lock, flags); + reinit_completion(&mas->xfer_done); + mas->cur_mcmd = CMD_CANCEL; + geni_se_cancel_m_cmd(se); + writel(0, se->base + SE_GENI_TX_WATERMARK_REG); + spin_unlock_irqrestore(&mas->lock, flags); + time_left = wait_for_completion_timeout(&mas->xfer_done, HZ); + if (time_left) + return; + + spin_lock_irqsave(&mas->lock, flags); + reinit_completion(&mas->xfer_done); + geni_se_abort_m_cmd(se); + spin_unlock_irqrestore(&mas->lock, flags); + time_left = wait_for_completion_timeout(&mas->xfer_done, HZ); + if (!time_left) + dev_err(mas->dev, "Failed to cancel/abort m_cmd\n"); +} + static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) { struct spi_geni_master *mas = spi_master_get_devdata(slv->master); @@ -233,7 +256,6 @@ static int spi_geni_prepare_message(struct spi_master *spi, struct geni_se *se = &mas->se; geni_se_select_mode(se, GENI_SE_FIFO); - reinit_completion(&mas->xfer_done); ret = setup_fifo_params(spi_msg->spi, spi); if (ret) dev_err(mas->dev, "Couldn't select mode %d\n", ret); @@ -357,32 +379,6 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG); } -static void handle_fifo_timeout(struct spi_master *spi, - struct spi_message *msg) -{ - struct spi_geni_master *mas = spi_master_get_devdata(spi); - unsigned long time_left, flags; - struct geni_se *se = &mas->se; - - spin_lock_irqsave(&mas->lock, flags); - reinit_completion(&mas->xfer_done); - mas->cur_mcmd = CMD_CANCEL; - geni_se_cancel_m_cmd(se); - writel(0, se->base + SE_GENI_TX_WATERMARK_REG); - spin_unlock_irqrestore(&mas->lock, flags); - time_left = wait_for_completion_timeout(&mas->xfer_done, HZ); - if (time_left) - return; - - spin_lock_irqsave(&mas->lock, flags); - reinit_completion(&mas->xfer_done); - geni_se_abort_m_cmd(se); - spin_unlock_irqrestore(&mas->lock, flags); - time_left = wait_for_completion_timeout(&mas->xfer_done, HZ); - if (!time_left) - dev_err(mas->dev, "Failed to cancel/abort m_cmd\n"); -} - static int spi_geni_transfer_one(struct spi_master *spi, struct spi_device *slv, struct spi_transfer *xfer) diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index a4aee26028cd..53b35c56a557 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -428,7 +428,8 @@ static int spi_gpio_probe(struct platform_device *pdev) return status; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); - master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL; + master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL | + SPI_CS_HIGH; master->flags = master_flags; master->bus_num = pdev->id; /* The master needs to think there is a chipselect even if not connected */ @@ -455,7 +456,6 @@ static int spi_gpio_probe(struct platform_device *pdev) spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3; } spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; - spi_gpio->bitbang.flags = SPI_CS_HIGH; status = spi_bitbang_start(&spi_gpio->bitbang); if (status) diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index 5217a5628be2..a4d8d19ecff9 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -537,7 +537,6 @@ EXPORT_SYMBOL_GPL(spi_mem_dirmap_create); /** * spi_mem_dirmap_destroy() - Destroy a direct mapping descriptor * @desc: the direct mapping descriptor to destroy - * @info: direct mapping information * * This function destroys a direct mapping descriptor previously created by * spi_mem_dirmap_create(). @@ -548,9 +547,80 @@ void spi_mem_dirmap_destroy(struct spi_mem_dirmap_desc *desc) if (!desc->nodirmap && ctlr->mem_ops && ctlr->mem_ops->dirmap_destroy) ctlr->mem_ops->dirmap_destroy(desc); + + kfree(desc); } EXPORT_SYMBOL_GPL(spi_mem_dirmap_destroy); +static void devm_spi_mem_dirmap_release(struct device *dev, void *res) +{ + struct spi_mem_dirmap_desc *desc = *(struct spi_mem_dirmap_desc **)res; + + spi_mem_dirmap_destroy(desc); +} + +/** + * devm_spi_mem_dirmap_create() - Create a direct mapping descriptor and attach + * it to a device + * @dev: device the dirmap desc will be attached to + * @mem: SPI mem device this direct mapping should be created for + * @info: direct mapping information + * + * devm_ variant of the spi_mem_dirmap_create() function. See + * spi_mem_dirmap_create() for more details. + * + * Return: a valid pointer in case of success, and ERR_PTR() otherwise. + */ +struct spi_mem_dirmap_desc * +devm_spi_mem_dirmap_create(struct device *dev, struct spi_mem *mem, + const struct spi_mem_dirmap_info *info) +{ + struct spi_mem_dirmap_desc **ptr, *desc; + + ptr = devres_alloc(devm_spi_mem_dirmap_release, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + desc = spi_mem_dirmap_create(mem, info); + if (IS_ERR(desc)) { + devres_free(ptr); + } else { + *ptr = desc; + devres_add(dev, ptr); + } + + return desc; +} +EXPORT_SYMBOL_GPL(devm_spi_mem_dirmap_create); + +static int devm_spi_mem_dirmap_match(struct device *dev, void *res, void *data) +{ + struct spi_mem_dirmap_desc **ptr = res; + + if (WARN_ON(!ptr || !*ptr)) + return 0; + + return *ptr == data; +} + +/** + * devm_spi_mem_dirmap_destroy() - Destroy a direct mapping descriptor attached + * to a device + * @dev: device the dirmap desc is attached to + * @desc: the direct mapping descriptor to destroy + * + * devm_ variant of the spi_mem_dirmap_destroy() function. See + * spi_mem_dirmap_destroy() for more details. + */ +void devm_spi_mem_dirmap_destroy(struct device *dev, + struct spi_mem_dirmap_desc *desc) +{ + devres_release(dev, devm_spi_mem_dirmap_release, + devm_spi_mem_dirmap_match, desc); +} +EXPORT_SYMBOL_GPL(devm_spi_mem_dirmap_destroy); + /** * spi_mem_dirmap_dirmap_read() - Read data through a direct mapping * @desc: direct mapping descriptor diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 6ac95a2a21ce..7bf53cfc25d6 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -39,6 +39,7 @@ #include <linux/stmp_device.h> #include <linux/spi/spi.h> #include <linux/spi/mxs-spi.h> +#include <trace/events/spi.h> #define DRIVER_NAME "mxs-spi" @@ -374,6 +375,8 @@ static int mxs_spi_transfer_one(struct spi_master *master, list_for_each_entry(t, &m->transfers, transfer_list) { + trace_spi_transfer_start(m, t); + status = mxs_spi_setup_transfer(m->spi, t); if (status) break; @@ -419,6 +422,8 @@ static int mxs_spi_transfer_one(struct spi_master *master, flag); } + trace_spi_transfer_stop(m, t); + if (status) { stmp_reset_block(ssp->base); break; diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c index e1dca79b9090..734a2b956959 100644 --- a/drivers/spi/spi-npcm-pspi.c +++ b/drivers/spi/spi-npcm-pspi.c @@ -465,7 +465,8 @@ out_master_put: static int npcm_pspi_remove(struct platform_device *pdev) { - struct npcm_pspi *priv = platform_get_drvdata(pdev); + struct spi_master *master = platform_get_drvdata(pdev); + struct npcm_pspi *priv = spi_master_get_devdata(master); npcm_pspi_reset_hw(priv); clk_disable_unprepare(priv->clk); diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c new file mode 100644 index 000000000000..8894f98cc99c --- /dev/null +++ b/drivers/spi/spi-nxp-fspi.c @@ -0,0 +1,1106 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * NXP FlexSPI(FSPI) controller driver. + * + * Copyright 2019 NXP. + * + * FlexSPI is a flexsible SPI host controller which supports two SPI + * channels and up to 4 external devices. Each channel supports + * Single/Dual/Quad/Octal mode data transfer (1/2/4/8 bidirectional + * data lines). + * + * FlexSPI controller is driven by the LUT(Look-up Table) registers + * LUT registers are a look-up-table for sequences of instructions. + * A valid sequence consists of four LUT registers. + * Maximum 32 LUT sequences can be programmed simultaneously. + * + * LUTs are being created at run-time based on the commands passed + * from the spi-mem framework, thus using single LUT index. + * + * Software triggered Flash read/write access by IP Bus. + * + * Memory mapped read access by AHB Bus. + * + * Based on SPI MEM interface and spi-fsl-qspi.c driver. + * + * Author: + * Yogesh Narayan Gaur <yogeshnarayan.gaur@nxp.com> + * Boris Brezillon <bbrezillon@kernel.org> + * Frieder Schrempf <frieder.schrempf@kontron.de> + */ + +#include <linux/bitops.h> +#include <linux/clk.h> +#include <linux/completion.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_qos.h> +#include <linux/sizes.h> + +#include <linux/spi/spi.h> +#include <linux/spi/spi-mem.h> + +/* + * The driver only uses one single LUT entry, that is updated on + * each call of exec_op(). Index 0 is preset at boot with a basic + * read operation, so let's use the last entry (31). + */ +#define SEQID_LUT 31 + +/* Registers used by the driver */ +#define FSPI_MCR0 0x00 +#define FSPI_MCR0_AHB_TIMEOUT(x) ((x) << 24) +#define FSPI_MCR0_IP_TIMEOUT(x) ((x) << 16) +#define FSPI_MCR0_LEARN_EN BIT(15) +#define FSPI_MCR0_SCRFRUN_EN BIT(14) +#define FSPI_MCR0_OCTCOMB_EN BIT(13) +#define FSPI_MCR0_DOZE_EN BIT(12) +#define FSPI_MCR0_HSEN BIT(11) +#define FSPI_MCR0_SERCLKDIV BIT(8) +#define FSPI_MCR0_ATDF_EN BIT(7) +#define FSPI_MCR0_ARDF_EN BIT(6) +#define FSPI_MCR0_RXCLKSRC(x) ((x) << 4) +#define FSPI_MCR0_END_CFG(x) ((x) << 2) +#define FSPI_MCR0_MDIS BIT(1) +#define FSPI_MCR0_SWRST BIT(0) + +#define FSPI_MCR1 0x04 +#define FSPI_MCR1_SEQ_TIMEOUT(x) ((x) << 16) +#define FSPI_MCR1_AHB_TIMEOUT(x) (x) + +#define FSPI_MCR2 0x08 +#define FSPI_MCR2_IDLE_WAIT(x) ((x) << 24) +#define FSPI_MCR2_SAMEDEVICEEN BIT(15) +#define FSPI_MCR2_CLRLRPHS BIT(14) +#define FSPI_MCR2_ABRDATSZ BIT(8) +#define FSPI_MCR2_ABRLEARN BIT(7) +#define FSPI_MCR2_ABR_READ BIT(6) +#define FSPI_MCR2_ABRWRITE BIT(5) +#define FSPI_MCR2_ABRDUMMY BIT(4) +#define FSPI_MCR2_ABR_MODE BIT(3) +#define FSPI_MCR2_ABRCADDR BIT(2) +#define FSPI_MCR2_ABRRADDR BIT(1) +#define FSPI_MCR2_ABR_CMD BIT(0) + +#define FSPI_AHBCR 0x0c +#define FSPI_AHBCR_RDADDROPT BIT(6) +#define FSPI_AHBCR_PREF_EN BIT(5) +#define FSPI_AHBCR_BUFF_EN BIT(4) +#define FSPI_AHBCR_CACH_EN BIT(3) +#define FSPI_AHBCR_CLRTXBUF BIT(2) +#define FSPI_AHBCR_CLRRXBUF BIT(1) +#define FSPI_AHBCR_PAR_EN BIT(0) + +#define FSPI_INTEN 0x10 +#define FSPI_INTEN_SCLKSBWR BIT(9) +#define FSPI_INTEN_SCLKSBRD BIT(8) +#define FSPI_INTEN_DATALRNFL BIT(7) +#define FSPI_INTEN_IPTXWE BIT(6) +#define FSPI_INTEN_IPRXWA BIT(5) +#define FSPI_INTEN_AHBCMDERR BIT(4) +#define FSPI_INTEN_IPCMDERR BIT(3) +#define FSPI_INTEN_AHBCMDGE BIT(2) +#define FSPI_INTEN_IPCMDGE BIT(1) +#define FSPI_INTEN_IPCMDDONE BIT(0) + +#define FSPI_INTR 0x14 +#define FSPI_INTR_SCLKSBWR BIT(9) +#define FSPI_INTR_SCLKSBRD BIT(8) +#define FSPI_INTR_DATALRNFL BIT(7) +#define FSPI_INTR_IPTXWE BIT(6) +#define FSPI_INTR_IPRXWA BIT(5) +#define FSPI_INTR_AHBCMDERR BIT(4) +#define FSPI_INTR_IPCMDERR BIT(3) +#define FSPI_INTR_AHBCMDGE BIT(2) +#define FSPI_INTR_IPCMDGE BIT(1) +#define FSPI_INTR_IPCMDDONE BIT(0) + +#define FSPI_LUTKEY 0x18 +#define FSPI_LUTKEY_VALUE 0x5AF05AF0 + +#define FSPI_LCKCR 0x1C + +#define FSPI_LCKER_LOCK 0x1 +#define FSPI_LCKER_UNLOCK 0x2 + +#define FSPI_BUFXCR_INVALID_MSTRID 0xE +#define FSPI_AHBRX_BUF0CR0 0x20 +#define FSPI_AHBRX_BUF1CR0 0x24 +#define FSPI_AHBRX_BUF2CR0 0x28 +#define FSPI_AHBRX_BUF3CR0 0x2C +#define FSPI_AHBRX_BUF4CR0 0x30 +#define FSPI_AHBRX_BUF5CR0 0x34 +#define FSPI_AHBRX_BUF6CR0 0x38 +#define FSPI_AHBRX_BUF7CR0 0x3C +#define FSPI_AHBRXBUF0CR7_PREF BIT(31) + +#define FSPI_AHBRX_BUF0CR1 0x40 +#define FSPI_AHBRX_BUF1CR1 0x44 +#define FSPI_AHBRX_BUF2CR1 0x48 +#define FSPI_AHBRX_BUF3CR1 0x4C +#define FSPI_AHBRX_BUF4CR1 0x50 +#define FSPI_AHBRX_BUF5CR1 0x54 +#define FSPI_AHBRX_BUF6CR1 0x58 +#define FSPI_AHBRX_BUF7CR1 0x5C + +#define FSPI_FLSHA1CR0 0x60 +#define FSPI_FLSHA2CR0 0x64 +#define FSPI_FLSHB1CR0 0x68 +#define FSPI_FLSHB2CR0 0x6C +#define FSPI_FLSHXCR0_SZ_KB 10 +#define FSPI_FLSHXCR0_SZ(x) ((x) >> FSPI_FLSHXCR0_SZ_KB) + +#define FSPI_FLSHA1CR1 0x70 +#define FSPI_FLSHA2CR1 0x74 +#define FSPI_FLSHB1CR1 0x78 +#define FSPI_FLSHB2CR1 0x7C +#define FSPI_FLSHXCR1_CSINTR(x) ((x) << 16) +#define FSPI_FLSHXCR1_CAS(x) ((x) << 11) +#define FSPI_FLSHXCR1_WA BIT(10) +#define FSPI_FLSHXCR1_TCSH(x) ((x) << 5) +#define FSPI_FLSHXCR1_TCSS(x) (x) + +#define FSPI_FLSHA1CR2 0x80 +#define FSPI_FLSHA2CR2 0x84 +#define FSPI_FLSHB1CR2 0x88 +#define FSPI_FLSHB2CR2 0x8C +#define FSPI_FLSHXCR2_CLRINSP BIT(24) +#define FSPI_FLSHXCR2_AWRWAIT BIT(16) +#define FSPI_FLSHXCR2_AWRSEQN_SHIFT 13 +#define FSPI_FLSHXCR2_AWRSEQI_SHIFT 8 +#define FSPI_FLSHXCR2_ARDSEQN_SHIFT 5 +#define FSPI_FLSHXCR2_ARDSEQI_SHIFT 0 + +#define FSPI_IPCR0 0xA0 + +#define FSPI_IPCR1 0xA4 +#define FSPI_IPCR1_IPAREN BIT(31) +#define FSPI_IPCR1_SEQNUM_SHIFT 24 +#define FSPI_IPCR1_SEQID_SHIFT 16 +#define FSPI_IPCR1_IDATSZ(x) (x) + +#define FSPI_IPCMD 0xB0 +#define FSPI_IPCMD_TRG BIT(0) + +#define FSPI_DLPR 0xB4 + +#define FSPI_IPRXFCR 0xB8 +#define FSPI_IPRXFCR_CLR BIT(0) +#define FSPI_IPRXFCR_DMA_EN BIT(1) +#define FSPI_IPRXFCR_WMRK(x) ((x) << 2) + +#define FSPI_IPTXFCR 0xBC +#define FSPI_IPTXFCR_CLR BIT(0) +#define FSPI_IPTXFCR_DMA_EN BIT(1) +#define FSPI_IPTXFCR_WMRK(x) ((x) << 2) + +#define FSPI_DLLACR 0xC0 +#define FSPI_DLLACR_OVRDEN BIT(8) + +#define FSPI_DLLBCR 0xC4 +#define FSPI_DLLBCR_OVRDEN BIT(8) + +#define FSPI_STS0 0xE0 +#define FSPI_STS0_DLPHB(x) ((x) << 8) +#define FSPI_STS0_DLPHA(x) ((x) << 4) +#define FSPI_STS0_CMD_SRC(x) ((x) << 2) +#define FSPI_STS0_ARB_IDLE BIT(1) +#define FSPI_STS0_SEQ_IDLE BIT(0) + +#define FSPI_STS1 0xE4 +#define FSPI_STS1_IP_ERRCD(x) ((x) << 24) +#define FSPI_STS1_IP_ERRID(x) ((x) << 16) +#define FSPI_STS1_AHB_ERRCD(x) ((x) << 8) +#define FSPI_STS1_AHB_ERRID(x) (x) + +#define FSPI_AHBSPNST 0xEC +#define FSPI_AHBSPNST_DATLFT(x) ((x) << 16) +#define FSPI_AHBSPNST_BUFID(x) ((x) << 1) +#define FSPI_AHBSPNST_ACTIVE BIT(0) + +#define FSPI_IPRXFSTS 0xF0 +#define FSPI_IPRXFSTS_RDCNTR(x) ((x) << 16) +#define FSPI_IPRXFSTS_FILL(x) (x) + +#define FSPI_IPTXFSTS 0xF4 +#define FSPI_IPTXFSTS_WRCNTR(x) ((x) << 16) +#define FSPI_IPTXFSTS_FILL(x) (x) + +#define FSPI_RFDR 0x100 +#define FSPI_TFDR 0x180 + +#define FSPI_LUT_BASE 0x200 +#define FSPI_LUT_OFFSET (SEQID_LUT * 4 * 4) +#define FSPI_LUT_REG(idx) \ + (FSPI_LUT_BASE + FSPI_LUT_OFFSET + (idx) * 4) + +/* register map end */ + +/* Instruction set for the LUT register. */ +#define LUT_STOP 0x00 +#define LUT_CMD 0x01 +#define LUT_ADDR 0x02 +#define LUT_CADDR_SDR 0x03 +#define LUT_MODE 0x04 +#define LUT_MODE2 0x05 +#define LUT_MODE4 0x06 +#define LUT_MODE8 0x07 +#define LUT_NXP_WRITE 0x08 +#define LUT_NXP_READ 0x09 +#define LUT_LEARN_SDR 0x0A +#define LUT_DATSZ_SDR 0x0B +#define LUT_DUMMY 0x0C +#define LUT_DUMMY_RWDS_SDR 0x0D +#define LUT_JMP_ON_CS 0x1F +#define LUT_CMD_DDR 0x21 +#define LUT_ADDR_DDR 0x22 +#define LUT_CADDR_DDR 0x23 +#define LUT_MODE_DDR 0x24 +#define LUT_MODE2_DDR 0x25 +#define LUT_MODE4_DDR 0x26 +#define LUT_MODE8_DDR 0x27 +#define LUT_WRITE_DDR 0x28 +#define LUT_READ_DDR 0x29 +#define LUT_LEARN_DDR 0x2A +#define LUT_DATSZ_DDR 0x2B +#define LUT_DUMMY_DDR 0x2C +#define LUT_DUMMY_RWDS_DDR 0x2D + +/* + * Calculate number of required PAD bits for LUT register. + * + * The pad stands for the number of IO lines [0:7]. + * For example, the octal read needs eight IO lines, + * so you should use LUT_PAD(8). This macro + * returns 3 i.e. use eight (2^3) IP lines for read. + */ +#define LUT_PAD(x) (fls(x) - 1) + +/* + * Macro for constructing the LUT entries with the following + * register layout: + * + * --------------------------------------------------- + * | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 | + * --------------------------------------------------- + */ +#define PAD_SHIFT 8 +#define INSTR_SHIFT 10 +#define OPRND_SHIFT 16 + +/* Macros for constructing the LUT register. */ +#define LUT_DEF(idx, ins, pad, opr) \ + ((((ins) << INSTR_SHIFT) | ((pad) << PAD_SHIFT) | \ + (opr)) << (((idx) % 2) * OPRND_SHIFT)) + +#define POLL_TOUT 5000 +#define NXP_FSPI_MAX_CHIPSELECT 4 + +struct nxp_fspi_devtype_data { + unsigned int rxfifo; + unsigned int txfifo; + unsigned int ahb_buf_size; + unsigned int quirks; + bool little_endian; +}; + +static const struct nxp_fspi_devtype_data lx2160a_data = { + .rxfifo = SZ_512, /* (64 * 64 bits) */ + .txfifo = SZ_1K, /* (128 * 64 bits) */ + .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ + .quirks = 0, + .little_endian = true, /* little-endian */ +}; + +struct nxp_fspi { + void __iomem *iobase; + void __iomem *ahb_addr; + u32 memmap_phy; + u32 memmap_phy_size; + struct clk *clk, *clk_en; + struct device *dev; + struct completion c; + const struct nxp_fspi_devtype_data *devtype_data; + struct mutex lock; + struct pm_qos_request pm_qos_req; + int selected; +}; + +/* + * R/W functions for big- or little-endian registers: + * The FSPI controller's endianness is independent of + * the CPU core's endianness. So far, although the CPU + * core is little-endian the FSPI controller can use + * big-endian or little-endian. + */ +static void fspi_writel(struct nxp_fspi *f, u32 val, void __iomem *addr) +{ + if (f->devtype_data->little_endian) + iowrite32(val, addr); + else + iowrite32be(val, addr); +} + +static u32 fspi_readl(struct nxp_fspi *f, void __iomem *addr) +{ + if (f->devtype_data->little_endian) + return ioread32(addr); + else + return ioread32be(addr); +} + +static irqreturn_t nxp_fspi_irq_handler(int irq, void *dev_id) +{ + struct nxp_fspi *f = dev_id; + u32 reg; + + /* clear interrupt */ + reg = fspi_readl(f, f->iobase + FSPI_INTR); + fspi_writel(f, FSPI_INTR_IPCMDDONE, f->iobase + FSPI_INTR); + + if (reg & FSPI_INTR_IPCMDDONE) + complete(&f->c); + + return IRQ_HANDLED; +} + +static int nxp_fspi_check_buswidth(struct nxp_fspi *f, u8 width) +{ + switch (width) { + case 1: + case 2: + case 4: + case 8: + return 0; + } + + return -ENOTSUPP; +} + +static bool nxp_fspi_supports_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master); + int ret; + + ret = nxp_fspi_check_buswidth(f, op->cmd.buswidth); + + if (op->addr.nbytes) + ret |= nxp_fspi_check_buswidth(f, op->addr.buswidth); + + if (op->dummy.nbytes) + ret |= nxp_fspi_check_buswidth(f, op->dummy.buswidth); + + if (op->data.nbytes) + ret |= nxp_fspi_check_buswidth(f, op->data.buswidth); + + if (ret) + return false; + + /* + * The number of address bytes should be equal to or less than 4 bytes. + */ + if (op->addr.nbytes > 4) + return false; + + /* + * If requested address value is greater than controller assigned + * memory mapped space, return error as it didn't fit in the range + * of assigned address space. + */ + if (op->addr.val >= f->memmap_phy_size) + return false; + + /* Max 64 dummy clock cycles supported */ + if (op->dummy.buswidth && + (op->dummy.nbytes * 8 / op->dummy.buswidth > 64)) + return false; + + /* Max data length, check controller limits and alignment */ + if (op->data.dir == SPI_MEM_DATA_IN && + (op->data.nbytes > f->devtype_data->ahb_buf_size || + (op->data.nbytes > f->devtype_data->rxfifo - 4 && + !IS_ALIGNED(op->data.nbytes, 8)))) + return false; + + if (op->data.dir == SPI_MEM_DATA_OUT && + op->data.nbytes > f->devtype_data->txfifo) + return false; + + return true; +} + +/* Instead of busy looping invoke readl_poll_timeout functionality. */ +static int fspi_readl_poll_tout(struct nxp_fspi *f, void __iomem *base, + u32 mask, u32 delay_us, + u32 timeout_us, bool c) +{ + u32 reg; + + if (!f->devtype_data->little_endian) + mask = (u32)cpu_to_be32(mask); + + if (c) + return readl_poll_timeout(base, reg, (reg & mask), + delay_us, timeout_us); + else + return readl_poll_timeout(base, reg, !(reg & mask), + delay_us, timeout_us); +} + +/* + * If the slave device content being changed by Write/Erase, need to + * invalidate the AHB buffer. This can be achieved by doing the reset + * of controller after setting MCR0[SWRESET] bit. + */ +static inline void nxp_fspi_invalid(struct nxp_fspi *f) +{ + u32 reg; + int ret; + + reg = fspi_readl(f, f->iobase + FSPI_MCR0); + fspi_writel(f, reg | FSPI_MCR0_SWRST, f->iobase + FSPI_MCR0); + + /* w1c register, wait unit clear */ + ret = fspi_readl_poll_tout(f, f->iobase + FSPI_MCR0, + FSPI_MCR0_SWRST, 0, POLL_TOUT, false); + WARN_ON(ret); +} + +static void nxp_fspi_prepare_lut(struct nxp_fspi *f, + const struct spi_mem_op *op) +{ + void __iomem *base = f->iobase; + u32 lutval[4] = {}; + int lutidx = 1, i; + + /* cmd */ + lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth), + op->cmd.opcode); + + /* addr bytes */ + if (op->addr.nbytes) { + lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_ADDR, + LUT_PAD(op->addr.buswidth), + op->addr.nbytes * 8); + lutidx++; + } + + /* dummy bytes, if needed */ + if (op->dummy.nbytes) { + lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY, + /* + * Due to FlexSPI controller limitation number of PAD for dummy + * buswidth needs to be programmed as equal to data buswidth. + */ + LUT_PAD(op->data.buswidth), + op->dummy.nbytes * 8 / + op->dummy.buswidth); + lutidx++; + } + + /* read/write data bytes */ + if (op->data.nbytes) { + lutval[lutidx / 2] |= LUT_DEF(lutidx, + op->data.dir == SPI_MEM_DATA_IN ? + LUT_NXP_READ : LUT_NXP_WRITE, + LUT_PAD(op->data.buswidth), + 0); + lutidx++; + } + + /* stop condition. */ + lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_STOP, 0, 0); + + /* unlock LUT */ + fspi_writel(f, FSPI_LUTKEY_VALUE, f->iobase + FSPI_LUTKEY); + fspi_writel(f, FSPI_LCKER_UNLOCK, f->iobase + FSPI_LCKCR); + + /* fill LUT */ + for (i = 0; i < ARRAY_SIZE(lutval); i++) + fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i)); + + dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x]\n", + op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3]); + + /* lock LUT */ + fspi_writel(f, FSPI_LUTKEY_VALUE, f->iobase + FSPI_LUTKEY); + fspi_writel(f, FSPI_LCKER_LOCK, f->iobase + FSPI_LCKCR); +} + +static int nxp_fspi_clk_prep_enable(struct nxp_fspi *f) +{ + int ret; + + ret = clk_prepare_enable(f->clk_en); + if (ret) + return ret; + + ret = clk_prepare_enable(f->clk); + if (ret) { + clk_disable_unprepare(f->clk_en); + return ret; + } + + return 0; +} + +static void nxp_fspi_clk_disable_unprep(struct nxp_fspi *f) +{ + clk_disable_unprepare(f->clk); + clk_disable_unprepare(f->clk_en); +} + +/* + * In FlexSPI controller, flash access is based on value of FSPI_FLSHXXCR0 + * register and start base address of the slave device. + * + * (Higher address) + * -------- <-- FLSHB2CR0 + * | B2 | + * | | + * B2 start address --> -------- <-- FLSHB1CR0 + * | B1 | + * | | + * B1 start address --> -------- <-- FLSHA2CR0 + * | A2 | + * | | + * A2 start address --> -------- <-- FLSHA1CR0 + * | A1 | + * | | + * A1 start address --> -------- (Lower address) + * + * + * Start base address defines the starting address range for given CS and + * FSPI_FLSHXXCR0 defines the size of the slave device connected at given CS. + * + * But, different targets are having different combinations of number of CS, + * some targets only have single CS or two CS covering controller's full + * memory mapped space area. + * Thus, implementation is being done as independent of the size and number + * of the connected slave device. + * Assign controller memory mapped space size as the size to the connected + * slave device. + * Mark FLSHxxCR0 as zero initially and then assign value only to the selected + * chip-select Flash configuration register. + * + * For e.g. to access CS2 (B1), FLSHB1CR0 register would be equal to the + * memory mapped size of the controller. + * Value for rest of the CS FLSHxxCR0 register would be zero. + * + */ +static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi) +{ + unsigned long rate = spi->max_speed_hz; + int ret; + uint64_t size_kb; + + /* + * Return, if previously selected slave device is same as current + * requested slave device. + */ + if (f->selected == spi->chip_select) + return; + + /* Reset FLSHxxCR0 registers */ + fspi_writel(f, 0, f->iobase + FSPI_FLSHA1CR0); + fspi_writel(f, 0, f->iobase + FSPI_FLSHA2CR0); + fspi_writel(f, 0, f->iobase + FSPI_FLSHB1CR0); + fspi_writel(f, 0, f->iobase + FSPI_FLSHB2CR0); + + /* Assign controller memory mapped space as size, KBytes, of flash. */ + size_kb = FSPI_FLSHXCR0_SZ(f->memmap_phy_size); + + fspi_writel(f, size_kb, f->iobase + FSPI_FLSHA1CR0 + + 4 * spi->chip_select); + + dev_dbg(f->dev, "Slave device [CS:%x] selected\n", spi->chip_select); + + nxp_fspi_clk_disable_unprep(f); + + ret = clk_set_rate(f->clk, rate); + if (ret) + return; + + ret = nxp_fspi_clk_prep_enable(f); + if (ret) + return; + + f->selected = spi->chip_select; +} + +static void nxp_fspi_read_ahb(struct nxp_fspi *f, const struct spi_mem_op *op) +{ + u32 len = op->data.nbytes; + + /* Read out the data directly from the AHB buffer. */ + memcpy_fromio(op->data.buf.in, (f->ahb_addr + op->addr.val), len); +} + +static void nxp_fspi_fill_txfifo(struct nxp_fspi *f, + const struct spi_mem_op *op) +{ + void __iomem *base = f->iobase; + int i, ret; + u8 *buf = (u8 *) op->data.buf.out; + + /* clear the TX FIFO. */ + fspi_writel(f, FSPI_IPTXFCR_CLR, base + FSPI_IPTXFCR); + + /* + * Default value of water mark level is 8 bytes, hence in single + * write request controller can write max 8 bytes of data. + */ + + for (i = 0; i < ALIGN_DOWN(op->data.nbytes, 8); i += 8) { + /* Wait for TXFIFO empty */ + ret = fspi_readl_poll_tout(f, f->iobase + FSPI_INTR, + FSPI_INTR_IPTXWE, 0, + POLL_TOUT, true); + WARN_ON(ret); + + fspi_writel(f, *(u32 *) (buf + i), base + FSPI_TFDR); + fspi_writel(f, *(u32 *) (buf + i + 4), base + FSPI_TFDR + 4); + fspi_writel(f, FSPI_INTR_IPTXWE, base + FSPI_INTR); + } + + if (i < op->data.nbytes) { + u32 data = 0; + int j; + /* Wait for TXFIFO empty */ + ret = fspi_readl_poll_tout(f, f->iobase + FSPI_INTR, + FSPI_INTR_IPTXWE, 0, + POLL_TOUT, true); + WARN_ON(ret); + + for (j = 0; j < ALIGN(op->data.nbytes - i, 4); j += 4) { + memcpy(&data, buf + i + j, 4); + fspi_writel(f, data, base + FSPI_TFDR + j); + } + fspi_writel(f, FSPI_INTR_IPTXWE, base + FSPI_INTR); + } +} + +static void nxp_fspi_read_rxfifo(struct nxp_fspi *f, + const struct spi_mem_op *op) +{ + void __iomem *base = f->iobase; + int i, ret; + int len = op->data.nbytes; + u8 *buf = (u8 *) op->data.buf.in; + + /* + * Default value of water mark level is 8 bytes, hence in single + * read request controller can read max 8 bytes of data. + */ + for (i = 0; i < ALIGN_DOWN(len, 8); i += 8) { + /* Wait for RXFIFO available */ + ret = fspi_readl_poll_tout(f, f->iobase + FSPI_INTR, + FSPI_INTR_IPRXWA, 0, + POLL_TOUT, true); + WARN_ON(ret); + + *(u32 *)(buf + i) = fspi_readl(f, base + FSPI_RFDR); + *(u32 *)(buf + i + 4) = fspi_readl(f, base + FSPI_RFDR + 4); + /* move the FIFO pointer */ + fspi_writel(f, FSPI_INTR_IPRXWA, base + FSPI_INTR); + } + + if (i < len) { + u32 tmp; + int size, j; + + buf = op->data.buf.in + i; + /* Wait for RXFIFO available */ + ret = fspi_readl_poll_tout(f, f->iobase + FSPI_INTR, + FSPI_INTR_IPRXWA, 0, + POLL_TOUT, true); + WARN_ON(ret); + + len = op->data.nbytes - i; + for (j = 0; j < op->data.nbytes - i; j += 4) { + tmp = fspi_readl(f, base + FSPI_RFDR + j); + size = min(len, 4); + memcpy(buf + j, &tmp, size); + len -= size; + } + } + + /* invalid the RXFIFO */ + fspi_writel(f, FSPI_IPRXFCR_CLR, base + FSPI_IPRXFCR); + /* move the FIFO pointer */ + fspi_writel(f, FSPI_INTR_IPRXWA, base + FSPI_INTR); +} + +static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op) +{ + void __iomem *base = f->iobase; + int seqnum = 0; + int err = 0; + u32 reg; + + reg = fspi_readl(f, base + FSPI_IPRXFCR); + /* invalid RXFIFO first */ + reg &= ~FSPI_IPRXFCR_DMA_EN; + reg = reg | FSPI_IPRXFCR_CLR; + fspi_writel(f, reg, base + FSPI_IPRXFCR); + + init_completion(&f->c); + + fspi_writel(f, op->addr.val, base + FSPI_IPCR0); + /* + * Always start the sequence at the same index since we update + * the LUT at each exec_op() call. And also specify the DATA + * length, since it's has not been specified in the LUT. + */ + fspi_writel(f, op->data.nbytes | + (SEQID_LUT << FSPI_IPCR1_SEQID_SHIFT) | + (seqnum << FSPI_IPCR1_SEQNUM_SHIFT), + base + FSPI_IPCR1); + + /* Trigger the LUT now. */ + fspi_writel(f, FSPI_IPCMD_TRG, base + FSPI_IPCMD); + + /* Wait for the interrupt. */ + if (!wait_for_completion_timeout(&f->c, msecs_to_jiffies(1000))) + err = -ETIMEDOUT; + + /* Invoke IP data read, if request is of data read. */ + if (!err && op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN) + nxp_fspi_read_rxfifo(f, op); + + return err; +} + +static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) +{ + struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master); + int err = 0; + + mutex_lock(&f->lock); + + /* Wait for controller being ready. */ + err = fspi_readl_poll_tout(f, f->iobase + FSPI_STS0, + FSPI_STS0_ARB_IDLE, 1, POLL_TOUT, true); + WARN_ON(err); + + nxp_fspi_select_mem(f, mem->spi); + + nxp_fspi_prepare_lut(f, op); + /* + * If we have large chunks of data, we read them through the AHB bus + * by accessing the mapped memory. In all other cases we use + * IP commands to access the flash. + */ + if (op->data.nbytes > (f->devtype_data->rxfifo - 4) && + op->data.dir == SPI_MEM_DATA_IN) { + nxp_fspi_read_ahb(f, op); + } else { + if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) + nxp_fspi_fill_txfifo(f, op); + + err = nxp_fspi_do_op(f, op); + } + + /* Invalidate the data in the AHB buffer. */ + nxp_fspi_invalid(f); + + mutex_unlock(&f->lock); + + return err; +} + +static int nxp_fspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) +{ + struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master); + + if (op->data.dir == SPI_MEM_DATA_OUT) { + if (op->data.nbytes > f->devtype_data->txfifo) + op->data.nbytes = f->devtype_data->txfifo; + } else { + if (op->data.nbytes > f->devtype_data->ahb_buf_size) + op->data.nbytes = f->devtype_data->ahb_buf_size; + else if (op->data.nbytes > (f->devtype_data->rxfifo - 4)) + op->data.nbytes = ALIGN_DOWN(op->data.nbytes, 8); + } + + return 0; +} + +static int nxp_fspi_default_setup(struct nxp_fspi *f) +{ + void __iomem *base = f->iobase; + int ret, i; + u32 reg; + + /* disable and unprepare clock to avoid glitch pass to controller */ + nxp_fspi_clk_disable_unprep(f); + + /* the default frequency, we will change it later if necessary. */ + ret = clk_set_rate(f->clk, 20000000); + if (ret) + return ret; + + ret = nxp_fspi_clk_prep_enable(f); + if (ret) + return ret; + + /* Reset the module */ + /* w1c register, wait unit clear */ + ret = fspi_readl_poll_tout(f, f->iobase + FSPI_MCR0, + FSPI_MCR0_SWRST, 0, POLL_TOUT, false); + WARN_ON(ret); + + /* Disable the module */ + fspi_writel(f, FSPI_MCR0_MDIS, base + FSPI_MCR0); + + /* Reset the DLL register to default value */ + fspi_writel(f, FSPI_DLLACR_OVRDEN, base + FSPI_DLLACR); + fspi_writel(f, FSPI_DLLBCR_OVRDEN, base + FSPI_DLLBCR); + + /* enable module */ + fspi_writel(f, FSPI_MCR0_AHB_TIMEOUT(0xFF) | FSPI_MCR0_IP_TIMEOUT(0xFF), + base + FSPI_MCR0); + + /* + * Disable same device enable bit and configure all slave devices + * independently. + */ + reg = fspi_readl(f, f->iobase + FSPI_MCR2); + reg = reg & ~(FSPI_MCR2_SAMEDEVICEEN); + fspi_writel(f, reg, base + FSPI_MCR2); + + /* AHB configuration for access buffer 0~7. */ + for (i = 0; i < 7; i++) + fspi_writel(f, 0, base + FSPI_AHBRX_BUF0CR0 + 4 * i); + + /* + * Set ADATSZ with the maximum AHB buffer size to improve the read + * performance. + */ + fspi_writel(f, (f->devtype_data->ahb_buf_size / 8 | + FSPI_AHBRXBUF0CR7_PREF), base + FSPI_AHBRX_BUF7CR0); + + /* prefetch and no start address alignment limitation */ + fspi_writel(f, FSPI_AHBCR_PREF_EN | FSPI_AHBCR_RDADDROPT, + base + FSPI_AHBCR); + + /* AHB Read - Set lut sequence ID for all CS. */ + fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA1CR2); + fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA2CR2); + fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB1CR2); + fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB2CR2); + + f->selected = -1; + + /* enable the interrupt */ + fspi_writel(f, FSPI_INTEN_IPCMDDONE, base + FSPI_INTEN); + + return 0; +} + +static const char *nxp_fspi_get_name(struct spi_mem *mem) +{ + struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master); + struct device *dev = &mem->spi->dev; + const char *name; + + // Set custom name derived from the platform_device of the controller. + if (of_get_available_child_count(f->dev->of_node) == 1) + return dev_name(f->dev); + + name = devm_kasprintf(dev, GFP_KERNEL, + "%s-%d", dev_name(f->dev), + mem->spi->chip_select); + + if (!name) { + dev_err(dev, "failed to get memory for custom flash name\n"); + return ERR_PTR(-ENOMEM); + } + + return name; +} + +static const struct spi_controller_mem_ops nxp_fspi_mem_ops = { + .adjust_op_size = nxp_fspi_adjust_op_size, + .supports_op = nxp_fspi_supports_op, + .exec_op = nxp_fspi_exec_op, + .get_name = nxp_fspi_get_name, +}; + +static int nxp_fspi_probe(struct platform_device *pdev) +{ + struct spi_controller *ctlr; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct resource *res; + struct nxp_fspi *f; + int ret; + + ctlr = spi_alloc_master(&pdev->dev, sizeof(*f)); + if (!ctlr) + return -ENOMEM; + + ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL | + SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL; + + f = spi_controller_get_devdata(ctlr); + f->dev = dev; + f->devtype_data = of_device_get_match_data(dev); + if (!f->devtype_data) { + ret = -ENODEV; + goto err_put_ctrl; + } + + platform_set_drvdata(pdev, f); + + /* find the resources - configuration register address space */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fspi_base"); + f->iobase = devm_ioremap_resource(dev, res); + if (IS_ERR(f->iobase)) { + ret = PTR_ERR(f->iobase); + goto err_put_ctrl; + } + + /* find the resources - controller memory mapped space */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fspi_mmap"); + f->ahb_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(f->ahb_addr)) { + ret = PTR_ERR(f->ahb_addr); + goto err_put_ctrl; + } + + /* assign memory mapped starting address and mapped size. */ + f->memmap_phy = res->start; + f->memmap_phy_size = resource_size(res); + + /* find the clocks */ + f->clk_en = devm_clk_get(dev, "fspi_en"); + if (IS_ERR(f->clk_en)) { + ret = PTR_ERR(f->clk_en); + goto err_put_ctrl; + } + + f->clk = devm_clk_get(dev, "fspi"); + if (IS_ERR(f->clk)) { + ret = PTR_ERR(f->clk); + goto err_put_ctrl; + } + + ret = nxp_fspi_clk_prep_enable(f); + if (ret) { + dev_err(dev, "can not enable the clock\n"); + goto err_put_ctrl; + } + + /* find the irq */ + ret = platform_get_irq(pdev, 0); + if (ret < 0) { + dev_err(dev, "failed to get the irq: %d\n", ret); + goto err_disable_clk; + } + + ret = devm_request_irq(dev, ret, + nxp_fspi_irq_handler, 0, pdev->name, f); + if (ret) { + dev_err(dev, "failed to request irq: %d\n", ret); + goto err_disable_clk; + } + + mutex_init(&f->lock); + + ctlr->bus_num = -1; + ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT; + ctlr->mem_ops = &nxp_fspi_mem_ops; + + nxp_fspi_default_setup(f); + + ctlr->dev.of_node = np; + + ret = spi_register_controller(ctlr); + if (ret) + goto err_destroy_mutex; + + return 0; + +err_destroy_mutex: + mutex_destroy(&f->lock); + +err_disable_clk: + nxp_fspi_clk_disable_unprep(f); + +err_put_ctrl: + spi_controller_put(ctlr); + + dev_err(dev, "NXP FSPI probe failed\n"); + return ret; +} + +static int nxp_fspi_remove(struct platform_device *pdev) +{ + struct nxp_fspi *f = platform_get_drvdata(pdev); + + /* disable the hardware */ + fspi_writel(f, FSPI_MCR0_MDIS, f->iobase + FSPI_MCR0); + + nxp_fspi_clk_disable_unprep(f); + + mutex_destroy(&f->lock); + + return 0; +} + +static int nxp_fspi_suspend(struct device *dev) +{ + return 0; +} + +static int nxp_fspi_resume(struct device *dev) +{ + struct nxp_fspi *f = dev_get_drvdata(dev); + + nxp_fspi_default_setup(f); + + return 0; +} + +static const struct of_device_id nxp_fspi_dt_ids[] = { + { .compatible = "nxp,lx2160a-fspi", .data = (void *)&lx2160a_data, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, nxp_fspi_dt_ids); + +static const struct dev_pm_ops nxp_fspi_pm_ops = { + .suspend = nxp_fspi_suspend, + .resume = nxp_fspi_resume, +}; + +static struct platform_driver nxp_fspi_driver = { + .driver = { + .name = "nxp-fspi", + .of_match_table = nxp_fspi_dt_ids, + .pm = &nxp_fspi_pm_ops, + }, + .probe = nxp_fspi_probe, + .remove = nxp_fspi_remove, +}; +module_platform_driver(nxp_fspi_driver); + +MODULE_DESCRIPTION("NXP FSPI Controller Driver"); +MODULE_AUTHOR("NXP Semiconductor"); +MODULE_AUTHOR("Yogesh Narayan Gaur <yogeshnarayan.gaur@nxp.com>"); +MODULE_AUTHOR("Boris Brezillon <bbrezillon@kernel.org>"); +MODULE_AUTHOR("Frieder Schrempf <frieder.schrempf@kontron.de>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 2fd8881fcd65..8be304379628 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -623,8 +623,8 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0; cfg.src_addr_width = width; cfg.dst_addr_width = width; - cfg.src_maxburst = es; - cfg.dst_maxburst = es; + cfg.src_maxburst = 1; + cfg.dst_maxburst = 1; rx = xfer->rx_buf; tx = xfer->tx_buf; diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c index d7e4e18ec3df..1ae9af5f17ec 100644 --- a/drivers/spi/spi-pic32-sqi.c +++ b/drivers/spi/spi-pic32-sqi.c @@ -466,9 +466,9 @@ static int ring_desc_ring_alloc(struct pic32_sqi *sqi) int i; /* allocate coherent DMAable memory for hardware buffer descriptors. */ - sqi->bd = dma_zalloc_coherent(&sqi->master->dev, - sizeof(*bd) * PESQI_BD_COUNT, - &sqi->bd_dma, GFP_KERNEL); + sqi->bd = dma_alloc_coherent(&sqi->master->dev, + sizeof(*bd) * PESQI_BD_COUNT, + &sqi->bd_dma, GFP_KERNEL); if (!sqi->bd) { dev_err(&sqi->master->dev, "failed allocating dma buffer\n"); return -ENOMEM; diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 0c793e31d60f..26684178786f 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -253,6 +253,7 @@ #define STATE_RUNNING ((void *) 1) #define STATE_DONE ((void *) 2) #define STATE_ERROR ((void *) -1) +#define STATE_TIMEOUT ((void *) -2) /* * SSP State - Whether Enabled or Disabled @@ -1484,6 +1485,30 @@ err_config_dma: writew(irqflags, SSP_IMSC(pl022->virtbase)); } +static void print_current_status(struct pl022 *pl022) +{ + u32 read_cr0; + u16 read_cr1, read_dmacr, read_sr; + + if (pl022->vendor->extended_cr) + read_cr0 = readl(SSP_CR0(pl022->virtbase)); + else + read_cr0 = readw(SSP_CR0(pl022->virtbase)); + read_cr1 = readw(SSP_CR1(pl022->virtbase)); + read_dmacr = readw(SSP_DMACR(pl022->virtbase)); + read_sr = readw(SSP_SR(pl022->virtbase)); + + dev_warn(&pl022->adev->dev, "spi-pl022 CR0: %x\n", read_cr0); + dev_warn(&pl022->adev->dev, "spi-pl022 CR1: %x\n", read_cr1); + dev_warn(&pl022->adev->dev, "spi-pl022 DMACR: %x\n", read_dmacr); + dev_warn(&pl022->adev->dev, "spi-pl022 SR: %x\n", read_sr); + dev_warn(&pl022->adev->dev, + "spi-pl022 exp_fifo_level/fifodepth: %u/%d\n", + pl022->exp_fifo_level, + pl022->vendor->fifodepth); + +} + static void do_polling_transfer(struct pl022 *pl022) { struct spi_message *message = NULL; @@ -1535,7 +1560,8 @@ static void do_polling_transfer(struct pl022 *pl022) if (time_after(time, timeout)) { dev_warn(&pl022->adev->dev, "%s: timeout!\n", __func__); - message->state = STATE_ERROR; + message->state = STATE_TIMEOUT; + print_current_status(pl022); goto out; } cpu_relax(); @@ -1553,6 +1579,8 @@ out: /* Handle end of message */ if (message->state == STATE_DONE) message->status = 0; + else if (message->state == STATE_TIMEOUT) + message->status = -EAGAIN; else message->status = -EIO; diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index 2fa7f4b43492..15592598273e 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -23,7 +23,7 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data, bool error) { - struct spi_message *msg = drv_data->master->cur_msg; + struct spi_message *msg = drv_data->controller->cur_msg; /* * It is possible that one CPU is handling ROR interrupt and other @@ -59,7 +59,7 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data, msg->status = -EIO; } - spi_finalize_current_transfer(drv_data->master); + spi_finalize_current_transfer(drv_data->controller); } } @@ -74,7 +74,7 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data, struct spi_transfer *xfer) { struct chip_data *chip = - spi_get_ctldata(drv_data->master->cur_msg->spi); + spi_get_ctldata(drv_data->controller->cur_msg->spi); enum dma_slave_buswidth width; struct dma_slave_config cfg; struct dma_chan *chan; @@ -102,14 +102,14 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data, cfg.dst_maxburst = chip->dma_burst_size; sgt = &xfer->tx_sg; - chan = drv_data->master->dma_tx; + chan = drv_data->controller->dma_tx; } else { cfg.src_addr = drv_data->ssdr_physical; cfg.src_addr_width = width; cfg.src_maxburst = chip->dma_burst_size; sgt = &xfer->rx_sg; - chan = drv_data->master->dma_rx; + chan = drv_data->controller->dma_rx; } ret = dmaengine_slave_config(chan, &cfg); @@ -130,8 +130,8 @@ irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data) if (status & SSSR_ROR) { dev_err(&drv_data->pdev->dev, "FIFO overrun\n"); - dmaengine_terminate_async(drv_data->master->dma_rx); - dmaengine_terminate_async(drv_data->master->dma_tx); + dmaengine_terminate_async(drv_data->controller->dma_rx); + dmaengine_terminate_async(drv_data->controller->dma_tx); pxa2xx_spi_dma_transfer_complete(drv_data, true); return IRQ_HANDLED; @@ -171,15 +171,15 @@ int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, return 0; err_rx: - dmaengine_terminate_async(drv_data->master->dma_tx); + dmaengine_terminate_async(drv_data->controller->dma_tx); err_tx: return err; } void pxa2xx_spi_dma_start(struct driver_data *drv_data) { - dma_async_issue_pending(drv_data->master->dma_rx); - dma_async_issue_pending(drv_data->master->dma_tx); + dma_async_issue_pending(drv_data->controller->dma_rx); + dma_async_issue_pending(drv_data->controller->dma_tx); atomic_set(&drv_data->dma_running, 1); } @@ -187,30 +187,30 @@ void pxa2xx_spi_dma_start(struct driver_data *drv_data) void pxa2xx_spi_dma_stop(struct driver_data *drv_data) { atomic_set(&drv_data->dma_running, 0); - dmaengine_terminate_sync(drv_data->master->dma_rx); - dmaengine_terminate_sync(drv_data->master->dma_tx); + dmaengine_terminate_sync(drv_data->controller->dma_rx); + dmaengine_terminate_sync(drv_data->controller->dma_tx); } int pxa2xx_spi_dma_setup(struct driver_data *drv_data) { - struct pxa2xx_spi_master *pdata = drv_data->master_info; + struct pxa2xx_spi_controller *pdata = drv_data->controller_info; struct device *dev = &drv_data->pdev->dev; - struct spi_controller *master = drv_data->master; + struct spi_controller *controller = drv_data->controller; dma_cap_mask_t mask; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - master->dma_tx = dma_request_slave_channel_compat(mask, + controller->dma_tx = dma_request_slave_channel_compat(mask, pdata->dma_filter, pdata->tx_param, dev, "tx"); - if (!master->dma_tx) + if (!controller->dma_tx) return -ENODEV; - master->dma_rx = dma_request_slave_channel_compat(mask, + controller->dma_rx = dma_request_slave_channel_compat(mask, pdata->dma_filter, pdata->rx_param, dev, "rx"); - if (!master->dma_rx) { - dma_release_channel(master->dma_tx); - master->dma_tx = NULL; + if (!controller->dma_rx) { + dma_release_channel(controller->dma_tx); + controller->dma_tx = NULL; return -ENODEV; } @@ -219,17 +219,17 @@ int pxa2xx_spi_dma_setup(struct driver_data *drv_data) void pxa2xx_spi_dma_release(struct driver_data *drv_data) { - struct spi_controller *master = drv_data->master; + struct spi_controller *controller = drv_data->controller; - if (master->dma_rx) { - dmaengine_terminate_sync(master->dma_rx); - dma_release_channel(master->dma_rx); - master->dma_rx = NULL; + if (controller->dma_rx) { + dmaengine_terminate_sync(controller->dma_rx); + dma_release_channel(controller->dma_rx); + controller->dma_rx = NULL; } - if (master->dma_tx) { - dmaengine_terminate_sync(master->dma_tx); - dma_release_channel(master->dma_tx); - master->dma_tx = NULL; + if (controller->dma_tx) { + dmaengine_terminate_sync(controller->dma_tx); + dma_release_channel(controller->dma_tx); + controller->dma_tx = NULL; } } diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index 869f188b02eb..1727fdfbac28 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -197,7 +197,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, struct platform_device_info pi; int ret; struct platform_device *pdev; - struct pxa2xx_spi_master spi_pdata; + struct pxa2xx_spi_controller spi_pdata; struct ssp_device *ssp; struct pxa_spi_info *c; char buf[40]; @@ -265,7 +265,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, static void pxa2xx_spi_pci_remove(struct pci_dev *dev) { struct platform_device *pdev = pci_get_drvdata(dev); - struct pxa2xx_spi_master *spi_pdata; + struct pxa2xx_spi_controller *spi_pdata; spi_pdata = dev_get_platdata(&pdev->dev); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index d84b893a64d7..b6ddba833d02 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -328,7 +328,7 @@ static void lpss_ssp_setup(struct driver_data *drv_data) __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value); /* Enable multiblock DMA transfers */ - if (drv_data->master_info->enable_dma) { + if (drv_data->controller_info->enable_dma) { __lpss_ssp_write_priv(drv_data, config->reg_ssp, 1); if (config->reg_general >= 0) { @@ -368,7 +368,7 @@ static void lpss_ssp_select_cs(struct spi_device *spi, __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value); ndelay(1000000000 / - (drv_data->master->max_speed_hz / 2)); + (drv_data->controller->max_speed_hz / 2)); } } @@ -567,7 +567,7 @@ static int u32_reader(struct driver_data *drv_data) static void reset_sccr1(struct driver_data *drv_data) { struct chip_data *chip = - spi_get_ctldata(drv_data->master->cur_msg->spi); + spi_get_ctldata(drv_data->controller->cur_msg->spi); u32 sccr1_reg; sccr1_reg = pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1; @@ -599,8 +599,8 @@ static void int_error_stop(struct driver_data *drv_data, const char* msg) dev_err(&drv_data->pdev->dev, "%s\n", msg); - drv_data->master->cur_msg->status = -EIO; - spi_finalize_current_transfer(drv_data->master); + drv_data->controller->cur_msg->status = -EIO; + spi_finalize_current_transfer(drv_data->controller); } static void int_transfer_complete(struct driver_data *drv_data) @@ -611,7 +611,7 @@ static void int_transfer_complete(struct driver_data *drv_data) if (!pxa25x_ssp_comp(drv_data)) pxa2xx_spi_write(drv_data, SSTO, 0); - spi_finalize_current_transfer(drv_data->master); + spi_finalize_current_transfer(drv_data->controller); } static irqreturn_t interrupt_transfer(struct driver_data *drv_data) @@ -747,7 +747,7 @@ static irqreturn_t ssp_int(int irq, void *dev_id) pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg & ~drv_data->int_cr1); pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg); - if (!drv_data->master->cur_msg) { + if (!drv_data->controller->cur_msg) { handle_bad_msg(drv_data); /* Never fail */ return IRQ_HANDLED; @@ -879,7 +879,7 @@ static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds) static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate) { - unsigned long ssp_clk = drv_data->master->max_speed_hz; + unsigned long ssp_clk = drv_data->controller->max_speed_hz; const struct ssp_device *ssp = drv_data->ssp; rate = min_t(int, ssp_clk, rate); @@ -894,7 +894,7 @@ static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data, int rate) { struct chip_data *chip = - spi_get_ctldata(drv_data->master->cur_msg->spi); + spi_get_ctldata(drv_data->controller->cur_msg->spi); unsigned int clk_div; switch (drv_data->ssp_type) { @@ -908,7 +908,7 @@ static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data, return clk_div << 8; } -static bool pxa2xx_spi_can_dma(struct spi_controller *master, +static bool pxa2xx_spi_can_dma(struct spi_controller *controller, struct spi_device *spi, struct spi_transfer *xfer) { @@ -919,12 +919,12 @@ static bool pxa2xx_spi_can_dma(struct spi_controller *master, xfer->len >= chip->dma_burst_size; } -static int pxa2xx_spi_transfer_one(struct spi_controller *master, +static int pxa2xx_spi_transfer_one(struct spi_controller *controller, struct spi_device *spi, struct spi_transfer *transfer) { - struct driver_data *drv_data = spi_controller_get_devdata(master); - struct spi_message *message = master->cur_msg; + struct driver_data *drv_data = spi_controller_get_devdata(controller); + struct spi_message *message = controller->cur_msg; struct chip_data *chip = spi_get_ctldata(message->spi); u32 dma_thresh = chip->dma_threshold; u32 dma_burst = chip->dma_burst_size; @@ -1006,9 +1006,9 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *master, "DMA burst size reduced to match bits_per_word\n"); } - dma_mapped = master->can_dma && - master->can_dma(master, message->spi, transfer) && - master->cur_msg_mapped; + dma_mapped = controller->can_dma && + controller->can_dma(controller, message->spi, transfer) && + controller->cur_msg_mapped; if (dma_mapped) { /* Ensure we have the correct interrupt handler */ @@ -1036,12 +1036,12 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *master, cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits); if (!pxa25x_ssp_comp(drv_data)) dev_dbg(&message->spi->dev, "%u Hz actual, %s\n", - master->max_speed_hz + controller->max_speed_hz / (1 + ((cr0 & SSCR0_SCR(0xfff)) >> 8)), dma_mapped ? "DMA" : "PIO"); else dev_dbg(&message->spi->dev, "%u Hz actual, %s\n", - master->max_speed_hz / 2 + controller->max_speed_hz / 2 / (1 + ((cr0 & SSCR0_SCR(0x0ff)) >> 8)), dma_mapped ? "DMA" : "PIO"); @@ -1092,7 +1092,7 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *master, } } - if (spi_controller_is_slave(master)) { + if (spi_controller_is_slave(controller)) { while (drv_data->write(drv_data)) ; if (drv_data->gpiod_ready) { @@ -1111,9 +1111,9 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *master, return 1; } -static int pxa2xx_spi_slave_abort(struct spi_master *master) +static int pxa2xx_spi_slave_abort(struct spi_controller *controller) { - struct driver_data *drv_data = spi_controller_get_devdata(master); + struct driver_data *drv_data = spi_controller_get_devdata(controller); /* Stop and reset SSP */ write_SSSR_CS(drv_data, drv_data->clear_sr); @@ -1126,16 +1126,16 @@ static int pxa2xx_spi_slave_abort(struct spi_master *master) dev_dbg(&drv_data->pdev->dev, "transfer aborted\n"); - drv_data->master->cur_msg->status = -EINTR; - spi_finalize_current_transfer(drv_data->master); + drv_data->controller->cur_msg->status = -EINTR; + spi_finalize_current_transfer(drv_data->controller); return 0; } -static void pxa2xx_spi_handle_err(struct spi_controller *master, +static void pxa2xx_spi_handle_err(struct spi_controller *controller, struct spi_message *msg) { - struct driver_data *drv_data = spi_controller_get_devdata(master); + struct driver_data *drv_data = spi_controller_get_devdata(controller); /* Disable the SSP */ pxa2xx_spi_write(drv_data, SSCR0, @@ -1159,9 +1159,9 @@ static void pxa2xx_spi_handle_err(struct spi_controller *master, pxa2xx_spi_dma_stop(drv_data); } -static int pxa2xx_spi_unprepare_transfer(struct spi_controller *master) +static int pxa2xx_spi_unprepare_transfer(struct spi_controller *controller) { - struct driver_data *drv_data = spi_controller_get_devdata(master); + struct driver_data *drv_data = spi_controller_get_devdata(controller); /* Disable the SSP now */ pxa2xx_spi_write(drv_data, SSCR0, @@ -1260,7 +1260,7 @@ static int setup(struct spi_device *spi) break; default: tx_hi_thres = 0; - if (spi_controller_is_slave(drv_data->master)) { + if (spi_controller_is_slave(drv_data->controller)) { tx_thres = 1; rx_thres = 2; } else { @@ -1287,7 +1287,7 @@ static int setup(struct spi_device *spi) chip->frm = spi->chip_select; } - chip->enable_dma = drv_data->master_info->enable_dma; + chip->enable_dma = drv_data->controller_info->enable_dma; chip->timeout = TIMOUT_DFLT; } @@ -1310,7 +1310,7 @@ static int setup(struct spi_device *spi) if (chip_info->enable_loopback) chip->cr1 = SSCR1_LBM; } - if (spi_controller_is_slave(drv_data->master)) { + if (spi_controller_is_slave(drv_data->controller)) { chip->cr1 |= SSCR1_SCFR; chip->cr1 |= SSCR1_SCLKDIR; chip->cr1 |= SSCR1_SFRMDIR; @@ -1497,10 +1497,10 @@ static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param) #endif /* CONFIG_PCI */ -static struct pxa2xx_spi_master * +static struct pxa2xx_spi_controller * pxa2xx_spi_init_pdata(struct platform_device *pdev) { - struct pxa2xx_spi_master *pdata; + struct pxa2xx_spi_controller *pdata; struct acpi_device *adev; struct ssp_device *ssp; struct resource *res; @@ -1568,10 +1568,10 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev) return pdata; } -static int pxa2xx_spi_fw_translate_cs(struct spi_controller *master, +static int pxa2xx_spi_fw_translate_cs(struct spi_controller *controller, unsigned int cs) { - struct driver_data *drv_data = spi_controller_get_devdata(master); + struct driver_data *drv_data = spi_controller_get_devdata(controller); if (has_acpi_companion(&drv_data->pdev->dev)) { switch (drv_data->ssp_type) { @@ -1595,8 +1595,8 @@ static int pxa2xx_spi_fw_translate_cs(struct spi_controller *master, static int pxa2xx_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct pxa2xx_spi_master *platform_info; - struct spi_controller *master; + struct pxa2xx_spi_controller *platform_info; + struct spi_controller *controller; struct driver_data *drv_data; struct ssp_device *ssp; const struct lpss_config *config; @@ -1622,37 +1622,37 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) } if (platform_info->is_slave) - master = spi_alloc_slave(dev, sizeof(struct driver_data)); + controller = spi_alloc_slave(dev, sizeof(struct driver_data)); else - master = spi_alloc_master(dev, sizeof(struct driver_data)); + controller = spi_alloc_master(dev, sizeof(struct driver_data)); - if (!master) { - dev_err(&pdev->dev, "cannot alloc spi_master\n"); + if (!controller) { + dev_err(&pdev->dev, "cannot alloc spi_controller\n"); pxa_ssp_free(ssp); return -ENOMEM; } - drv_data = spi_controller_get_devdata(master); - drv_data->master = master; - drv_data->master_info = platform_info; + drv_data = spi_controller_get_devdata(controller); + drv_data->controller = controller; + drv_data->controller_info = platform_info; drv_data->pdev = pdev; drv_data->ssp = ssp; - master->dev.of_node = pdev->dev.of_node; + controller->dev.of_node = pdev->dev.of_node; /* the spi->mode bits understood by this driver: */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; - - master->bus_num = ssp->port_id; - master->dma_alignment = DMA_ALIGNMENT; - master->cleanup = cleanup; - master->setup = setup; - master->set_cs = pxa2xx_spi_set_cs; - master->transfer_one = pxa2xx_spi_transfer_one; - master->slave_abort = pxa2xx_spi_slave_abort; - master->handle_err = pxa2xx_spi_handle_err; - master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer; - master->fw_translate_cs = pxa2xx_spi_fw_translate_cs; - master->auto_runtime_pm = true; - master->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX; + controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; + + controller->bus_num = ssp->port_id; + controller->dma_alignment = DMA_ALIGNMENT; + controller->cleanup = cleanup; + controller->setup = setup; + controller->set_cs = pxa2xx_spi_set_cs; + controller->transfer_one = pxa2xx_spi_transfer_one; + controller->slave_abort = pxa2xx_spi_slave_abort; + controller->handle_err = pxa2xx_spi_handle_err; + controller->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer; + controller->fw_translate_cs = pxa2xx_spi_fw_translate_cs; + controller->auto_runtime_pm = true; + controller->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX; drv_data->ssp_type = ssp->type; @@ -1661,10 +1661,10 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) if (pxa25x_ssp_comp(drv_data)) { switch (drv_data->ssp_type) { case QUARK_X1000_SSP: - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); + controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); break; default: - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); + controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); break; } @@ -1673,7 +1673,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) drv_data->clear_sr = SSSR_ROR; drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR; } else { - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); + controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE; drv_data->dma_cr1 = DEFAULT_DMA_CR1; drv_data->clear_sr = SSSR_ROR | SSSR_TINT; @@ -1685,7 +1685,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) drv_data); if (status < 0) { dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq); - goto out_error_master_alloc; + goto out_error_controller_alloc; } /* Setup DMA if requested */ @@ -1695,7 +1695,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) dev_dbg(dev, "no DMA channels available, using PIO\n"); platform_info->enable_dma = false; } else { - master->can_dma = pxa2xx_spi_can_dma; + controller->can_dma = pxa2xx_spi_can_dma; + controller->max_dma_len = MAX_DMA_LEN; } } @@ -1704,7 +1705,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) if (status) goto out_error_dma_irq_alloc; - master->max_speed_hz = clk_get_rate(ssp->clk); + controller->max_speed_hz = clk_get_rate(ssp->clk); /* Load default SSP configuration */ pxa2xx_spi_write(drv_data, SSCR0, 0); @@ -1727,7 +1728,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) break; default: - if (spi_controller_is_slave(master)) { + if (spi_controller_is_slave(controller)) { tmp = SSCR1_SCFR | SSCR1_SCLKDIR | SSCR1_SFRMDIR | @@ -1740,7 +1741,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) } pxa2xx_spi_write(drv_data, SSCR1, tmp); tmp = SSCR0_Motorola | SSCR0_DataSize(8); - if (!spi_controller_is_slave(master)) + if (!spi_controller_is_slave(controller)) tmp |= SSCR0_SCR(2); pxa2xx_spi_write(drv_data, SSCR0, tmp); break; @@ -1765,24 +1766,24 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) platform_info->num_chipselect = config->cs_num; } } - master->num_chipselect = platform_info->num_chipselect; + controller->num_chipselect = platform_info->num_chipselect; count = gpiod_count(&pdev->dev, "cs"); if (count > 0) { int i; - master->num_chipselect = max_t(int, count, - master->num_chipselect); + controller->num_chipselect = max_t(int, count, + controller->num_chipselect); drv_data->cs_gpiods = devm_kcalloc(&pdev->dev, - master->num_chipselect, sizeof(struct gpio_desc *), + controller->num_chipselect, sizeof(struct gpio_desc *), GFP_KERNEL); if (!drv_data->cs_gpiods) { status = -ENOMEM; goto out_error_clock_enabled; } - for (i = 0; i < master->num_chipselect; i++) { + for (i = 0; i < controller->num_chipselect; i++) { struct gpio_desc *gpiod; gpiod = devm_gpiod_get_index(dev, "cs", i, GPIOD_ASIS); @@ -1815,9 +1816,9 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) /* Register with the SPI framework */ platform_set_drvdata(pdev, drv_data); - status = devm_spi_register_controller(&pdev->dev, master); + status = devm_spi_register_controller(&pdev->dev, controller); if (status != 0) { - dev_err(&pdev->dev, "problem registering spi master\n"); + dev_err(&pdev->dev, "problem registering spi controller\n"); goto out_error_clock_enabled; } @@ -1832,8 +1833,8 @@ out_error_dma_irq_alloc: pxa2xx_spi_dma_release(drv_data); free_irq(ssp->irq, drv_data); -out_error_master_alloc: - spi_controller_put(master); +out_error_controller_alloc: + spi_controller_put(controller); pxa_ssp_free(ssp); return status; } @@ -1854,7 +1855,7 @@ static int pxa2xx_spi_remove(struct platform_device *pdev) clk_disable_unprepare(ssp->clk); /* Release DMA */ - if (drv_data->master_info->enable_dma) + if (drv_data->controller_info->enable_dma) pxa2xx_spi_dma_release(drv_data); pm_runtime_put_noidle(&pdev->dev); @@ -1876,7 +1877,7 @@ static int pxa2xx_spi_suspend(struct device *dev) struct ssp_device *ssp = drv_data->ssp; int status; - status = spi_controller_suspend(drv_data->master); + status = spi_controller_suspend(drv_data->controller); if (status != 0) return status; pxa2xx_spi_write(drv_data, SSCR0, 0); @@ -1901,7 +1902,7 @@ static int pxa2xx_spi_resume(struct device *dev) } /* Start the queue running */ - return spi_controller_resume(drv_data->master); + return spi_controller_resume(drv_data->controller); } #endif diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h index 4e324da66ef7..aba777b4502d 100644 --- a/drivers/spi/spi-pxa2xx.h +++ b/drivers/spi/spi-pxa2xx.h @@ -31,10 +31,10 @@ struct driver_data { /* SPI framework hookup */ enum pxa_ssp_type ssp_type; - struct spi_controller *master; + struct spi_controller *controller; /* PXA hookup */ - struct pxa2xx_spi_master *master_info; + struct pxa2xx_spi_controller *controller_info; /* SSP register addresses */ void __iomem *ioaddr; diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index a4ef641b5227..556870dcdf79 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -180,7 +180,7 @@ struct rspi_data { void __iomem *addr; u32 max_speed_hz; - struct spi_master *master; + struct spi_controller *ctlr; wait_queue_head_t wait; struct clk *clk; u16 spcmd; @@ -237,8 +237,8 @@ static u16 rspi_read_data(const struct rspi_data *rspi) /* optional functions */ struct spi_ops { int (*set_config_register)(struct rspi_data *rspi, int access_size); - int (*transfer_one)(struct spi_master *master, struct spi_device *spi, - struct spi_transfer *xfer); + int (*transfer_one)(struct spi_controller *ctlr, + struct spi_device *spi, struct spi_transfer *xfer); u16 mode_bits; u16 flags; u16 fifo_size; @@ -466,7 +466,7 @@ static int rspi_data_out(struct rspi_data *rspi, u8 data) { int error = rspi_wait_for_tx_empty(rspi); if (error < 0) { - dev_err(&rspi->master->dev, "transmit timeout\n"); + dev_err(&rspi->ctlr->dev, "transmit timeout\n"); return error; } rspi_write_data(rspi, data); @@ -480,7 +480,7 @@ static int rspi_data_in(struct rspi_data *rspi) error = rspi_wait_for_rx_full(rspi); if (error < 0) { - dev_err(&rspi->master->dev, "receive timeout\n"); + dev_err(&rspi->ctlr->dev, "receive timeout\n"); return error; } data = rspi_read_data(rspi); @@ -526,8 +526,8 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, /* First prepare and submit the DMA request(s), as this may fail */ if (rx) { - desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx, - rx->sgl, rx->nents, DMA_DEV_TO_MEM, + desc_rx = dmaengine_prep_slave_sg(rspi->ctlr->dma_rx, rx->sgl, + rx->nents, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_rx) { ret = -EAGAIN; @@ -546,8 +546,8 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, } if (tx) { - desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx, - tx->sgl, tx->nents, DMA_MEM_TO_DEV, + desc_tx = dmaengine_prep_slave_sg(rspi->ctlr->dma_tx, tx->sgl, + tx->nents, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_tx) { ret = -EAGAIN; @@ -584,9 +584,9 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, /* Now start DMA */ if (rx) - dma_async_issue_pending(rspi->master->dma_rx); + dma_async_issue_pending(rspi->ctlr->dma_rx); if (tx) - dma_async_issue_pending(rspi->master->dma_tx); + dma_async_issue_pending(rspi->ctlr->dma_tx); ret = wait_event_interruptible_timeout(rspi->wait, rspi->dma_callbacked, HZ); @@ -594,13 +594,13 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, ret = 0; } else { if (!ret) { - dev_err(&rspi->master->dev, "DMA timeout\n"); + dev_err(&rspi->ctlr->dev, "DMA timeout\n"); ret = -ETIMEDOUT; } if (tx) - dmaengine_terminate_all(rspi->master->dma_tx); + dmaengine_terminate_all(rspi->ctlr->dma_tx); if (rx) - dmaengine_terminate_all(rspi->master->dma_rx); + dmaengine_terminate_all(rspi->ctlr->dma_rx); } rspi_disable_irq(rspi, irq_mask); @@ -614,12 +614,12 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, no_dma_tx: if (rx) - dmaengine_terminate_all(rspi->master->dma_rx); + dmaengine_terminate_all(rspi->ctlr->dma_rx); no_dma_rx: if (ret == -EAGAIN) { pr_warn_once("%s %s: DMA not available, falling back to PIO\n", - dev_driver_string(&rspi->master->dev), - dev_name(&rspi->master->dev)); + dev_driver_string(&rspi->ctlr->dev), + dev_name(&rspi->ctlr->dev)); } return ret; } @@ -660,10 +660,10 @@ static bool __rspi_can_dma(const struct rspi_data *rspi, return xfer->len > rspi->ops->fifo_size; } -static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi, +static bool rspi_can_dma(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *xfer) { - struct rspi_data *rspi = spi_master_get_devdata(master); + struct rspi_data *rspi = spi_controller_get_devdata(ctlr); return __rspi_can_dma(rspi, xfer); } @@ -671,7 +671,7 @@ static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi, static int rspi_dma_check_then_transfer(struct rspi_data *rspi, struct spi_transfer *xfer) { - if (!rspi->master->can_dma || !__rspi_can_dma(rspi, xfer)) + if (!rspi->ctlr->can_dma || !__rspi_can_dma(rspi, xfer)) return -EAGAIN; /* rx_buf can be NULL on RSPI on SH in TX-only Mode */ @@ -698,10 +698,10 @@ static int rspi_common_transfer(struct rspi_data *rspi, return 0; } -static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi, - struct spi_transfer *xfer) +static int rspi_transfer_one(struct spi_controller *ctlr, + struct spi_device *spi, struct spi_transfer *xfer) { - struct rspi_data *rspi = spi_master_get_devdata(master); + struct rspi_data *rspi = spi_controller_get_devdata(ctlr); u8 spcr; spcr = rspi_read8(rspi, RSPI_SPCR); @@ -716,11 +716,11 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi, return rspi_common_transfer(rspi, xfer); } -static int rspi_rz_transfer_one(struct spi_master *master, +static int rspi_rz_transfer_one(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *xfer) { - struct rspi_data *rspi = spi_master_get_devdata(master); + struct rspi_data *rspi = spi_controller_get_devdata(ctlr); rspi_rz_receive_init(rspi); @@ -739,7 +739,7 @@ static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx, if (n == QSPI_BUFFER_SIZE) { ret = rspi_wait_for_tx_empty(rspi); if (ret < 0) { - dev_err(&rspi->master->dev, "transmit timeout\n"); + dev_err(&rspi->ctlr->dev, "transmit timeout\n"); return ret; } for (i = 0; i < n; i++) @@ -747,7 +747,7 @@ static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx, ret = rspi_wait_for_rx_full(rspi); if (ret < 0) { - dev_err(&rspi->master->dev, "receive timeout\n"); + dev_err(&rspi->ctlr->dev, "receive timeout\n"); return ret; } for (i = 0; i < n; i++) @@ -785,7 +785,7 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) unsigned int i, len; int ret; - if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { + if (rspi->ctlr->can_dma && __rspi_can_dma(rspi, xfer)) { ret = rspi_dma_transfer(rspi, &xfer->tx_sg, NULL); if (ret != -EAGAIN) return ret; @@ -796,7 +796,7 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) if (len == QSPI_BUFFER_SIZE) { ret = rspi_wait_for_tx_empty(rspi); if (ret < 0) { - dev_err(&rspi->master->dev, "transmit timeout\n"); + dev_err(&rspi->ctlr->dev, "transmit timeout\n"); return ret; } for (i = 0; i < len; i++) @@ -822,7 +822,7 @@ static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) unsigned int i, len; int ret; - if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { + if (rspi->ctlr->can_dma && __rspi_can_dma(rspi, xfer)) { int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg); if (ret != -EAGAIN) return ret; @@ -833,7 +833,7 @@ static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) if (len == QSPI_BUFFER_SIZE) { ret = rspi_wait_for_rx_full(rspi); if (ret < 0) { - dev_err(&rspi->master->dev, "receive timeout\n"); + dev_err(&rspi->ctlr->dev, "receive timeout\n"); return ret; } for (i = 0; i < len; i++) @@ -849,10 +849,10 @@ static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) return 0; } -static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi, - struct spi_transfer *xfer) +static int qspi_transfer_one(struct spi_controller *ctlr, + struct spi_device *spi, struct spi_transfer *xfer) { - struct rspi_data *rspi = spi_master_get_devdata(master); + struct rspi_data *rspi = spi_controller_get_devdata(ctlr); if (spi->mode & SPI_LOOP) { return qspi_transfer_out_in(rspi, xfer); @@ -870,7 +870,7 @@ static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi, static int rspi_setup(struct spi_device *spi) { - struct rspi_data *rspi = spi_master_get_devdata(spi->master); + struct rspi_data *rspi = spi_controller_get_devdata(spi->controller); rspi->max_speed_hz = spi->max_speed_hz; @@ -955,10 +955,10 @@ static int qspi_setup_sequencer(struct rspi_data *rspi, return 0; } -static int rspi_prepare_message(struct spi_master *master, +static int rspi_prepare_message(struct spi_controller *ctlr, struct spi_message *msg) { - struct rspi_data *rspi = spi_master_get_devdata(master); + struct rspi_data *rspi = spi_controller_get_devdata(ctlr); int ret; if (msg->spi->mode & @@ -974,10 +974,10 @@ static int rspi_prepare_message(struct spi_master *master, return 0; } -static int rspi_unprepare_message(struct spi_master *master, +static int rspi_unprepare_message(struct spi_controller *ctlr, struct spi_message *msg) { - struct rspi_data *rspi = spi_master_get_devdata(master); + struct rspi_data *rspi = spi_controller_get_devdata(ctlr); /* Disable SPI function */ rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR); @@ -1081,7 +1081,7 @@ static struct dma_chan *rspi_request_dma_chan(struct device *dev, return chan; } -static int rspi_request_dma(struct device *dev, struct spi_master *master, +static int rspi_request_dma(struct device *dev, struct spi_controller *ctlr, const struct resource *res) { const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev); @@ -1099,37 +1099,37 @@ static int rspi_request_dma(struct device *dev, struct spi_master *master, return 0; } - master->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id, - res->start + RSPI_SPDR); - if (!master->dma_tx) + ctlr->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id, + res->start + RSPI_SPDR); + if (!ctlr->dma_tx) return -ENODEV; - master->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id, - res->start + RSPI_SPDR); - if (!master->dma_rx) { - dma_release_channel(master->dma_tx); - master->dma_tx = NULL; + ctlr->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id, + res->start + RSPI_SPDR); + if (!ctlr->dma_rx) { + dma_release_channel(ctlr->dma_tx); + ctlr->dma_tx = NULL; return -ENODEV; } - master->can_dma = rspi_can_dma; + ctlr->can_dma = rspi_can_dma; dev_info(dev, "DMA available"); return 0; } -static void rspi_release_dma(struct spi_master *master) +static void rspi_release_dma(struct spi_controller *ctlr) { - if (master->dma_tx) - dma_release_channel(master->dma_tx); - if (master->dma_rx) - dma_release_channel(master->dma_rx); + if (ctlr->dma_tx) + dma_release_channel(ctlr->dma_tx); + if (ctlr->dma_rx) + dma_release_channel(ctlr->dma_rx); } static int rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); - rspi_release_dma(rspi->master); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); return 0; @@ -1139,7 +1139,7 @@ static const struct spi_ops rspi_ops = { .set_config_register = rspi_set_config_register, .transfer_one = rspi_transfer_one, .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, - .flags = SPI_MASTER_MUST_TX, + .flags = SPI_CONTROLLER_MUST_TX, .fifo_size = 8, }; @@ -1147,7 +1147,7 @@ static const struct spi_ops rspi_rz_ops = { .set_config_register = rspi_rz_set_config_register, .transfer_one = rspi_rz_transfer_one, .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, - .flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX, + .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX, .fifo_size = 8, /* 8 for TX, 32 for RX */ }; @@ -1157,7 +1157,7 @@ static const struct spi_ops qspi_ops = { .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP | SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD, - .flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX, + .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX, .fifo_size = 32, }; @@ -1174,7 +1174,7 @@ static const struct of_device_id rspi_of_match[] = { MODULE_DEVICE_TABLE(of, rspi_of_match); -static int rspi_parse_dt(struct device *dev, struct spi_master *master) +static int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr) { u32 num_cs; int error; @@ -1186,12 +1186,12 @@ static int rspi_parse_dt(struct device *dev, struct spi_master *master) return error; } - master->num_chipselect = num_cs; + ctlr->num_chipselect = num_cs; return 0; } #else #define rspi_of_match NULL -static inline int rspi_parse_dt(struct device *dev, struct spi_master *master) +static inline int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr) { return -EINVAL; } @@ -1212,28 +1212,28 @@ static int rspi_request_irq(struct device *dev, unsigned int irq, static int rspi_probe(struct platform_device *pdev) { struct resource *res; - struct spi_master *master; + struct spi_controller *ctlr; struct rspi_data *rspi; int ret; const struct rspi_plat_data *rspi_pd; const struct spi_ops *ops; - master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data)); - if (master == NULL) + ctlr = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data)); + if (ctlr == NULL) return -ENOMEM; ops = of_device_get_match_data(&pdev->dev); if (ops) { - ret = rspi_parse_dt(&pdev->dev, master); + ret = rspi_parse_dt(&pdev->dev, ctlr); if (ret) goto error1; } else { ops = (struct spi_ops *)pdev->id_entry->driver_data; rspi_pd = dev_get_platdata(&pdev->dev); if (rspi_pd && rspi_pd->num_chipselect) - master->num_chipselect = rspi_pd->num_chipselect; + ctlr->num_chipselect = rspi_pd->num_chipselect; else - master->num_chipselect = 2; /* default */ + ctlr->num_chipselect = 2; /* default */ } /* ops parameter check */ @@ -1243,10 +1243,10 @@ static int rspi_probe(struct platform_device *pdev) goto error1; } - rspi = spi_master_get_devdata(master); + rspi = spi_controller_get_devdata(ctlr); platform_set_drvdata(pdev, rspi); rspi->ops = ops; - rspi->master = master; + rspi->ctlr = ctlr; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); rspi->addr = devm_ioremap_resource(&pdev->dev, res); @@ -1266,15 +1266,15 @@ static int rspi_probe(struct platform_device *pdev) init_waitqueue_head(&rspi->wait); - master->bus_num = pdev->id; - master->setup = rspi_setup; - master->auto_runtime_pm = true; - master->transfer_one = ops->transfer_one; - master->prepare_message = rspi_prepare_message; - master->unprepare_message = rspi_unprepare_message; - master->mode_bits = ops->mode_bits; - master->flags = ops->flags; - master->dev.of_node = pdev->dev.of_node; + ctlr->bus_num = pdev->id; + ctlr->setup = rspi_setup; + ctlr->auto_runtime_pm = true; + ctlr->transfer_one = ops->transfer_one; + ctlr->prepare_message = rspi_prepare_message; + ctlr->unprepare_message = rspi_unprepare_message; + ctlr->mode_bits = ops->mode_bits; + ctlr->flags = ops->flags; + ctlr->dev.of_node = pdev->dev.of_node; ret = platform_get_irq_byname(pdev, "rx"); if (ret < 0) { @@ -1311,13 +1311,13 @@ static int rspi_probe(struct platform_device *pdev) goto error2; } - ret = rspi_request_dma(&pdev->dev, master, res); + ret = rspi_request_dma(&pdev->dev, ctlr, res); if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, ctlr); if (ret < 0) { - dev_err(&pdev->dev, "spi_register_master error.\n"); + dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); goto error3; } @@ -1326,11 +1326,11 @@ static int rspi_probe(struct platform_device *pdev) return 0; error3: - rspi_release_dma(master); + rspi_release_dma(ctlr); error2: pm_runtime_disable(&pdev->dev); error1: - spi_master_put(master); + spi_controller_put(ctlr); return ret; } @@ -1349,14 +1349,14 @@ static int rspi_suspend(struct device *dev) { struct rspi_data *rspi = dev_get_drvdata(dev); - return spi_master_suspend(rspi->master); + return spi_controller_suspend(rspi->ctlr); } static int rspi_resume(struct device *dev) { struct rspi_data *rspi = dev_get_drvdata(dev); - return spi_master_resume(rspi->master); + return spi_controller_resume(rspi->ctlr); } static SIMPLE_DEV_PM_OPS(rspi_pm_ops, rspi_suspend, rspi_resume); diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index dc0926e43665..7f73f91d412a 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -35,7 +35,7 @@ struct hspi_priv { void __iomem *addr; - struct spi_master *master; + struct spi_controller *ctlr; struct device *dev; struct clk *clk; }; @@ -140,10 +140,10 @@ static void hspi_hw_setup(struct hspi_priv *hspi, hspi_write(hspi, SPSCR, 0x21); /* master mode / CS control */ } -static int hspi_transfer_one_message(struct spi_master *master, +static int hspi_transfer_one_message(struct spi_controller *ctlr, struct spi_message *msg) { - struct hspi_priv *hspi = spi_master_get_devdata(master); + struct hspi_priv *hspi = spi_controller_get_devdata(ctlr); struct spi_transfer *t; u32 tx; u32 rx; @@ -205,7 +205,7 @@ static int hspi_transfer_one_message(struct spi_master *master, ndelay(nsecs); hspi_hw_cs_disable(hspi); } - spi_finalize_current_message(master); + spi_finalize_current_message(ctlr); return ret; } @@ -213,7 +213,7 @@ static int hspi_transfer_one_message(struct spi_master *master, static int hspi_probe(struct platform_device *pdev) { struct resource *res; - struct spi_master *master; + struct spi_controller *ctlr; struct hspi_priv *hspi; struct clk *clk; int ret; @@ -225,11 +225,9 @@ static int hspi_probe(struct platform_device *pdev) return -EINVAL; } - master = spi_alloc_master(&pdev->dev, sizeof(*hspi)); - if (!master) { - dev_err(&pdev->dev, "spi_alloc_master error.\n"); + ctlr = spi_alloc_master(&pdev->dev, sizeof(*hspi)); + if (!ctlr) return -ENOMEM; - } clk = clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { @@ -238,33 +236,32 @@ static int hspi_probe(struct platform_device *pdev) goto error0; } - hspi = spi_master_get_devdata(master); + hspi = spi_controller_get_devdata(ctlr); platform_set_drvdata(pdev, hspi); /* init hspi */ - hspi->master = master; + hspi->ctlr = ctlr; hspi->dev = &pdev->dev; hspi->clk = clk; hspi->addr = devm_ioremap(hspi->dev, res->start, resource_size(res)); if (!hspi->addr) { - dev_err(&pdev->dev, "ioremap error.\n"); ret = -ENOMEM; goto error1; } pm_runtime_enable(&pdev->dev); - master->bus_num = pdev->id; - master->mode_bits = SPI_CPOL | SPI_CPHA; - master->dev.of_node = pdev->dev.of_node; - master->auto_runtime_pm = true; - master->transfer_one_message = hspi_transfer_one_message; - master->bits_per_word_mask = SPI_BPW_MASK(8); + ctlr->bus_num = pdev->id; + ctlr->mode_bits = SPI_CPOL | SPI_CPHA; + ctlr->dev.of_node = pdev->dev.of_node; + ctlr->auto_runtime_pm = true; + ctlr->transfer_one_message = hspi_transfer_one_message; + ctlr->bits_per_word_mask = SPI_BPW_MASK(8); - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, ctlr); if (ret < 0) { - dev_err(&pdev->dev, "spi_register_master error.\n"); + dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); goto error2; } @@ -275,7 +272,7 @@ static int hspi_probe(struct platform_device *pdev) error1: clk_put(clk); error0: - spi_master_put(master); + spi_controller_put(ctlr); return ret; } diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index d14b407cc800..e2eb466db10a 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * SuperH MSIOF SPI Master Interface + * SuperH MSIOF SPI Controller Interface * * Copyright (c) 2009 Magnus Damm * Copyright (C) 2014 Renesas Electronics Corporation @@ -32,14 +32,15 @@ #include <asm/unaligned.h> struct sh_msiof_chipdata { + u32 bits_per_word_mask; u16 tx_fifo_size; u16 rx_fifo_size; - u16 master_flags; + u16 ctlr_flags; u16 min_div_pow; }; struct sh_msiof_spi_priv { - struct spi_master *master; + struct spi_controller *ctlr; void __iomem *mapbase; struct clk *clk; struct platform_device *pdev; @@ -287,7 +288,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, scr = sh_msiof_spi_div_array[div_pow] | SCR_BRPS(brps); sh_msiof_write(p, TSCR, scr); - if (!(p->master->flags & SPI_MASTER_MUST_TX)) + if (!(p->ctlr->flags & SPI_CONTROLLER_MUST_TX)) sh_msiof_write(p, RSCR, scr); } @@ -351,14 +352,14 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, u32 ss, tmp |= !cs_high << MDR1_SYNCAC_SHIFT; tmp |= lsb_first << MDR1_BITLSB_SHIFT; tmp |= sh_msiof_spi_get_dtdl_and_syncdl(p); - if (spi_controller_is_slave(p->master)) { + if (spi_controller_is_slave(p->ctlr)) { sh_msiof_write(p, TMDR1, tmp | TMDR1_PCON); } else { sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON | (ss < MAX_SS ? ss : 0) << TMDR1_SYNCCH_SHIFT); } - if (p->master->flags & SPI_MASTER_MUST_TX) { + if (p->ctlr->flags & SPI_CONTROLLER_MUST_TX) { /* These bits are reserved if RX needs TX */ tmp &= ~0x0000ffff; } @@ -382,7 +383,7 @@ static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p, { u32 dr2 = MDR2_BITLEN1(bits) | MDR2_WDLEN1(words); - if (tx_buf || (p->master->flags & SPI_MASTER_MUST_TX)) + if (tx_buf || (p->ctlr->flags & SPI_CONTROLLER_MUST_TX)) sh_msiof_write(p, TMDR2, dr2); else sh_msiof_write(p, TMDR2, dr2 | MDR2_GRPMASK1); @@ -539,8 +540,9 @@ static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p, static int sh_msiof_spi_setup(struct spi_device *spi) { - struct device_node *np = spi->master->dev.of_node; - struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master); + struct device_node *np = spi->controller->dev.of_node; + struct sh_msiof_spi_priv *p = + spi_controller_get_devdata(spi->controller); u32 clr, set, tmp; if (!np) { @@ -556,7 +558,7 @@ static int sh_msiof_spi_setup(struct spi_device *spi) return 0; } - if (spi_controller_is_slave(p->master)) + if (spi_controller_is_slave(p->ctlr)) return 0; if (p->native_cs_inited && @@ -581,10 +583,10 @@ static int sh_msiof_spi_setup(struct spi_device *spi) return 0; } -static int sh_msiof_prepare_message(struct spi_master *master, +static int sh_msiof_prepare_message(struct spi_controller *ctlr, struct spi_message *msg) { - struct sh_msiof_spi_priv *p = spi_master_get_devdata(master); + struct sh_msiof_spi_priv *p = spi_controller_get_devdata(ctlr); const struct spi_device *spi = msg->spi; u32 ss, cs_high; @@ -605,7 +607,7 @@ static int sh_msiof_prepare_message(struct spi_master *master, static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) { - bool slave = spi_controller_is_slave(p->master); + bool slave = spi_controller_is_slave(p->ctlr); int ret = 0; /* setup clock and rx/tx signals */ @@ -625,7 +627,7 @@ static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf) { - bool slave = spi_controller_is_slave(p->master); + bool slave = spi_controller_is_slave(p->ctlr); int ret = 0; /* shut down frame, rx/tx and clock signals */ @@ -641,9 +643,9 @@ static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf) return ret; } -static int sh_msiof_slave_abort(struct spi_master *master) +static int sh_msiof_slave_abort(struct spi_controller *ctlr) { - struct sh_msiof_spi_priv *p = spi_master_get_devdata(master); + struct sh_msiof_spi_priv *p = spi_controller_get_devdata(ctlr); p->slave_aborted = true; complete(&p->done); @@ -654,7 +656,7 @@ static int sh_msiof_slave_abort(struct spi_master *master) static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p, struct completion *x) { - if (spi_controller_is_slave(p->master)) { + if (spi_controller_is_slave(p->ctlr)) { if (wait_for_completion_interruptible(x) || p->slave_aborted) { dev_dbg(&p->pdev->dev, "interrupted\n"); @@ -754,7 +756,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, /* First prepare and submit the DMA request(s), as this may fail */ if (rx) { ier_bits |= IER_RDREQE | IER_RDMAE; - desc_rx = dmaengine_prep_slave_single(p->master->dma_rx, + desc_rx = dmaengine_prep_slave_single(p->ctlr->dma_rx, p->rx_dma_addr, len, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_rx) @@ -769,9 +771,9 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, if (tx) { ier_bits |= IER_TDREQE | IER_TDMAE; - dma_sync_single_for_device(p->master->dma_tx->device->dev, + dma_sync_single_for_device(p->ctlr->dma_tx->device->dev, p->tx_dma_addr, len, DMA_TO_DEVICE); - desc_tx = dmaengine_prep_slave_single(p->master->dma_tx, + desc_tx = dmaengine_prep_slave_single(p->ctlr->dma_tx, p->tx_dma_addr, len, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_tx) { @@ -803,9 +805,9 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, /* Now start DMA */ if (rx) - dma_async_issue_pending(p->master->dma_rx); + dma_async_issue_pending(p->ctlr->dma_rx); if (tx) - dma_async_issue_pending(p->master->dma_tx); + dma_async_issue_pending(p->ctlr->dma_tx); ret = sh_msiof_spi_start(p, rx); if (ret) { @@ -845,9 +847,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, } if (rx) - dma_sync_single_for_cpu(p->master->dma_rx->device->dev, - p->rx_dma_addr, len, - DMA_FROM_DEVICE); + dma_sync_single_for_cpu(p->ctlr->dma_rx->device->dev, + p->rx_dma_addr, len, DMA_FROM_DEVICE); return 0; @@ -856,10 +857,10 @@ stop_reset: sh_msiof_spi_stop(p, rx); stop_dma: if (tx) - dmaengine_terminate_all(p->master->dma_tx); + dmaengine_terminate_all(p->ctlr->dma_tx); no_dma_tx: if (rx) - dmaengine_terminate_all(p->master->dma_rx); + dmaengine_terminate_all(p->ctlr->dma_rx); sh_msiof_write(p, IER, 0); return ret; } @@ -907,11 +908,11 @@ static void copy_plain32(u32 *dst, const u32 *src, unsigned int words) memcpy(dst, src, words * 4); } -static int sh_msiof_transfer_one(struct spi_master *master, +static int sh_msiof_transfer_one(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *t) { - struct sh_msiof_spi_priv *p = spi_master_get_devdata(master); + struct sh_msiof_spi_priv *p = spi_controller_get_devdata(ctlr); void (*copy32)(u32 *, const u32 *, unsigned int); void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int); void (*rx_fifo)(struct sh_msiof_spi_priv *, void *, int, int); @@ -926,10 +927,10 @@ static int sh_msiof_transfer_one(struct spi_master *master, int ret; /* setup clocks (clock already enabled in chipselect()) */ - if (!spi_controller_is_slave(p->master)) + if (!spi_controller_is_slave(p->ctlr)) sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz); - while (master->dma_tx && len > 15) { + while (ctlr->dma_tx && len > 15) { /* * DMA supports 32-bit words only, hence pack 8-bit and 16-bit * words, with byte resp. word swapping. @@ -937,17 +938,13 @@ static int sh_msiof_transfer_one(struct spi_master *master, unsigned int l = 0; if (tx_buf) - l = min(len, p->tx_fifo_size * 4); + l = min(round_down(len, 4), p->tx_fifo_size * 4); if (rx_buf) - l = min(len, p->rx_fifo_size * 4); + l = min(round_down(len, 4), p->rx_fifo_size * 4); if (bits <= 8) { - if (l & 3) - break; copy32 = copy_bswap32; } else if (bits <= 16) { - if (l & 3) - break; copy32 = copy_wswap32; } else { copy32 = copy_plain32; @@ -1052,23 +1049,28 @@ static int sh_msiof_transfer_one(struct spi_master *master, } static const struct sh_msiof_chipdata sh_data = { + .bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32), .tx_fifo_size = 64, .rx_fifo_size = 64, - .master_flags = 0, + .ctlr_flags = 0, .min_div_pow = 0, }; static const struct sh_msiof_chipdata rcar_gen2_data = { + .bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16) | + SPI_BPW_MASK(24) | SPI_BPW_MASK(32), .tx_fifo_size = 64, .rx_fifo_size = 64, - .master_flags = SPI_MASTER_MUST_TX, + .ctlr_flags = SPI_CONTROLLER_MUST_TX, .min_div_pow = 0, }; static const struct sh_msiof_chipdata rcar_gen3_data = { + .bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16) | + SPI_BPW_MASK(24) | SPI_BPW_MASK(32), .tx_fifo_size = 64, .rx_fifo_size = 64, - .master_flags = SPI_MASTER_MUST_TX, + .ctlr_flags = SPI_CONTROLLER_MUST_TX, .min_div_pow = 1, }; @@ -1136,7 +1138,7 @@ static int sh_msiof_get_cs_gpios(struct sh_msiof_spi_priv *p) if (ret <= 0) return 0; - num_cs = max_t(unsigned int, ret, p->master->num_chipselect); + num_cs = max_t(unsigned int, ret, p->ctlr->num_chipselect); for (i = 0; i < num_cs; i++) { struct gpio_desc *gpiod; @@ -1206,10 +1208,10 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p) { struct platform_device *pdev = p->pdev; struct device *dev = &pdev->dev; - const struct sh_msiof_spi_info *info = dev_get_platdata(dev); + const struct sh_msiof_spi_info *info = p->info; unsigned int dma_tx_id, dma_rx_id; const struct resource *res; - struct spi_master *master; + struct spi_controller *ctlr; struct device *tx_dev, *rx_dev; if (dev->of_node) { @@ -1229,17 +1231,15 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p) if (!res) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - master = p->master; - master->dma_tx = sh_msiof_request_dma_chan(dev, DMA_MEM_TO_DEV, - dma_tx_id, - res->start + TFDR); - if (!master->dma_tx) + ctlr = p->ctlr; + ctlr->dma_tx = sh_msiof_request_dma_chan(dev, DMA_MEM_TO_DEV, + dma_tx_id, res->start + TFDR); + if (!ctlr->dma_tx) return -ENODEV; - master->dma_rx = sh_msiof_request_dma_chan(dev, DMA_DEV_TO_MEM, - dma_rx_id, - res->start + RFDR); - if (!master->dma_rx) + ctlr->dma_rx = sh_msiof_request_dma_chan(dev, DMA_DEV_TO_MEM, + dma_rx_id, res->start + RFDR); + if (!ctlr->dma_rx) goto free_tx_chan; p->tx_dma_page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); @@ -1250,13 +1250,13 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p) if (!p->rx_dma_page) goto free_tx_page; - tx_dev = master->dma_tx->device->dev; + tx_dev = ctlr->dma_tx->device->dev; p->tx_dma_addr = dma_map_single(tx_dev, p->tx_dma_page, PAGE_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(tx_dev, p->tx_dma_addr)) goto free_rx_page; - rx_dev = master->dma_rx->device->dev; + rx_dev = ctlr->dma_rx->device->dev; p->rx_dma_addr = dma_map_single(rx_dev, p->rx_dma_page, PAGE_SIZE, DMA_FROM_DEVICE); if (dma_mapping_error(rx_dev, p->rx_dma_addr)) @@ -1272,34 +1272,34 @@ free_rx_page: free_tx_page: free_page((unsigned long)p->tx_dma_page); free_rx_chan: - dma_release_channel(master->dma_rx); + dma_release_channel(ctlr->dma_rx); free_tx_chan: - dma_release_channel(master->dma_tx); - master->dma_tx = NULL; + dma_release_channel(ctlr->dma_tx); + ctlr->dma_tx = NULL; return -ENODEV; } static void sh_msiof_release_dma(struct sh_msiof_spi_priv *p) { - struct spi_master *master = p->master; + struct spi_controller *ctlr = p->ctlr; - if (!master->dma_tx) + if (!ctlr->dma_tx) return; - dma_unmap_single(master->dma_rx->device->dev, p->rx_dma_addr, - PAGE_SIZE, DMA_FROM_DEVICE); - dma_unmap_single(master->dma_tx->device->dev, p->tx_dma_addr, - PAGE_SIZE, DMA_TO_DEVICE); + dma_unmap_single(ctlr->dma_rx->device->dev, p->rx_dma_addr, PAGE_SIZE, + DMA_FROM_DEVICE); + dma_unmap_single(ctlr->dma_tx->device->dev, p->tx_dma_addr, PAGE_SIZE, + DMA_TO_DEVICE); free_page((unsigned long)p->rx_dma_page); free_page((unsigned long)p->tx_dma_page); - dma_release_channel(master->dma_rx); - dma_release_channel(master->dma_tx); + dma_release_channel(ctlr->dma_rx); + dma_release_channel(ctlr->dma_tx); } static int sh_msiof_spi_probe(struct platform_device *pdev) { struct resource *r; - struct spi_master *master; + struct spi_controller *ctlr; const struct sh_msiof_chipdata *chipdata; struct sh_msiof_spi_info *info; struct sh_msiof_spi_priv *p; @@ -1320,18 +1320,18 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) } if (info->mode == MSIOF_SPI_SLAVE) - master = spi_alloc_slave(&pdev->dev, - sizeof(struct sh_msiof_spi_priv)); + ctlr = spi_alloc_slave(&pdev->dev, + sizeof(struct sh_msiof_spi_priv)); else - master = spi_alloc_master(&pdev->dev, - sizeof(struct sh_msiof_spi_priv)); - if (master == NULL) + ctlr = spi_alloc_master(&pdev->dev, + sizeof(struct sh_msiof_spi_priv)); + if (ctlr == NULL) return -ENOMEM; - p = spi_master_get_devdata(master); + p = spi_controller_get_devdata(ctlr); platform_set_drvdata(pdev, p); - p->master = master; + p->ctlr = ctlr; p->info = info; p->min_div_pow = chipdata->min_div_pow; @@ -1378,31 +1378,31 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) p->rx_fifo_size = p->info->rx_fifo_override; /* Setup GPIO chip selects */ - master->num_chipselect = p->info->num_chipselect; + ctlr->num_chipselect = p->info->num_chipselect; ret = sh_msiof_get_cs_gpios(p); if (ret) goto err1; - /* init master code */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE; - master->flags = chipdata->master_flags; - master->bus_num = pdev->id; - master->dev.of_node = pdev->dev.of_node; - master->setup = sh_msiof_spi_setup; - master->prepare_message = sh_msiof_prepare_message; - master->slave_abort = sh_msiof_slave_abort; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); - master->auto_runtime_pm = true; - master->transfer_one = sh_msiof_transfer_one; + /* init controller code */ + ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + ctlr->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE; + ctlr->flags = chipdata->ctlr_flags; + ctlr->bus_num = pdev->id; + ctlr->dev.of_node = pdev->dev.of_node; + ctlr->setup = sh_msiof_spi_setup; + ctlr->prepare_message = sh_msiof_prepare_message; + ctlr->slave_abort = sh_msiof_slave_abort; + ctlr->bits_per_word_mask = chipdata->bits_per_word_mask; + ctlr->auto_runtime_pm = true; + ctlr->transfer_one = sh_msiof_transfer_one; ret = sh_msiof_request_dma(p); if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, ctlr); if (ret < 0) { - dev_err(&pdev->dev, "spi_register_master error.\n"); + dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); goto err2; } @@ -1412,7 +1412,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) sh_msiof_release_dma(p); pm_runtime_disable(&pdev->dev); err1: - spi_master_put(master); + spi_controller_put(ctlr); return ret; } @@ -1436,14 +1436,14 @@ static int sh_msiof_spi_suspend(struct device *dev) { struct sh_msiof_spi_priv *p = dev_get_drvdata(dev); - return spi_master_suspend(p->master); + return spi_controller_suspend(p->ctlr); } static int sh_msiof_spi_resume(struct device *dev) { struct sh_msiof_spi_priv *p = dev_get_drvdata(dev); - return spi_master_resume(p->master); + return spi_controller_resume(p->ctlr); } static SIMPLE_DEV_PM_OPS(sh_msiof_spi_pm_ops, sh_msiof_spi_suspend, @@ -1465,7 +1465,7 @@ static struct platform_driver sh_msiof_spi_drv = { }; module_platform_driver(sh_msiof_spi_drv); -MODULE_DESCRIPTION("SuperH MSIOF SPI Master Interface Driver"); +MODULE_DESCRIPTION("SuperH MSIOF SPI Controller Interface Driver"); MODULE_AUTHOR("Magnus Damm"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:spi_sh_msiof"); diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c new file mode 100644 index 000000000000..93ec2c6cdbfd --- /dev/null +++ b/drivers/spi/spi-sifive.c @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2018 SiFive, Inc. +// +// SiFive SPI controller driver (master mode only) +// +// Author: SiFive, Inc. +// sifive@sifive.com + +#include <linux/clk.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <linux/io.h> +#include <linux/log2.h> + +#define SIFIVE_SPI_DRIVER_NAME "sifive_spi" + +#define SIFIVE_SPI_MAX_CS 32 +#define SIFIVE_SPI_DEFAULT_DEPTH 8 +#define SIFIVE_SPI_DEFAULT_MAX_BITS 8 + +/* register offsets */ +#define SIFIVE_SPI_REG_SCKDIV 0x00 /* Serial clock divisor */ +#define SIFIVE_SPI_REG_SCKMODE 0x04 /* Serial clock mode */ +#define SIFIVE_SPI_REG_CSID 0x10 /* Chip select ID */ +#define SIFIVE_SPI_REG_CSDEF 0x14 /* Chip select default */ +#define SIFIVE_SPI_REG_CSMODE 0x18 /* Chip select mode */ +#define SIFIVE_SPI_REG_DELAY0 0x28 /* Delay control 0 */ +#define SIFIVE_SPI_REG_DELAY1 0x2c /* Delay control 1 */ +#define SIFIVE_SPI_REG_FMT 0x40 /* Frame format */ +#define SIFIVE_SPI_REG_TXDATA 0x48 /* Tx FIFO data */ +#define SIFIVE_SPI_REG_RXDATA 0x4c /* Rx FIFO data */ +#define SIFIVE_SPI_REG_TXMARK 0x50 /* Tx FIFO watermark */ +#define SIFIVE_SPI_REG_RXMARK 0x54 /* Rx FIFO watermark */ +#define SIFIVE_SPI_REG_FCTRL 0x60 /* SPI flash interface control */ +#define SIFIVE_SPI_REG_FFMT 0x64 /* SPI flash instruction format */ +#define SIFIVE_SPI_REG_IE 0x70 /* Interrupt Enable Register */ +#define SIFIVE_SPI_REG_IP 0x74 /* Interrupt Pendings Register */ + +/* sckdiv bits */ +#define SIFIVE_SPI_SCKDIV_DIV_MASK 0xfffU + +/* sckmode bits */ +#define SIFIVE_SPI_SCKMODE_PHA BIT(0) +#define SIFIVE_SPI_SCKMODE_POL BIT(1) +#define SIFIVE_SPI_SCKMODE_MODE_MASK (SIFIVE_SPI_SCKMODE_PHA | \ + SIFIVE_SPI_SCKMODE_POL) + +/* csmode bits */ +#define SIFIVE_SPI_CSMODE_MODE_AUTO 0U +#define SIFIVE_SPI_CSMODE_MODE_HOLD 2U +#define SIFIVE_SPI_CSMODE_MODE_OFF 3U + +/* delay0 bits */ +#define SIFIVE_SPI_DELAY0_CSSCK(x) ((u32)(x)) +#define SIFIVE_SPI_DELAY0_CSSCK_MASK 0xffU +#define SIFIVE_SPI_DELAY0_SCKCS(x) ((u32)(x) << 16) +#define SIFIVE_SPI_DELAY0_SCKCS_MASK (0xffU << 16) + +/* delay1 bits */ +#define SIFIVE_SPI_DELAY1_INTERCS(x) ((u32)(x)) +#define SIFIVE_SPI_DELAY1_INTERCS_MASK 0xffU +#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((u32)(x) << 16) +#define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16) + +/* fmt bits */ +#define SIFIVE_SPI_FMT_PROTO_SINGLE 0U +#define SIFIVE_SPI_FMT_PROTO_DUAL 1U +#define SIFIVE_SPI_FMT_PROTO_QUAD 2U +#define SIFIVE_SPI_FMT_PROTO_MASK 3U +#define SIFIVE_SPI_FMT_ENDIAN BIT(2) +#define SIFIVE_SPI_FMT_DIR BIT(3) +#define SIFIVE_SPI_FMT_LEN(x) ((u32)(x) << 16) +#define SIFIVE_SPI_FMT_LEN_MASK (0xfU << 16) + +/* txdata bits */ +#define SIFIVE_SPI_TXDATA_DATA_MASK 0xffU +#define SIFIVE_SPI_TXDATA_FULL BIT(31) + +/* rxdata bits */ +#define SIFIVE_SPI_RXDATA_DATA_MASK 0xffU +#define SIFIVE_SPI_RXDATA_EMPTY BIT(31) + +/* ie and ip bits */ +#define SIFIVE_SPI_IP_TXWM BIT(0) +#define SIFIVE_SPI_IP_RXWM BIT(1) + +struct sifive_spi { + void __iomem *regs; /* virt. address of control registers */ + struct clk *clk; /* bus clock */ + unsigned int fifo_depth; /* fifo depth in words */ + u32 cs_inactive; /* level of the CS pins when inactive */ + struct completion done; /* wake-up from interrupt */ +}; + +static void sifive_spi_write(struct sifive_spi *spi, int offset, u32 value) +{ + iowrite32(value, spi->regs + offset); +} + +static u32 sifive_spi_read(struct sifive_spi *spi, int offset) +{ + return ioread32(spi->regs + offset); +} + +static void sifive_spi_init(struct sifive_spi *spi) +{ + /* Watermark interrupts are disabled by default */ + sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0); + + /* Default watermark FIFO threshold values */ + sifive_spi_write(spi, SIFIVE_SPI_REG_TXMARK, 1); + sifive_spi_write(spi, SIFIVE_SPI_REG_RXMARK, 0); + + /* Set CS/SCK Delays and Inactive Time to defaults */ + sifive_spi_write(spi, SIFIVE_SPI_REG_DELAY0, + SIFIVE_SPI_DELAY0_CSSCK(1) | + SIFIVE_SPI_DELAY0_SCKCS(1)); + sifive_spi_write(spi, SIFIVE_SPI_REG_DELAY1, + SIFIVE_SPI_DELAY1_INTERCS(1) | + SIFIVE_SPI_DELAY1_INTERXFR(0)); + + /* Exit specialized memory-mapped SPI flash mode */ + sifive_spi_write(spi, SIFIVE_SPI_REG_FCTRL, 0); +} + +static int +sifive_spi_prepare_message(struct spi_master *master, struct spi_message *msg) +{ + struct sifive_spi *spi = spi_master_get_devdata(master); + struct spi_device *device = msg->spi; + + /* Update the chip select polarity */ + if (device->mode & SPI_CS_HIGH) + spi->cs_inactive &= ~BIT(device->chip_select); + else + spi->cs_inactive |= BIT(device->chip_select); + sifive_spi_write(spi, SIFIVE_SPI_REG_CSDEF, spi->cs_inactive); + + /* Select the correct device */ + sifive_spi_write(spi, SIFIVE_SPI_REG_CSID, device->chip_select); + + /* Set clock mode */ + sifive_spi_write(spi, SIFIVE_SPI_REG_SCKMODE, + device->mode & SIFIVE_SPI_SCKMODE_MODE_MASK); + + return 0; +} + +static void sifive_spi_set_cs(struct spi_device *device, bool is_high) +{ + struct sifive_spi *spi = spi_master_get_devdata(device->master); + + /* Reverse polarity is handled by SCMR/CPOL. Not inverted CS. */ + if (device->mode & SPI_CS_HIGH) + is_high = !is_high; + + sifive_spi_write(spi, SIFIVE_SPI_REG_CSMODE, is_high ? + SIFIVE_SPI_CSMODE_MODE_AUTO : + SIFIVE_SPI_CSMODE_MODE_HOLD); +} + +static int +sifive_spi_prep_transfer(struct sifive_spi *spi, struct spi_device *device, + struct spi_transfer *t) +{ + u32 cr; + unsigned int mode; + + /* Calculate and program the clock rate */ + cr = DIV_ROUND_UP(clk_get_rate(spi->clk) >> 1, t->speed_hz) - 1; + cr &= SIFIVE_SPI_SCKDIV_DIV_MASK; + sifive_spi_write(spi, SIFIVE_SPI_REG_SCKDIV, cr); + + mode = max_t(unsigned int, t->rx_nbits, t->tx_nbits); + + /* Set frame format */ + cr = SIFIVE_SPI_FMT_LEN(t->bits_per_word); + switch (mode) { + case SPI_NBITS_QUAD: + cr |= SIFIVE_SPI_FMT_PROTO_QUAD; + break; + case SPI_NBITS_DUAL: + cr |= SIFIVE_SPI_FMT_PROTO_DUAL; + break; + default: + cr |= SIFIVE_SPI_FMT_PROTO_SINGLE; + break; + } + if (device->mode & SPI_LSB_FIRST) + cr |= SIFIVE_SPI_FMT_ENDIAN; + if (!t->rx_buf) + cr |= SIFIVE_SPI_FMT_DIR; + sifive_spi_write(spi, SIFIVE_SPI_REG_FMT, cr); + + /* We will want to poll if the time we need to wait is + * less than the context switching time. + * Let's call that threshold 5us. The operation will take: + * (8/mode) * fifo_depth / hz <= 5 * 10^-6 + * 1600000 * fifo_depth <= hz * mode + */ + return 1600000 * spi->fifo_depth <= t->speed_hz * mode; +} + +static irqreturn_t sifive_spi_irq(int irq, void *dev_id) +{ + struct sifive_spi *spi = dev_id; + u32 ip = sifive_spi_read(spi, SIFIVE_SPI_REG_IP); + + if (ip & (SIFIVE_SPI_IP_TXWM | SIFIVE_SPI_IP_RXWM)) { + /* Disable interrupts until next transfer */ + sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0); + complete(&spi->done); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static void sifive_spi_wait(struct sifive_spi *spi, u32 bit, int poll) +{ + if (poll) { + u32 cr; + + do { + cr = sifive_spi_read(spi, SIFIVE_SPI_REG_IP); + } while (!(cr & bit)); + } else { + reinit_completion(&spi->done); + sifive_spi_write(spi, SIFIVE_SPI_REG_IE, bit); + wait_for_completion(&spi->done); + } +} + +static void sifive_spi_tx(struct sifive_spi *spi, const u8 *tx_ptr) +{ + WARN_ON_ONCE((sifive_spi_read(spi, SIFIVE_SPI_REG_TXDATA) + & SIFIVE_SPI_TXDATA_FULL) != 0); + sifive_spi_write(spi, SIFIVE_SPI_REG_TXDATA, + *tx_ptr & SIFIVE_SPI_TXDATA_DATA_MASK); +} + +static void sifive_spi_rx(struct sifive_spi *spi, u8 *rx_ptr) +{ + u32 data = sifive_spi_read(spi, SIFIVE_SPI_REG_RXDATA); + + WARN_ON_ONCE((data & SIFIVE_SPI_RXDATA_EMPTY) != 0); + *rx_ptr = data & SIFIVE_SPI_RXDATA_DATA_MASK; +} + +static int +sifive_spi_transfer_one(struct spi_master *master, struct spi_device *device, + struct spi_transfer *t) +{ + struct sifive_spi *spi = spi_master_get_devdata(master); + int poll = sifive_spi_prep_transfer(spi, device, t); + const u8 *tx_ptr = t->tx_buf; + u8 *rx_ptr = t->rx_buf; + unsigned int remaining_words = t->len; + + while (remaining_words) { + unsigned int n_words = min(remaining_words, spi->fifo_depth); + unsigned int i; + + /* Enqueue n_words for transmission */ + for (i = 0; i < n_words; i++) + sifive_spi_tx(spi, tx_ptr++); + + if (rx_ptr) { + /* Wait for transmission + reception to complete */ + sifive_spi_write(spi, SIFIVE_SPI_REG_RXMARK, + n_words - 1); + sifive_spi_wait(spi, SIFIVE_SPI_IP_RXWM, poll); + + /* Read out all the data from the RX FIFO */ + for (i = 0; i < n_words; i++) + sifive_spi_rx(spi, rx_ptr++); + } else { + /* Wait for transmission to complete */ + sifive_spi_wait(spi, SIFIVE_SPI_IP_TXWM, poll); + } + + remaining_words -= n_words; + } + + return 0; +} + +static int sifive_spi_probe(struct platform_device *pdev) +{ + struct sifive_spi *spi; + struct resource *res; + int ret, irq, num_cs; + u32 cs_bits, max_bits_per_word; + struct spi_master *master; + + master = spi_alloc_master(&pdev->dev, sizeof(struct sifive_spi)); + if (!master) { + dev_err(&pdev->dev, "out of memory\n"); + return -ENOMEM; + } + + spi = spi_master_get_devdata(master); + init_completion(&spi->done); + platform_set_drvdata(pdev, master); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + spi->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(spi->regs)) { + ret = PTR_ERR(spi->regs); + goto put_master; + } + + spi->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(spi->clk)) { + dev_err(&pdev->dev, "Unable to find bus clock\n"); + ret = PTR_ERR(spi->clk); + goto put_master; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "Unable to find interrupt\n"); + ret = irq; + goto put_master; + } + + /* Optional parameters */ + ret = + of_property_read_u32(pdev->dev.of_node, "sifive,fifo-depth", + &spi->fifo_depth); + if (ret < 0) + spi->fifo_depth = SIFIVE_SPI_DEFAULT_DEPTH; + + ret = + of_property_read_u32(pdev->dev.of_node, "sifive,max-bits-per-word", + &max_bits_per_word); + + if (!ret && max_bits_per_word < 8) { + dev_err(&pdev->dev, "Only 8bit SPI words supported by the driver\n"); + ret = -EINVAL; + goto put_master; + } + + /* Spin up the bus clock before hitting registers */ + ret = clk_prepare_enable(spi->clk); + if (ret) { + dev_err(&pdev->dev, "Unable to enable bus clock\n"); + goto put_master; + } + + /* probe the number of CS lines */ + spi->cs_inactive = sifive_spi_read(spi, SIFIVE_SPI_REG_CSDEF); + sifive_spi_write(spi, SIFIVE_SPI_REG_CSDEF, 0xffffffffU); + cs_bits = sifive_spi_read(spi, SIFIVE_SPI_REG_CSDEF); + sifive_spi_write(spi, SIFIVE_SPI_REG_CSDEF, spi->cs_inactive); + if (!cs_bits) { + dev_err(&pdev->dev, "Could not auto probe CS lines\n"); + ret = -EINVAL; + goto put_master; + } + + num_cs = ilog2(cs_bits) + 1; + if (num_cs > SIFIVE_SPI_MAX_CS) { + dev_err(&pdev->dev, "Invalid number of spi slaves\n"); + ret = -EINVAL; + goto put_master; + } + + /* Define our master */ + master->dev.of_node = pdev->dev.of_node; + master->bus_num = pdev->id; + master->num_chipselect = num_cs; + master->mode_bits = SPI_CPHA | SPI_CPOL + | SPI_CS_HIGH | SPI_LSB_FIRST + | SPI_TX_DUAL | SPI_TX_QUAD + | SPI_RX_DUAL | SPI_RX_QUAD; + /* TODO: add driver support for bits_per_word < 8 + * we need to "left-align" the bits (unless SPI_LSB_FIRST) + */ + master->bits_per_word_mask = SPI_BPW_MASK(8); + master->flags = SPI_CONTROLLER_MUST_TX | SPI_MASTER_GPIO_SS; + master->prepare_message = sifive_spi_prepare_message; + master->set_cs = sifive_spi_set_cs; + master->transfer_one = sifive_spi_transfer_one; + + pdev->dev.dma_mask = NULL; + /* Configure the SPI master hardware */ + sifive_spi_init(spi); + + /* Register for SPI Interrupt */ + ret = devm_request_irq(&pdev->dev, irq, sifive_spi_irq, 0, + dev_name(&pdev->dev), spi); + if (ret) { + dev_err(&pdev->dev, "Unable to bind to interrupt\n"); + goto put_master; + } + + dev_info(&pdev->dev, "mapped; irq=%d, cs=%d\n", + irq, master->num_chipselect); + + ret = devm_spi_register_master(&pdev->dev, master); + if (ret < 0) { + dev_err(&pdev->dev, "spi_register_master failed\n"); + goto put_master; + } + + return 0; + +put_master: + spi_master_put(master); + + return ret; +} + +static int sifive_spi_remove(struct platform_device *pdev) +{ + struct spi_master *master = platform_get_drvdata(pdev); + struct sifive_spi *spi = spi_master_get_devdata(master); + + /* Disable all the interrupts just in case */ + sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0); + + return 0; +} + +static const struct of_device_id sifive_spi_of_match[] = { + { .compatible = "sifive,spi0", }, + {} +}; +MODULE_DEVICE_TABLE(of, sifive_spi_of_match); + +static struct platform_driver sifive_spi_driver = { + .probe = sifive_spi_probe, + .remove = sifive_spi_remove, + .driver = { + .name = SIFIVE_SPI_DRIVER_NAME, + .of_match_table = sifive_spi_of_match, + }, +}; +module_platform_driver(sifive_spi_driver); + +MODULE_AUTHOR("SiFive, Inc. <sifive@sifive.com>"); +MODULE_DESCRIPTION("SiFive SPI driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c index 8daa24eec624..1b7eebb72c07 100644 --- a/drivers/spi/spi-sprd.c +++ b/drivers/spi/spi-sprd.c @@ -2,6 +2,9 @@ // Copyright (C) 2018 Spreadtrum Communications Inc. #include <linux/clk.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> +#include <linux/dma/sprd-dma.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/iopoll.h> @@ -9,6 +12,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/of_dma.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/spi/spi.h> @@ -128,11 +132,28 @@ #define SPRD_SPI_DEFAULT_SOURCE 26000000 #define SPRD_SPI_MAX_SPEED_HZ 48000000 #define SPRD_SPI_AUTOSUSPEND_DELAY 100 +#define SPRD_SPI_DMA_STEP 8 + +enum sprd_spi_dma_channel { + SPRD_SPI_RX, + SPRD_SPI_TX, + SPRD_SPI_MAX, +}; + +struct sprd_spi_dma { + bool enable; + struct dma_chan *dma_chan[SPRD_SPI_MAX]; + enum dma_slave_buswidth width; + u32 fragmens_len; + u32 rx_len; +}; struct sprd_spi { void __iomem *base; + phys_addr_t phy_base; struct device *dev; struct clk *clk; + int irq; u32 src_clk; u32 hw_mode; u32 trans_len; @@ -141,6 +162,8 @@ struct sprd_spi { u32 hw_speed_hz; u32 len; int status; + struct sprd_spi_dma dma; + struct completion xfer_completion; const void *tx_buf; void *rx_buf; int (*read_bufs)(struct sprd_spi *ss, u32 len); @@ -380,7 +403,7 @@ static int sprd_spi_txrx_bufs(struct spi_device *sdev, struct spi_transfer *t) { struct sprd_spi *ss = spi_controller_get_devdata(sdev->controller); u32 trans_len = ss->trans_len, len; - int ret, write_size = 0; + int ret, write_size = 0, read_size = 0; while (trans_len) { len = trans_len > SPRD_SPI_FIFO_SIZE ? SPRD_SPI_FIFO_SIZE : @@ -416,19 +439,223 @@ static int sprd_spi_txrx_bufs(struct spi_device *sdev, struct spi_transfer *t) goto complete; if (ss->trans_mode & SPRD_SPI_RX_MODE) - ss->read_bufs(ss, len); + read_size += ss->read_bufs(ss, len); trans_len -= len; } - ret = write_size; - + if (ss->trans_mode & SPRD_SPI_TX_MODE) + ret = write_size; + else + ret = read_size; complete: sprd_spi_enter_idle(ss); return ret; } +static void sprd_spi_irq_enable(struct sprd_spi *ss) +{ + u32 val; + + /* Clear interrupt status before enabling interrupt. */ + writel_relaxed(SPRD_SPI_TX_END_CLR | SPRD_SPI_RX_END_CLR, + ss->base + SPRD_SPI_INT_CLR); + /* Enable SPI interrupt only in DMA mode. */ + val = readl_relaxed(ss->base + SPRD_SPI_INT_EN); + writel_relaxed(val | SPRD_SPI_TX_END_INT_EN | + SPRD_SPI_RX_END_INT_EN, + ss->base + SPRD_SPI_INT_EN); +} + +static void sprd_spi_irq_disable(struct sprd_spi *ss) +{ + writel_relaxed(0, ss->base + SPRD_SPI_INT_EN); +} + +static void sprd_spi_dma_enable(struct sprd_spi *ss, bool enable) +{ + u32 val = readl_relaxed(ss->base + SPRD_SPI_CTL2); + + if (enable) + val |= SPRD_SPI_DMA_EN; + else + val &= ~SPRD_SPI_DMA_EN; + + writel_relaxed(val, ss->base + SPRD_SPI_CTL2); +} + +static int sprd_spi_dma_submit(struct dma_chan *dma_chan, + struct dma_slave_config *c, + struct sg_table *sg, + enum dma_transfer_direction dir) +{ + struct dma_async_tx_descriptor *desc; + dma_cookie_t cookie; + unsigned long flags; + int ret; + + ret = dmaengine_slave_config(dma_chan, c); + if (ret < 0) + return ret; + + flags = SPRD_DMA_FLAGS(SPRD_DMA_CHN_MODE_NONE, SPRD_DMA_NO_TRG, + SPRD_DMA_FRAG_REQ, SPRD_DMA_TRANS_INT); + desc = dmaengine_prep_slave_sg(dma_chan, sg->sgl, sg->nents, dir, flags); + if (!desc) + return -ENODEV; + + cookie = dmaengine_submit(desc); + if (dma_submit_error(cookie)) + return dma_submit_error(cookie); + + dma_async_issue_pending(dma_chan); + + return 0; +} + +static int sprd_spi_dma_rx_config(struct sprd_spi *ss, struct spi_transfer *t) +{ + struct dma_chan *dma_chan = ss->dma.dma_chan[SPRD_SPI_RX]; + struct dma_slave_config config = { + .src_addr = ss->phy_base, + .src_addr_width = ss->dma.width, + .dst_addr_width = ss->dma.width, + .dst_maxburst = ss->dma.fragmens_len, + }; + int ret; + + ret = sprd_spi_dma_submit(dma_chan, &config, &t->rx_sg, DMA_DEV_TO_MEM); + if (ret) + return ret; + + return ss->dma.rx_len; +} + +static int sprd_spi_dma_tx_config(struct sprd_spi *ss, struct spi_transfer *t) +{ + struct dma_chan *dma_chan = ss->dma.dma_chan[SPRD_SPI_TX]; + struct dma_slave_config config = { + .dst_addr = ss->phy_base, + .src_addr_width = ss->dma.width, + .dst_addr_width = ss->dma.width, + .src_maxburst = ss->dma.fragmens_len, + }; + int ret; + + ret = sprd_spi_dma_submit(dma_chan, &config, &t->tx_sg, DMA_MEM_TO_DEV); + if (ret) + return ret; + + return t->len; +} + +static int sprd_spi_dma_request(struct sprd_spi *ss) +{ + ss->dma.dma_chan[SPRD_SPI_RX] = dma_request_chan(ss->dev, "rx_chn"); + if (IS_ERR_OR_NULL(ss->dma.dma_chan[SPRD_SPI_RX])) { + if (PTR_ERR(ss->dma.dma_chan[SPRD_SPI_RX]) == -EPROBE_DEFER) + return PTR_ERR(ss->dma.dma_chan[SPRD_SPI_RX]); + + dev_err(ss->dev, "request RX DMA channel failed!\n"); + return PTR_ERR(ss->dma.dma_chan[SPRD_SPI_RX]); + } + + ss->dma.dma_chan[SPRD_SPI_TX] = dma_request_chan(ss->dev, "tx_chn"); + if (IS_ERR_OR_NULL(ss->dma.dma_chan[SPRD_SPI_TX])) { + if (PTR_ERR(ss->dma.dma_chan[SPRD_SPI_TX]) == -EPROBE_DEFER) + return PTR_ERR(ss->dma.dma_chan[SPRD_SPI_TX]); + + dev_err(ss->dev, "request TX DMA channel failed!\n"); + dma_release_channel(ss->dma.dma_chan[SPRD_SPI_RX]); + return PTR_ERR(ss->dma.dma_chan[SPRD_SPI_TX]); + } + + return 0; +} + +static void sprd_spi_dma_release(struct sprd_spi *ss) +{ + if (ss->dma.dma_chan[SPRD_SPI_RX]) + dma_release_channel(ss->dma.dma_chan[SPRD_SPI_RX]); + + if (ss->dma.dma_chan[SPRD_SPI_TX]) + dma_release_channel(ss->dma.dma_chan[SPRD_SPI_TX]); +} + +static int sprd_spi_dma_txrx_bufs(struct spi_device *sdev, + struct spi_transfer *t) +{ + struct sprd_spi *ss = spi_master_get_devdata(sdev->master); + u32 trans_len = ss->trans_len; + int ret, write_size = 0; + + reinit_completion(&ss->xfer_completion); + sprd_spi_irq_enable(ss); + if (ss->trans_mode & SPRD_SPI_TX_MODE) { + write_size = sprd_spi_dma_tx_config(ss, t); + sprd_spi_set_tx_length(ss, trans_len); + + /* + * For our 3 wires mode or dual TX line mode, we need + * to request the controller to transfer. + */ + if (ss->hw_mode & SPI_3WIRE || ss->hw_mode & SPI_TX_DUAL) + sprd_spi_tx_req(ss); + } else { + sprd_spi_set_rx_length(ss, trans_len); + + /* + * For our 3 wires mode or dual TX line mode, we need + * to request the controller to read. + */ + if (ss->hw_mode & SPI_3WIRE || ss->hw_mode & SPI_TX_DUAL) + sprd_spi_rx_req(ss); + else + write_size = ss->write_bufs(ss, trans_len); + } + + if (write_size < 0) { + ret = write_size; + dev_err(ss->dev, "failed to write, ret = %d\n", ret); + goto trans_complete; + } + + if (ss->trans_mode & SPRD_SPI_RX_MODE) { + /* + * Set up the DMA receive data length, which must be an + * integral multiple of fragment length. But when the length + * of received data is less than fragment length, DMA can be + * configured to receive data according to the actual length + * of received data. + */ + ss->dma.rx_len = t->len > ss->dma.fragmens_len ? + (t->len - t->len % ss->dma.fragmens_len) : + t->len; + ret = sprd_spi_dma_rx_config(ss, t); + if (ret < 0) { + dev_err(&sdev->dev, + "failed to configure rx DMA, ret = %d\n", ret); + goto trans_complete; + } + } + + sprd_spi_dma_enable(ss, true); + wait_for_completion(&(ss->xfer_completion)); + + if (ss->trans_mode & SPRD_SPI_TX_MODE) + ret = write_size; + else + ret = ss->dma.rx_len; + +trans_complete: + sprd_spi_dma_enable(ss, false); + sprd_spi_enter_idle(ss); + sprd_spi_irq_disable(ss); + + return ret; +} + static void sprd_spi_set_speed(struct sprd_spi *ss, u32 speed_hz) { /* @@ -514,16 +741,22 @@ static int sprd_spi_setup_transfer(struct spi_device *sdev, ss->trans_len = t->len; ss->read_bufs = sprd_spi_read_bufs_u8; ss->write_bufs = sprd_spi_write_bufs_u8; + ss->dma.width = DMA_SLAVE_BUSWIDTH_1_BYTE; + ss->dma.fragmens_len = SPRD_SPI_DMA_STEP; break; case 16: ss->trans_len = t->len >> 1; ss->read_bufs = sprd_spi_read_bufs_u16; ss->write_bufs = sprd_spi_write_bufs_u16; + ss->dma.width = DMA_SLAVE_BUSWIDTH_2_BYTES; + ss->dma.fragmens_len = SPRD_SPI_DMA_STEP << 1; break; case 32: ss->trans_len = t->len >> 2; ss->read_bufs = sprd_spi_read_bufs_u32; ss->write_bufs = sprd_spi_write_bufs_u32; + ss->dma.width = DMA_SLAVE_BUSWIDTH_4_BYTES; + ss->dma.fragmens_len = SPRD_SPI_DMA_STEP << 2; break; default: return -EINVAL; @@ -561,7 +794,11 @@ static int sprd_spi_transfer_one(struct spi_controller *sctlr, if (ret) goto setup_err; - ret = sprd_spi_txrx_bufs(sdev, t); + if (sctlr->can_dma(sctlr, sdev, t)) + ret = sprd_spi_dma_txrx_bufs(sdev, t); + else + ret = sprd_spi_txrx_bufs(sdev, t); + if (ret == t->len) ret = 0; else if (ret >= 0) @@ -573,6 +810,53 @@ setup_err: return ret; } +static irqreturn_t sprd_spi_handle_irq(int irq, void *data) +{ + struct sprd_spi *ss = (struct sprd_spi *)data; + u32 val = readl_relaxed(ss->base + SPRD_SPI_INT_MASK_STS); + + if (val & SPRD_SPI_MASK_TX_END) { + writel_relaxed(SPRD_SPI_TX_END_CLR, ss->base + SPRD_SPI_INT_CLR); + if (!(ss->trans_mode & SPRD_SPI_RX_MODE)) + complete(&ss->xfer_completion); + + return IRQ_HANDLED; + } + + if (val & SPRD_SPI_MASK_RX_END) { + writel_relaxed(SPRD_SPI_RX_END_CLR, ss->base + SPRD_SPI_INT_CLR); + if (ss->dma.rx_len < ss->len) { + ss->rx_buf += ss->dma.rx_len; + ss->dma.rx_len += + ss->read_bufs(ss, ss->len - ss->dma.rx_len); + } + complete(&ss->xfer_completion); + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static int sprd_spi_irq_init(struct platform_device *pdev, struct sprd_spi *ss) +{ + int ret; + + ss->irq = platform_get_irq(pdev, 0); + if (ss->irq < 0) { + dev_err(&pdev->dev, "failed to get irq resource\n"); + return ss->irq; + } + + ret = devm_request_irq(&pdev->dev, ss->irq, sprd_spi_handle_irq, + 0, pdev->name, ss); + if (ret) + dev_err(&pdev->dev, "failed to request spi irq %d, ret = %d\n", + ss->irq, ret); + + return ret; +} + static int sprd_spi_clk_init(struct platform_device *pdev, struct sprd_spi *ss) { struct clk *clk_spi, *clk_parent; @@ -603,6 +887,35 @@ static int sprd_spi_clk_init(struct platform_device *pdev, struct sprd_spi *ss) return 0; } +static bool sprd_spi_can_dma(struct spi_controller *sctlr, + struct spi_device *spi, struct spi_transfer *t) +{ + struct sprd_spi *ss = spi_controller_get_devdata(sctlr); + + return ss->dma.enable && (t->len > SPRD_SPI_FIFO_SIZE); +} + +static int sprd_spi_dma_init(struct platform_device *pdev, struct sprd_spi *ss) +{ + int ret; + + ret = sprd_spi_dma_request(ss); + if (ret) { + if (ret == -EPROBE_DEFER) + return ret; + + dev_warn(&pdev->dev, + "failed to request dma, enter no dma mode, ret = %d\n", + ret); + + return 0; + } + + ss->dma.enable = true; + + return 0; +} + static int sprd_spi_probe(struct platform_device *pdev) { struct spi_controller *sctlr; @@ -623,25 +936,36 @@ static int sprd_spi_probe(struct platform_device *pdev) goto free_controller; } + ss->phy_base = res->start; ss->dev = &pdev->dev; sctlr->dev.of_node = pdev->dev.of_node; sctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE | SPI_TX_DUAL; sctlr->bus_num = pdev->id; sctlr->set_cs = sprd_spi_chipselect; sctlr->transfer_one = sprd_spi_transfer_one; + sctlr->can_dma = sprd_spi_can_dma; sctlr->auto_runtime_pm = true; sctlr->max_speed_hz = min_t(u32, ss->src_clk >> 1, SPRD_SPI_MAX_SPEED_HZ); + init_completion(&ss->xfer_completion); platform_set_drvdata(pdev, sctlr); ret = sprd_spi_clk_init(pdev, ss); if (ret) goto free_controller; - ret = clk_prepare_enable(ss->clk); + ret = sprd_spi_irq_init(pdev, ss); if (ret) goto free_controller; + ret = sprd_spi_dma_init(pdev, ss); + if (ret) + goto free_controller; + + ret = clk_prepare_enable(ss->clk); + if (ret) + goto release_dma; + ret = pm_runtime_set_active(&pdev->dev); if (ret < 0) goto disable_clk; @@ -670,6 +994,8 @@ err_rpm_put: pm_runtime_disable(&pdev->dev); disable_clk: clk_disable_unprepare(ss->clk); +release_dma: + sprd_spi_dma_release(ss); free_controller: spi_controller_put(sctlr); @@ -688,6 +1014,10 @@ static int sprd_spi_remove(struct platform_device *pdev) return ret; } + spi_controller_suspend(sctlr); + + if (ss->dma.enable) + sprd_spi_dma_release(ss); clk_disable_unprepare(ss->clk); pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -700,6 +1030,9 @@ static int __maybe_unused sprd_spi_runtime_suspend(struct device *dev) struct spi_controller *sctlr = dev_get_drvdata(dev); struct sprd_spi *ss = spi_controller_get_devdata(sctlr); + if (ss->dma.enable) + sprd_spi_dma_release(ss); + clk_disable_unprepare(ss->clk); return 0; @@ -715,7 +1048,14 @@ static int __maybe_unused sprd_spi_runtime_resume(struct device *dev) if (ret) return ret; - return 0; + if (!ss->dma.enable) + return 0; + + ret = sprd_spi_dma_request(ss); + if (ret) + clk_disable_unprepare(ss->clk); + + return ret; } static const struct dev_pm_ops sprd_spi_pm_ops = { diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index ad1e55d3d5d5..4186ed20d796 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1,23 +1,10 @@ -/* - * STMicroelectronics STM32 SPI Controller driver (master mode only) - * - * Copyright (C) 2017, STMicroelectronics - All Rights Reserved - * Author(s): Amelie Delaunay <amelie.delaunay@st.com> for STMicroelectronics. - * - * License terms: GPL V2.0. - * - * spi_stm32 driver 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. - * - * spi_stm32 driver is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * spi_stm32 driver. If not, see <http://www.gnu.org/licenses/>. - */ +// SPDX-License-Identifier: GPL-2.0 +// +// STMicroelectronics STM32 SPI Controller driver (master mode only) +// +// Copyright (C) 2017, STMicroelectronics - All Rights Reserved +// Author(s): Amelie Delaunay <amelie.delaunay@st.com> for STMicroelectronics. + #include <linux/debugfs.h> #include <linux/clk.h> #include <linux/delay.h> @@ -33,99 +20,251 @@ #define DRIVER_NAME "spi_stm32" -/* STM32 SPI registers */ -#define STM32_SPI_CR1 0x00 -#define STM32_SPI_CR2 0x04 -#define STM32_SPI_CFG1 0x08 -#define STM32_SPI_CFG2 0x0C -#define STM32_SPI_IER 0x10 -#define STM32_SPI_SR 0x14 -#define STM32_SPI_IFCR 0x18 -#define STM32_SPI_TXDR 0x20 -#define STM32_SPI_RXDR 0x30 -#define STM32_SPI_I2SCFGR 0x50 - -/* STM32_SPI_CR1 bit fields */ -#define SPI_CR1_SPE BIT(0) -#define SPI_CR1_MASRX BIT(8) -#define SPI_CR1_CSTART BIT(9) -#define SPI_CR1_CSUSP BIT(10) -#define SPI_CR1_HDDIR BIT(11) -#define SPI_CR1_SSI BIT(12) - -/* STM32_SPI_CR2 bit fields */ -#define SPI_CR2_TSIZE_SHIFT 0 -#define SPI_CR2_TSIZE GENMASK(15, 0) - -/* STM32_SPI_CFG1 bit fields */ -#define SPI_CFG1_DSIZE_SHIFT 0 -#define SPI_CFG1_DSIZE GENMASK(4, 0) -#define SPI_CFG1_FTHLV_SHIFT 5 -#define SPI_CFG1_FTHLV GENMASK(8, 5) -#define SPI_CFG1_RXDMAEN BIT(14) -#define SPI_CFG1_TXDMAEN BIT(15) -#define SPI_CFG1_MBR_SHIFT 28 -#define SPI_CFG1_MBR GENMASK(30, 28) -#define SPI_CFG1_MBR_MIN 0 -#define SPI_CFG1_MBR_MAX (GENMASK(30, 28) >> 28) - -/* STM32_SPI_CFG2 bit fields */ -#define SPI_CFG2_MIDI_SHIFT 4 -#define SPI_CFG2_MIDI GENMASK(7, 4) -#define SPI_CFG2_COMM_SHIFT 17 -#define SPI_CFG2_COMM GENMASK(18, 17) -#define SPI_CFG2_SP_SHIFT 19 -#define SPI_CFG2_SP GENMASK(21, 19) -#define SPI_CFG2_MASTER BIT(22) -#define SPI_CFG2_LSBFRST BIT(23) -#define SPI_CFG2_CPHA BIT(24) -#define SPI_CFG2_CPOL BIT(25) -#define SPI_CFG2_SSM BIT(26) -#define SPI_CFG2_AFCNTR BIT(31) - -/* STM32_SPI_IER bit fields */ -#define SPI_IER_RXPIE BIT(0) -#define SPI_IER_TXPIE BIT(1) -#define SPI_IER_DXPIE BIT(2) -#define SPI_IER_EOTIE BIT(3) -#define SPI_IER_TXTFIE BIT(4) -#define SPI_IER_OVRIE BIT(6) -#define SPI_IER_MODFIE BIT(9) -#define SPI_IER_ALL GENMASK(10, 0) - -/* STM32_SPI_SR bit fields */ -#define SPI_SR_RXP BIT(0) -#define SPI_SR_TXP BIT(1) -#define SPI_SR_EOT BIT(3) -#define SPI_SR_OVR BIT(6) -#define SPI_SR_MODF BIT(9) -#define SPI_SR_SUSP BIT(11) -#define SPI_SR_RXPLVL_SHIFT 13 -#define SPI_SR_RXPLVL GENMASK(14, 13) -#define SPI_SR_RXWNE BIT(15) - -/* STM32_SPI_IFCR bit fields */ -#define SPI_IFCR_ALL GENMASK(11, 3) - -/* STM32_SPI_I2SCFGR bit fields */ -#define SPI_I2SCFGR_I2SMOD BIT(0) - -/* SPI Master Baud Rate min/max divisor */ -#define SPI_MBR_DIV_MIN (2 << SPI_CFG1_MBR_MIN) -#define SPI_MBR_DIV_MAX (2 << SPI_CFG1_MBR_MAX) - -/* SPI Communication mode */ +/* STM32F4 SPI registers */ +#define STM32F4_SPI_CR1 0x00 +#define STM32F4_SPI_CR2 0x04 +#define STM32F4_SPI_SR 0x08 +#define STM32F4_SPI_DR 0x0C +#define STM32F4_SPI_I2SCFGR 0x1C + +/* STM32F4_SPI_CR1 bit fields */ +#define STM32F4_SPI_CR1_CPHA BIT(0) +#define STM32F4_SPI_CR1_CPOL BIT(1) +#define STM32F4_SPI_CR1_MSTR BIT(2) +#define STM32F4_SPI_CR1_BR_SHIFT 3 +#define STM32F4_SPI_CR1_BR GENMASK(5, 3) +#define STM32F4_SPI_CR1_SPE BIT(6) +#define STM32F4_SPI_CR1_LSBFRST BIT(7) +#define STM32F4_SPI_CR1_SSI BIT(8) +#define STM32F4_SPI_CR1_SSM BIT(9) +#define STM32F4_SPI_CR1_RXONLY BIT(10) +#define STM32F4_SPI_CR1_DFF BIT(11) +#define STM32F4_SPI_CR1_CRCNEXT BIT(12) +#define STM32F4_SPI_CR1_CRCEN BIT(13) +#define STM32F4_SPI_CR1_BIDIOE BIT(14) +#define STM32F4_SPI_CR1_BIDIMODE BIT(15) +#define STM32F4_SPI_CR1_BR_MIN 0 +#define STM32F4_SPI_CR1_BR_MAX (GENMASK(5, 3) >> 3) + +/* STM32F4_SPI_CR2 bit fields */ +#define STM32F4_SPI_CR2_RXDMAEN BIT(0) +#define STM32F4_SPI_CR2_TXDMAEN BIT(1) +#define STM32F4_SPI_CR2_SSOE BIT(2) +#define STM32F4_SPI_CR2_FRF BIT(4) +#define STM32F4_SPI_CR2_ERRIE BIT(5) +#define STM32F4_SPI_CR2_RXNEIE BIT(6) +#define STM32F4_SPI_CR2_TXEIE BIT(7) + +/* STM32F4_SPI_SR bit fields */ +#define STM32F4_SPI_SR_RXNE BIT(0) +#define STM32F4_SPI_SR_TXE BIT(1) +#define STM32F4_SPI_SR_CHSIDE BIT(2) +#define STM32F4_SPI_SR_UDR BIT(3) +#define STM32F4_SPI_SR_CRCERR BIT(4) +#define STM32F4_SPI_SR_MODF BIT(5) +#define STM32F4_SPI_SR_OVR BIT(6) +#define STM32F4_SPI_SR_BSY BIT(7) +#define STM32F4_SPI_SR_FRE BIT(8) + +/* STM32F4_SPI_I2SCFGR bit fields */ +#define STM32F4_SPI_I2SCFGR_I2SMOD BIT(11) + +/* STM32F4 SPI Baud Rate min/max divisor */ +#define STM32F4_SPI_BR_DIV_MIN (2 << STM32F4_SPI_CR1_BR_MIN) +#define STM32F4_SPI_BR_DIV_MAX (2 << STM32F4_SPI_CR1_BR_MAX) + +/* STM32H7 SPI registers */ +#define STM32H7_SPI_CR1 0x00 +#define STM32H7_SPI_CR2 0x04 +#define STM32H7_SPI_CFG1 0x08 +#define STM32H7_SPI_CFG2 0x0C +#define STM32H7_SPI_IER 0x10 +#define STM32H7_SPI_SR 0x14 +#define STM32H7_SPI_IFCR 0x18 +#define STM32H7_SPI_TXDR 0x20 +#define STM32H7_SPI_RXDR 0x30 +#define STM32H7_SPI_I2SCFGR 0x50 + +/* STM32H7_SPI_CR1 bit fields */ +#define STM32H7_SPI_CR1_SPE BIT(0) +#define STM32H7_SPI_CR1_MASRX BIT(8) +#define STM32H7_SPI_CR1_CSTART BIT(9) +#define STM32H7_SPI_CR1_CSUSP BIT(10) +#define STM32H7_SPI_CR1_HDDIR BIT(11) +#define STM32H7_SPI_CR1_SSI BIT(12) + +/* STM32H7_SPI_CR2 bit fields */ +#define STM32H7_SPI_CR2_TSIZE_SHIFT 0 +#define STM32H7_SPI_CR2_TSIZE GENMASK(15, 0) + +/* STM32H7_SPI_CFG1 bit fields */ +#define STM32H7_SPI_CFG1_DSIZE_SHIFT 0 +#define STM32H7_SPI_CFG1_DSIZE GENMASK(4, 0) +#define STM32H7_SPI_CFG1_FTHLV_SHIFT 5 +#define STM32H7_SPI_CFG1_FTHLV GENMASK(8, 5) +#define STM32H7_SPI_CFG1_RXDMAEN BIT(14) +#define STM32H7_SPI_CFG1_TXDMAEN BIT(15) +#define STM32H7_SPI_CFG1_MBR_SHIFT 28 +#define STM32H7_SPI_CFG1_MBR GENMASK(30, 28) +#define STM32H7_SPI_CFG1_MBR_MIN 0 +#define STM32H7_SPI_CFG1_MBR_MAX (GENMASK(30, 28) >> 28) + +/* STM32H7_SPI_CFG2 bit fields */ +#define STM32H7_SPI_CFG2_MIDI_SHIFT 4 +#define STM32H7_SPI_CFG2_MIDI GENMASK(7, 4) +#define STM32H7_SPI_CFG2_COMM_SHIFT 17 +#define STM32H7_SPI_CFG2_COMM GENMASK(18, 17) +#define STM32H7_SPI_CFG2_SP_SHIFT 19 +#define STM32H7_SPI_CFG2_SP GENMASK(21, 19) +#define STM32H7_SPI_CFG2_MASTER BIT(22) +#define STM32H7_SPI_CFG2_LSBFRST BIT(23) +#define STM32H7_SPI_CFG2_CPHA BIT(24) +#define STM32H7_SPI_CFG2_CPOL BIT(25) +#define STM32H7_SPI_CFG2_SSM BIT(26) +#define STM32H7_SPI_CFG2_AFCNTR BIT(31) + +/* STM32H7_SPI_IER bit fields */ +#define STM32H7_SPI_IER_RXPIE BIT(0) +#define STM32H7_SPI_IER_TXPIE BIT(1) +#define STM32H7_SPI_IER_DXPIE BIT(2) +#define STM32H7_SPI_IER_EOTIE BIT(3) +#define STM32H7_SPI_IER_TXTFIE BIT(4) +#define STM32H7_SPI_IER_OVRIE BIT(6) +#define STM32H7_SPI_IER_MODFIE BIT(9) +#define STM32H7_SPI_IER_ALL GENMASK(10, 0) + +/* STM32H7_SPI_SR bit fields */ +#define STM32H7_SPI_SR_RXP BIT(0) +#define STM32H7_SPI_SR_TXP BIT(1) +#define STM32H7_SPI_SR_EOT BIT(3) +#define STM32H7_SPI_SR_OVR BIT(6) +#define STM32H7_SPI_SR_MODF BIT(9) +#define STM32H7_SPI_SR_SUSP BIT(11) +#define STM32H7_SPI_SR_RXPLVL_SHIFT 13 +#define STM32H7_SPI_SR_RXPLVL GENMASK(14, 13) +#define STM32H7_SPI_SR_RXWNE BIT(15) + +/* STM32H7_SPI_IFCR bit fields */ +#define STM32H7_SPI_IFCR_ALL GENMASK(11, 3) + +/* STM32H7_SPI_I2SCFGR bit fields */ +#define STM32H7_SPI_I2SCFGR_I2SMOD BIT(0) + +/* STM32H7 SPI Master Baud Rate min/max divisor */ +#define STM32H7_SPI_MBR_DIV_MIN (2 << STM32H7_SPI_CFG1_MBR_MIN) +#define STM32H7_SPI_MBR_DIV_MAX (2 << STM32H7_SPI_CFG1_MBR_MAX) + +/* STM32H7 SPI Communication mode */ +#define STM32H7_SPI_FULL_DUPLEX 0 +#define STM32H7_SPI_SIMPLEX_TX 1 +#define STM32H7_SPI_SIMPLEX_RX 2 +#define STM32H7_SPI_HALF_DUPLEX 3 + +/* SPI Communication type */ #define SPI_FULL_DUPLEX 0 #define SPI_SIMPLEX_TX 1 #define SPI_SIMPLEX_RX 2 -#define SPI_HALF_DUPLEX 3 +#define SPI_3WIRE_TX 3 +#define SPI_3WIRE_RX 4 #define SPI_1HZ_NS 1000000000 +/* + * use PIO for small transfers, avoiding DMA setup/teardown overhead for drivers + * without fifo buffers. + */ +#define SPI_DMA_MIN_BYTES 16 + +/** + * stm32_spi_reg - stm32 SPI register & bitfield desc + * @reg: register offset + * @mask: bitfield mask + * @shift: left shift + */ +struct stm32_spi_reg { + int reg; + int mask; + int shift; +}; + +/** + * stm32_spi_regspec - stm32 registers definition, compatible dependent data + * en: enable register and SPI enable bit + * dma_rx_en: SPI DMA RX enable register end SPI DMA RX enable bit + * dma_tx_en: SPI DMA TX enable register end SPI DMA TX enable bit + * cpol: clock polarity register and polarity bit + * cpha: clock phase register and phase bit + * lsb_first: LSB transmitted first register and bit + * br: baud rate register and bitfields + * rx: SPI RX data register + * tx: SPI TX data register + */ +struct stm32_spi_regspec { + const struct stm32_spi_reg en; + const struct stm32_spi_reg dma_rx_en; + const struct stm32_spi_reg dma_tx_en; + const struct stm32_spi_reg cpol; + const struct stm32_spi_reg cpha; + const struct stm32_spi_reg lsb_first; + const struct stm32_spi_reg br; + const struct stm32_spi_reg rx; + const struct stm32_spi_reg tx; +}; + +struct stm32_spi; + +/** + * stm32_spi_cfg - stm32 compatible configuration data + * @regs: registers descriptions + * @get_fifo_size: routine to get fifo size + * @get_bpw_mask: routine to get bits per word mask + * @disable: routine to disable controller + * @config: routine to configure controller as SPI Master + * @set_bpw: routine to configure registers to for bits per word + * @set_mode: routine to configure registers to desired mode + * @set_data_idleness: optional routine to configure registers to desired idle + * time between frames (if driver has this functionality) + * set_number_of_data: optional routine to configure registers to desired + * number of data (if driver has this functionality) + * @can_dma: routine to determine if the transfer is eligible for DMA use + * @transfer_one_dma_start: routine to start transfer a single spi_transfer + * using DMA + * @dma_rx cb: routine to call after DMA RX channel operation is complete + * @dma_tx cb: routine to call after DMA TX channel operation is complete + * @transfer_one_irq: routine to configure interrupts for driver + * @irq_handler_event: Interrupt handler for SPI controller events + * @irq_handler_thread: thread of interrupt handler for SPI controller + * @baud_rate_div_min: minimum baud rate divisor + * @baud_rate_div_max: maximum baud rate divisor + * @has_fifo: boolean to know if fifo is used for driver + * @has_startbit: boolean to know if start bit is used to start transfer + */ +struct stm32_spi_cfg { + const struct stm32_spi_regspec *regs; + int (*get_fifo_size)(struct stm32_spi *spi); + int (*get_bpw_mask)(struct stm32_spi *spi); + void (*disable)(struct stm32_spi *spi); + int (*config)(struct stm32_spi *spi); + void (*set_bpw)(struct stm32_spi *spi); + int (*set_mode)(struct stm32_spi *spi, unsigned int comm_type); + void (*set_data_idleness)(struct stm32_spi *spi, u32 length); + int (*set_number_of_data)(struct stm32_spi *spi, u32 length); + void (*transfer_one_dma_start)(struct stm32_spi *spi); + void (*dma_rx_cb)(void *data); + void (*dma_tx_cb)(void *data); + int (*transfer_one_irq)(struct stm32_spi *spi); + irqreturn_t (*irq_handler_event)(int irq, void *dev_id); + irqreturn_t (*irq_handler_thread)(int irq, void *dev_id); + unsigned int baud_rate_div_min; + unsigned int baud_rate_div_max; + bool has_fifo; +}; + /** * struct stm32_spi - private data of the SPI controller * @dev: driver model representation of the controller * @master: controller master interface + * @cfg: compatible configuration data * @base: virtual memory area * @clk: hw kernel clock feeding the SPI clock generator * @clk_rate: rate of the hw kernel clock feeding the SPI clock generator @@ -151,6 +290,7 @@ struct stm32_spi { struct device *dev; struct spi_master *master; + const struct stm32_spi_cfg *cfg; void __iomem *base; struct clk *clk; u32 clk_rate; @@ -176,6 +316,40 @@ struct stm32_spi { dma_addr_t phys_addr; }; +static const struct stm32_spi_regspec stm32f4_spi_regspec = { + .en = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE }, + + .dma_rx_en = { STM32F4_SPI_CR2, STM32F4_SPI_CR2_RXDMAEN }, + .dma_tx_en = { STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXDMAEN }, + + .cpol = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPOL }, + .cpha = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPHA }, + .lsb_first = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_LSBFRST }, + .br = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_BR, STM32F4_SPI_CR1_BR_SHIFT }, + + .rx = { STM32F4_SPI_DR }, + .tx = { STM32F4_SPI_DR }, +}; + +static const struct stm32_spi_regspec stm32h7_spi_regspec = { + /* SPI data transfer is enabled but spi_ker_ck is idle. + * CFG1 and CFG2 registers are write protected when SPE is enabled. + */ + .en = { STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE }, + + .dma_rx_en = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_RXDMAEN }, + .dma_tx_en = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_TXDMAEN }, + + .cpol = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPOL }, + .cpha = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPHA }, + .lsb_first = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_LSBFRST }, + .br = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_MBR, + STM32H7_SPI_CFG1_MBR_SHIFT }, + + .rx = { STM32H7_SPI_RXDR }, + .tx = { STM32H7_SPI_TXDR }, +}; + static inline void stm32_spi_set_bits(struct stm32_spi *spi, u32 offset, u32 bits) { @@ -191,22 +365,22 @@ static inline void stm32_spi_clr_bits(struct stm32_spi *spi, } /** - * stm32_spi_get_fifo_size - Return fifo size + * stm32h7_spi_get_fifo_size - Return fifo size * @spi: pointer to the spi controller data structure */ -static int stm32_spi_get_fifo_size(struct stm32_spi *spi) +static int stm32h7_spi_get_fifo_size(struct stm32_spi *spi) { unsigned long flags; u32 count = 0; spin_lock_irqsave(&spi->lock, flags); - stm32_spi_set_bits(spi, STM32_SPI_CR1, SPI_CR1_SPE); + stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE); - while (readl_relaxed(spi->base + STM32_SPI_SR) & SPI_SR_TXP) - writeb_relaxed(++count, spi->base + STM32_SPI_TXDR); + while (readl_relaxed(spi->base + STM32H7_SPI_SR) & STM32H7_SPI_SR_TXP) + writeb_relaxed(++count, spi->base + STM32H7_SPI_TXDR); - stm32_spi_clr_bits(spi, STM32_SPI_CR1, SPI_CR1_SPE); + stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE); spin_unlock_irqrestore(&spi->lock, flags); @@ -216,10 +390,20 @@ static int stm32_spi_get_fifo_size(struct stm32_spi *spi) } /** - * stm32_spi_get_bpw_mask - Return bits per word mask + * stm32f4_spi_get_bpw_mask - Return bits per word mask * @spi: pointer to the spi controller data structure */ -static int stm32_spi_get_bpw_mask(struct stm32_spi *spi) +static int stm32f4_spi_get_bpw_mask(struct stm32_spi *spi) +{ + dev_dbg(spi->dev, "8-bit or 16-bit data frame supported\n"); + return SPI_BPW_MASK(8) | SPI_BPW_MASK(16); +} + +/** + * stm32h7_spi_get_bpw_mask - Return bits per word mask + * @spi: pointer to the spi controller data structure + */ +static int stm32h7_spi_get_bpw_mask(struct stm32_spi *spi) { unsigned long flags; u32 cfg1, max_bpw; @@ -230,10 +414,11 @@ static int stm32_spi_get_bpw_mask(struct stm32_spi *spi) * The most significant bit at DSIZE bit field is reserved when the * maximum data size of periperal instances is limited to 16-bit */ - stm32_spi_set_bits(spi, STM32_SPI_CFG1, SPI_CFG1_DSIZE); + stm32_spi_set_bits(spi, STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_DSIZE); - cfg1 = readl_relaxed(spi->base + STM32_SPI_CFG1); - max_bpw = (cfg1 & SPI_CFG1_DSIZE) >> SPI_CFG1_DSIZE_SHIFT; + cfg1 = readl_relaxed(spi->base + STM32H7_SPI_CFG1); + max_bpw = (cfg1 & STM32H7_SPI_CFG1_DSIZE) >> + STM32H7_SPI_CFG1_DSIZE_SHIFT; max_bpw += 1; spin_unlock_irqrestore(&spi->lock, flags); @@ -244,13 +429,16 @@ static int stm32_spi_get_bpw_mask(struct stm32_spi *spi) } /** - * stm32_spi_prepare_mbr - Determine SPI_CFG1.MBR value + * stm32_spi_prepare_mbr - Determine baud rate divisor value * @spi: pointer to the spi controller data structure * @speed_hz: requested speed + * @min_div: minimum baud rate divisor + * @max_div: maximum baud rate divisor * - * Return SPI_CFG1.MBR value in case of success or -EINVAL + * Return baud rate divisor value in case of success or -EINVAL */ -static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz) +static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz, + u32 min_div, u32 max_div) { u32 div, mbrdiv; @@ -263,8 +451,7 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz) * no need to check it there. * However, we need to ensure the following calculations. */ - if (div < SPI_MBR_DIV_MIN || - div > SPI_MBR_DIV_MAX) + if ((div < min_div) || (div > max_div)) return -EINVAL; /* Determine the first power of 2 greater than or equal to div */ @@ -279,10 +466,10 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz) } /** - * stm32_spi_prepare_fthlv - Determine FIFO threshold level + * stm32h7_spi_prepare_fthlv - Determine FIFO threshold level * @spi: pointer to the spi controller data structure */ -static u32 stm32_spi_prepare_fthlv(struct stm32_spi *spi) +static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi) { u32 fthlv, half_fifo; @@ -306,32 +493,62 @@ static u32 stm32_spi_prepare_fthlv(struct stm32_spi *spi) } /** - * stm32_spi_write_txfifo - Write bytes in Transmit Data Register + * stm32f4_spi_write_tx - Write bytes to Transmit Data Register * @spi: pointer to the spi controller data structure * * Read from tx_buf depends on remaining bytes to avoid to read beyond * tx_buf end. */ -static void stm32_spi_write_txfifo(struct stm32_spi *spi) +static void stm32f4_spi_write_tx(struct stm32_spi *spi) +{ + if ((spi->tx_len > 0) && (readl_relaxed(spi->base + STM32F4_SPI_SR) & + STM32F4_SPI_SR_TXE)) { + u32 offs = spi->cur_xferlen - spi->tx_len; + + if (spi->cur_bpw == 16) { + const u16 *tx_buf16 = (const u16 *)(spi->tx_buf + offs); + + writew_relaxed(*tx_buf16, spi->base + STM32F4_SPI_DR); + spi->tx_len -= sizeof(u16); + } else { + const u8 *tx_buf8 = (const u8 *)(spi->tx_buf + offs); + + writeb_relaxed(*tx_buf8, spi->base + STM32F4_SPI_DR); + spi->tx_len -= sizeof(u8); + } + } + + dev_dbg(spi->dev, "%s: %d bytes left\n", __func__, spi->tx_len); +} + +/** + * stm32h7_spi_write_txfifo - Write bytes in Transmit Data Register + * @spi: pointer to the spi controller data structure + * + * Read from tx_buf depends on remaining bytes to avoid to read beyond + * tx_buf end. + */ +static void stm32h7_spi_write_txfifo(struct stm32_spi *spi) { while ((spi->tx_len > 0) && - (readl_relaxed(spi->base + STM32_SPI_SR) & SPI_SR_TXP)) { + (readl_relaxed(spi->base + STM32H7_SPI_SR) & + STM32H7_SPI_SR_TXP)) { u32 offs = spi->cur_xferlen - spi->tx_len; if (spi->tx_len >= sizeof(u32)) { const u32 *tx_buf32 = (const u32 *)(spi->tx_buf + offs); - writel_relaxed(*tx_buf32, spi->base + STM32_SPI_TXDR); + writel_relaxed(*tx_buf32, spi->base + STM32H7_SPI_TXDR); spi->tx_len -= sizeof(u32); } else if (spi->tx_len >= sizeof(u16)) { const u16 *tx_buf16 = (const u16 *)(spi->tx_buf + offs); - writew_relaxed(*tx_buf16, spi->base + STM32_SPI_TXDR); + writew_relaxed(*tx_buf16, spi->base + STM32H7_SPI_TXDR); spi->tx_len -= sizeof(u16); } else { const u8 *tx_buf8 = (const u8 *)(spi->tx_buf + offs); - writeb_relaxed(*tx_buf8, spi->base + STM32_SPI_TXDR); + writeb_relaxed(*tx_buf8, spi->base + STM32H7_SPI_TXDR); spi->tx_len -= sizeof(u8); } } @@ -340,43 +557,74 @@ static void stm32_spi_write_txfifo(struct stm32_spi *spi) } /** - * stm32_spi_read_rxfifo - Read bytes in Receive Data Register + * stm32f4_spi_read_rx - Read bytes from Receive Data Register + * @spi: pointer to the spi controller data structure + * + * Write in rx_buf depends on remaining bytes to avoid to write beyond + * rx_buf end. + */ +static void stm32f4_spi_read_rx(struct stm32_spi *spi) +{ + if ((spi->rx_len > 0) && (readl_relaxed(spi->base + STM32F4_SPI_SR) & + STM32F4_SPI_SR_RXNE)) { + u32 offs = spi->cur_xferlen - spi->rx_len; + + if (spi->cur_bpw == 16) { + u16 *rx_buf16 = (u16 *)(spi->rx_buf + offs); + + *rx_buf16 = readw_relaxed(spi->base + STM32F4_SPI_DR); + spi->rx_len -= sizeof(u16); + } else { + u8 *rx_buf8 = (u8 *)(spi->rx_buf + offs); + + *rx_buf8 = readb_relaxed(spi->base + STM32F4_SPI_DR); + spi->rx_len -= sizeof(u8); + } + } + + dev_dbg(spi->dev, "%s: %d bytes left\n", __func__, spi->rx_len); +} + +/** + * stm32h7_spi_read_rxfifo - Read bytes in Receive Data Register * @spi: pointer to the spi controller data structure * * Write in rx_buf depends on remaining bytes to avoid to write beyond * rx_buf end. */ -static void stm32_spi_read_rxfifo(struct stm32_spi *spi, bool flush) +static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi, bool flush) { - u32 sr = readl_relaxed(spi->base + STM32_SPI_SR); - u32 rxplvl = (sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_SHIFT; + u32 sr = readl_relaxed(spi->base + STM32H7_SPI_SR); + u32 rxplvl = (sr & STM32H7_SPI_SR_RXPLVL) >> + STM32H7_SPI_SR_RXPLVL_SHIFT; while ((spi->rx_len > 0) && - ((sr & SPI_SR_RXP) || - (flush && ((sr & SPI_SR_RXWNE) || (rxplvl > 0))))) { + ((sr & STM32H7_SPI_SR_RXP) || + (flush && ((sr & STM32H7_SPI_SR_RXWNE) || (rxplvl > 0))))) { u32 offs = spi->cur_xferlen - spi->rx_len; if ((spi->rx_len >= sizeof(u32)) || - (flush && (sr & SPI_SR_RXWNE))) { + (flush && (sr & STM32H7_SPI_SR_RXWNE))) { u32 *rx_buf32 = (u32 *)(spi->rx_buf + offs); - *rx_buf32 = readl_relaxed(spi->base + STM32_SPI_RXDR); + *rx_buf32 = readl_relaxed(spi->base + STM32H7_SPI_RXDR); spi->rx_len -= sizeof(u32); } else if ((spi->rx_len >= sizeof(u16)) || (flush && (rxplvl >= 2 || spi->cur_bpw > 8))) { u16 *rx_buf16 = (u16 *)(spi->rx_buf + offs); - *rx_buf16 = readw_relaxed(spi->base + STM32_SPI_RXDR); + *rx_buf16 = readw_relaxed(spi->base + STM32H7_SPI_RXDR); spi->rx_len -= sizeof(u16); } else { u8 *rx_buf8 = (u8 *)(spi->rx_buf + offs); - *rx_buf8 = readb_relaxed(spi->base + STM32_SPI_RXDR); + *rx_buf8 = readb_relaxed(spi->base + STM32H7_SPI_RXDR); spi->rx_len -= sizeof(u8); } - sr = readl_relaxed(spi->base + STM32_SPI_SR); - rxplvl = (sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_SHIFT; + sr = readl_relaxed(spi->base + STM32H7_SPI_SR); + rxplvl = (sr & STM32H7_SPI_SR_RXPLVL) >> + STM32H7_SPI_SR_RXPLVL_SHIFT; } dev_dbg(spi->dev, "%s%s: %d bytes left\n", __func__, @@ -386,26 +634,76 @@ static void stm32_spi_read_rxfifo(struct stm32_spi *spi, bool flush) /** * stm32_spi_enable - Enable SPI controller * @spi: pointer to the spi controller data structure - * - * SPI data transfer is enabled but spi_ker_ck is idle. - * SPI_CFG1 and SPI_CFG2 are now write protected. */ static void stm32_spi_enable(struct stm32_spi *spi) { dev_dbg(spi->dev, "enable controller\n"); - stm32_spi_set_bits(spi, STM32_SPI_CR1, SPI_CR1_SPE); + stm32_spi_set_bits(spi, spi->cfg->regs->en.reg, + spi->cfg->regs->en.mask); } /** - * stm32_spi_disable - Disable SPI controller + * stm32f4_spi_disable - Disable SPI controller + * @spi: pointer to the spi controller data structure + */ +static void stm32f4_spi_disable(struct stm32_spi *spi) +{ + unsigned long flags; + u32 sr; + + dev_dbg(spi->dev, "disable controller\n"); + + spin_lock_irqsave(&spi->lock, flags); + + if (!(readl_relaxed(spi->base + STM32F4_SPI_CR1) & + STM32F4_SPI_CR1_SPE)) { + spin_unlock_irqrestore(&spi->lock, flags); + return; + } + + /* Disable interrupts */ + stm32_spi_clr_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXEIE | + STM32F4_SPI_CR2_RXNEIE | + STM32F4_SPI_CR2_ERRIE); + + /* Wait until BSY = 0 */ + if (readl_relaxed_poll_timeout_atomic(spi->base + STM32F4_SPI_SR, + sr, !(sr & STM32F4_SPI_SR_BSY), + 10, 100000) < 0) { + dev_warn(spi->dev, "disabling condition timeout\n"); + } + + if (spi->cur_usedma && spi->dma_tx) + dmaengine_terminate_all(spi->dma_tx); + if (spi->cur_usedma && spi->dma_rx) + dmaengine_terminate_all(spi->dma_rx); + + stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE); + + stm32_spi_clr_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXDMAEN | + STM32F4_SPI_CR2_RXDMAEN); + + /* Sequence to clear OVR flag */ + readl_relaxed(spi->base + STM32F4_SPI_DR); + readl_relaxed(spi->base + STM32F4_SPI_SR); + + spin_unlock_irqrestore(&spi->lock, flags); +} + +/** + * stm32h7_spi_disable - Disable SPI controller * @spi: pointer to the spi controller data structure * * RX-Fifo is flushed when SPI controller is disabled. To prevent any data - * loss, use stm32_spi_read_rxfifo(flush) to read the remaining bytes in + * loss, use stm32h7_spi_read_rxfifo(flush) to read the remaining bytes in * RX-Fifo. + * Normally, if TSIZE has been configured, we should relax the hardware at the + * reception of the EOT interrupt. But in case of error, EOT will not be + * raised. So the subsystem unprepare_message call allows us to properly + * complete the transfer from an hardware point of view. */ -static void stm32_spi_disable(struct stm32_spi *spi) +static void stm32h7_spi_disable(struct stm32_spi *spi) { unsigned long flags; u32 cr1, sr; @@ -414,23 +712,23 @@ static void stm32_spi_disable(struct stm32_spi *spi) spin_lock_irqsave(&spi->lock, flags); - cr1 = readl_relaxed(spi->base + STM32_SPI_CR1); + cr1 = readl_relaxed(spi->base + STM32H7_SPI_CR1); - if (!(cr1 & SPI_CR1_SPE)) { + if (!(cr1 & STM32H7_SPI_CR1_SPE)) { spin_unlock_irqrestore(&spi->lock, flags); return; } /* Wait on EOT or suspend the flow */ - if (readl_relaxed_poll_timeout_atomic(spi->base + STM32_SPI_SR, - sr, !(sr & SPI_SR_EOT), + if (readl_relaxed_poll_timeout_atomic(spi->base + STM32H7_SPI_SR, + sr, !(sr & STM32H7_SPI_SR_EOT), 10, 100000) < 0) { - if (cr1 & SPI_CR1_CSTART) { - writel_relaxed(cr1 | SPI_CR1_CSUSP, - spi->base + STM32_SPI_CR1); + if (cr1 & STM32H7_SPI_CR1_CSTART) { + writel_relaxed(cr1 | STM32H7_SPI_CR1_CSUSP, + spi->base + STM32H7_SPI_CR1); if (readl_relaxed_poll_timeout_atomic( - spi->base + STM32_SPI_SR, - sr, !(sr & SPI_SR_SUSP), + spi->base + STM32H7_SPI_SR, + sr, !(sr & STM32H7_SPI_SR_SUSP), 10, 100000) < 0) dev_warn(spi->dev, "Suspend request timeout\n"); @@ -438,21 +736,21 @@ static void stm32_spi_disable(struct stm32_spi *spi) } if (!spi->cur_usedma && spi->rx_buf && (spi->rx_len > 0)) - stm32_spi_read_rxfifo(spi, true); + stm32h7_spi_read_rxfifo(spi, true); - if (spi->cur_usedma && spi->tx_buf) + if (spi->cur_usedma && spi->dma_tx) dmaengine_terminate_all(spi->dma_tx); - if (spi->cur_usedma && spi->rx_buf) + if (spi->cur_usedma && spi->dma_rx) dmaengine_terminate_all(spi->dma_rx); - stm32_spi_clr_bits(spi, STM32_SPI_CR1, SPI_CR1_SPE); + stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE); - stm32_spi_clr_bits(spi, STM32_SPI_CFG1, SPI_CFG1_TXDMAEN | - SPI_CFG1_RXDMAEN); + stm32_spi_clr_bits(spi, STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_TXDMAEN | + STM32H7_SPI_CFG1_RXDMAEN); /* Disable interrupts and clear status flags */ - writel_relaxed(0, spi->base + STM32_SPI_IER); - writel_relaxed(SPI_IFCR_ALL, spi->base + STM32_SPI_IFCR); + writel_relaxed(0, spi->base + STM32H7_SPI_IER); + writel_relaxed(STM32H7_SPI_IFCR_ALL, spi->base + STM32H7_SPI_IFCR); spin_unlock_irqrestore(&spi->lock, flags); } @@ -460,26 +758,136 @@ static void stm32_spi_disable(struct stm32_spi *spi) /** * stm32_spi_can_dma - Determine if the transfer is eligible for DMA use * - * If the current transfer size is greater than fifo size, use DMA. + * If driver has fifo and the current transfer size is greater than fifo size, + * use DMA. Otherwise use DMA for transfer longer than defined DMA min bytes. */ static bool stm32_spi_can_dma(struct spi_master *master, struct spi_device *spi_dev, struct spi_transfer *transfer) { + unsigned int dma_size; struct stm32_spi *spi = spi_master_get_devdata(master); + if (spi->cfg->has_fifo) + dma_size = spi->fifo_size; + else + dma_size = SPI_DMA_MIN_BYTES; + dev_dbg(spi->dev, "%s: %s\n", __func__, - (transfer->len > spi->fifo_size) ? "true" : "false"); + (transfer->len > dma_size) ? "true" : "false"); + + return (transfer->len > dma_size); +} + +/** + * stm32f4_spi_irq_event - Interrupt handler for SPI controller events + * @irq: interrupt line + * @dev_id: SPI controller master interface + */ +static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id) +{ + struct spi_master *master = dev_id; + struct stm32_spi *spi = spi_master_get_devdata(master); + u32 sr, mask = 0; + unsigned long flags; + bool end = false; + + spin_lock_irqsave(&spi->lock, flags); + + sr = readl_relaxed(spi->base + STM32F4_SPI_SR); + /* + * BSY flag is not handled in interrupt but it is normal behavior when + * this flag is set. + */ + sr &= ~STM32F4_SPI_SR_BSY; + + if (!spi->cur_usedma && (spi->cur_comm == SPI_SIMPLEX_TX || + spi->cur_comm == SPI_3WIRE_TX)) { + /* OVR flag shouldn't be handled for TX only mode */ + sr &= ~STM32F4_SPI_SR_OVR | STM32F4_SPI_SR_RXNE; + mask |= STM32F4_SPI_SR_TXE; + } + + if (!spi->cur_usedma && spi->cur_comm == SPI_FULL_DUPLEX) { + /* TXE flag is set and is handled when RXNE flag occurs */ + sr &= ~STM32F4_SPI_SR_TXE; + mask |= STM32F4_SPI_SR_RXNE | STM32F4_SPI_SR_OVR; + } + + if (!(sr & mask)) { + dev_dbg(spi->dev, "spurious IT (sr=0x%08x)\n", sr); + spin_unlock_irqrestore(&spi->lock, flags); + return IRQ_NONE; + } + + if (sr & STM32F4_SPI_SR_OVR) { + dev_warn(spi->dev, "Overrun: received value discarded\n"); + + /* Sequence to clear OVR flag */ + readl_relaxed(spi->base + STM32F4_SPI_DR); + readl_relaxed(spi->base + STM32F4_SPI_SR); + + /* + * If overrun is detected, it means that something went wrong, + * so stop the current transfer. Transfer can wait for next + * RXNE but DR is already read and end never happens. + */ + end = true; + goto end_irq; + } + + if (sr & STM32F4_SPI_SR_TXE) { + if (spi->tx_buf) + stm32f4_spi_write_tx(spi); + if (spi->tx_len == 0) + end = true; + } + + if (sr & STM32F4_SPI_SR_RXNE) { + stm32f4_spi_read_rx(spi); + if (spi->rx_len == 0) + end = true; + else /* Load data for discontinuous mode */ + stm32f4_spi_write_tx(spi); + } + +end_irq: + if (end) { + /* Immediately disable interrupts to do not generate new one */ + stm32_spi_clr_bits(spi, STM32F4_SPI_CR2, + STM32F4_SPI_CR2_TXEIE | + STM32F4_SPI_CR2_RXNEIE | + STM32F4_SPI_CR2_ERRIE); + spin_unlock_irqrestore(&spi->lock, flags); + return IRQ_WAKE_THREAD; + } + + spin_unlock_irqrestore(&spi->lock, flags); + return IRQ_HANDLED; +} + +/** + * stm32f4_spi_irq_thread - Thread of interrupt handler for SPI controller + * @irq: interrupt line + * @dev_id: SPI controller master interface + */ +static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id) +{ + struct spi_master *master = dev_id; + struct stm32_spi *spi = spi_master_get_devdata(master); + + spi_finalize_current_transfer(master); + stm32f4_spi_disable(spi); - return (transfer->len > spi->fifo_size); + return IRQ_HANDLED; } /** - * stm32_spi_irq - Interrupt handler for SPI controller events + * stm32h7_spi_irq_thread - Thread of interrupt handler for SPI controller * @irq: interrupt line * @dev_id: SPI controller master interface */ -static irqreturn_t stm32_spi_irq(int irq, void *dev_id) +static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) { struct spi_master *master = dev_id; struct stm32_spi *spi = spi_master_get_devdata(master); @@ -489,19 +897,19 @@ static irqreturn_t stm32_spi_irq(int irq, void *dev_id) spin_lock_irqsave(&spi->lock, flags); - sr = readl_relaxed(spi->base + STM32_SPI_SR); - ier = readl_relaxed(spi->base + STM32_SPI_IER); + sr = readl_relaxed(spi->base + STM32H7_SPI_SR); + ier = readl_relaxed(spi->base + STM32H7_SPI_IER); mask = ier; /* EOTIE is triggered on EOT, SUSP and TXC events. */ - mask |= SPI_SR_SUSP; + mask |= STM32H7_SPI_SR_SUSP; /* * When TXTF is set, DXPIE and TXPIE are cleared. So in case of * Full-Duplex, need to poll RXP event to know if there are remaining * data, before disabling SPI. */ if (spi->rx_buf && !spi->cur_usedma) - mask |= SPI_SR_RXP; + mask |= STM32H7_SPI_SR_RXP; if (!(sr & mask)) { dev_dbg(spi->dev, "spurious IT (sr=0x%08x, ier=0x%08x)\n", @@ -510,10 +918,10 @@ static irqreturn_t stm32_spi_irq(int irq, void *dev_id) return IRQ_NONE; } - if (sr & SPI_SR_SUSP) { + if (sr & STM32H7_SPI_SR_SUSP) { dev_warn(spi->dev, "Communication suspended\n"); if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) - stm32_spi_read_rxfifo(spi, false); + stm32h7_spi_read_rxfifo(spi, false); /* * If communication is suspended while using DMA, it means * that something went wrong, so stop the current transfer @@ -522,15 +930,15 @@ static irqreturn_t stm32_spi_irq(int irq, void *dev_id) end = true; } - if (sr & SPI_SR_MODF) { + if (sr & STM32H7_SPI_SR_MODF) { dev_warn(spi->dev, "Mode fault: transfer aborted\n"); end = true; } - if (sr & SPI_SR_OVR) { + if (sr & STM32H7_SPI_SR_OVR) { dev_warn(spi->dev, "Overrun: received value discarded\n"); if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) - stm32_spi_read_rxfifo(spi, false); + stm32h7_spi_read_rxfifo(spi, false); /* * If overrun is detected while using DMA, it means that * something went wrong, so stop the current transfer @@ -539,27 +947,27 @@ static irqreturn_t stm32_spi_irq(int irq, void *dev_id) end = true; } - if (sr & SPI_SR_EOT) { + if (sr & STM32H7_SPI_SR_EOT) { if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) - stm32_spi_read_rxfifo(spi, true); + stm32h7_spi_read_rxfifo(spi, true); end = true; } - if (sr & SPI_SR_TXP) + if (sr & STM32H7_SPI_SR_TXP) if (!spi->cur_usedma && (spi->tx_buf && (spi->tx_len > 0))) - stm32_spi_write_txfifo(spi); + stm32h7_spi_write_txfifo(spi); - if (sr & SPI_SR_RXP) + if (sr & STM32H7_SPI_SR_RXP) if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) - stm32_spi_read_rxfifo(spi, false); + stm32h7_spi_read_rxfifo(spi, false); - writel_relaxed(mask, spi->base + STM32_SPI_IFCR); + writel_relaxed(mask, spi->base + STM32H7_SPI_IFCR); spin_unlock_irqrestore(&spi->lock, flags); if (end) { spi_finalize_current_transfer(master); - stm32_spi_disable(spi); + stm32h7_spi_disable(spi); } return IRQ_HANDLED; @@ -598,7 +1006,7 @@ static int stm32_spi_prepare_msg(struct spi_master *master, struct spi_device *spi_dev = msg->spi; struct device_node *np = spi_dev->dev.of_node; unsigned long flags; - u32 cfg2_clrb = 0, cfg2_setb = 0; + u32 clrb = 0, setb = 0; /* SPI slave device may need time between data frames */ spi->cur_midi = 0; @@ -606,19 +1014,19 @@ static int stm32_spi_prepare_msg(struct spi_master *master, dev_dbg(spi->dev, "%dns inter-data idleness\n", spi->cur_midi); if (spi_dev->mode & SPI_CPOL) - cfg2_setb |= SPI_CFG2_CPOL; + setb |= spi->cfg->regs->cpol.mask; else - cfg2_clrb |= SPI_CFG2_CPOL; + clrb |= spi->cfg->regs->cpol.mask; if (spi_dev->mode & SPI_CPHA) - cfg2_setb |= SPI_CFG2_CPHA; + setb |= spi->cfg->regs->cpha.mask; else - cfg2_clrb |= SPI_CFG2_CPHA; + clrb |= spi->cfg->regs->cpha.mask; if (spi_dev->mode & SPI_LSB_FIRST) - cfg2_setb |= SPI_CFG2_LSBFRST; + setb |= spi->cfg->regs->lsb_first.mask; else - cfg2_clrb |= SPI_CFG2_LSBFRST; + clrb |= spi->cfg->regs->lsb_first.mask; dev_dbg(spi->dev, "cpol=%d cpha=%d lsb_first=%d cs_high=%d\n", spi_dev->mode & SPI_CPOL, @@ -628,11 +1036,12 @@ static int stm32_spi_prepare_msg(struct spi_master *master, spin_lock_irqsave(&spi->lock, flags); - if (cfg2_clrb || cfg2_setb) + /* CPOL, CPHA and LSB FIRST bits have common register */ + if (clrb || setb) writel_relaxed( - (readl_relaxed(spi->base + STM32_SPI_CFG2) & - ~cfg2_clrb) | cfg2_setb, - spi->base + STM32_SPI_CFG2); + (readl_relaxed(spi->base + spi->cfg->regs->cpol.reg) & + ~clrb) | setb, + spi->base + spi->cfg->regs->cpol.reg); spin_unlock_irqrestore(&spi->lock, flags); @@ -640,12 +1049,40 @@ static int stm32_spi_prepare_msg(struct spi_master *master, } /** - * stm32_spi_dma_cb - dma callback + * stm32f4_spi_dma_tx_cb - dma callback + * + * DMA callback is called when the transfer is complete for DMA TX channel. + */ +static void stm32f4_spi_dma_tx_cb(void *data) +{ + struct stm32_spi *spi = data; + + if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) { + spi_finalize_current_transfer(spi->master); + stm32f4_spi_disable(spi); + } +} + +/** + * stm32f4_spi_dma_rx_cb - dma callback + * + * DMA callback is called when the transfer is complete for DMA RX channel. + */ +static void stm32f4_spi_dma_rx_cb(void *data) +{ + struct stm32_spi *spi = data; + + spi_finalize_current_transfer(spi->master); + stm32f4_spi_disable(spi); +} + +/** + * stm32h7_spi_dma_cb - dma callback * * DMA callback is called when the transfer is complete or when an error * occurs. If the transfer is complete, EOT flag is raised. */ -static void stm32_spi_dma_cb(void *data) +static void stm32h7_spi_dma_cb(void *data) { struct stm32_spi *spi = data; unsigned long flags; @@ -653,11 +1090,11 @@ static void stm32_spi_dma_cb(void *data) spin_lock_irqsave(&spi->lock, flags); - sr = readl_relaxed(spi->base + STM32_SPI_SR); + sr = readl_relaxed(spi->base + STM32H7_SPI_SR); spin_unlock_irqrestore(&spi->lock, flags); - if (!(sr & SPI_SR_EOT)) + if (!(sr & STM32H7_SPI_SR_EOT)) dev_warn(spi->dev, "DMA error (sr=0x%08x)\n", sr); /* Now wait for EOT, or SUSP or OVR in case of error */ @@ -681,23 +1118,27 @@ static void stm32_spi_dma_config(struct stm32_spi *spi, else buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; - /* Valid for DMA Half or Full Fifo threshold */ - if (spi->cur_fthlv == 2) + if (spi->cfg->has_fifo) { + /* Valid for DMA Half or Full Fifo threshold */ + if (spi->cur_fthlv == 2) + maxburst = 1; + else + maxburst = spi->cur_fthlv; + } else { maxburst = 1; - else - maxburst = spi->cur_fthlv; + } memset(dma_conf, 0, sizeof(struct dma_slave_config)); dma_conf->direction = dir; if (dma_conf->direction == DMA_DEV_TO_MEM) { /* RX */ - dma_conf->src_addr = spi->phys_addr + STM32_SPI_RXDR; + dma_conf->src_addr = spi->phys_addr + spi->cfg->regs->rx.reg; dma_conf->src_addr_width = buswidth; dma_conf->src_maxburst = maxburst; dev_dbg(spi->dev, "Rx DMA config buswidth=%d, maxburst=%d\n", buswidth, maxburst); } else if (dma_conf->direction == DMA_MEM_TO_DEV) { /* TX */ - dma_conf->dst_addr = spi->phys_addr + STM32_SPI_TXDR; + dma_conf->dst_addr = spi->phys_addr + spi->cfg->regs->tx.reg; dma_conf->dst_addr_width = buswidth; dma_conf->dst_maxburst = maxburst; @@ -707,27 +1148,68 @@ static void stm32_spi_dma_config(struct stm32_spi *spi, } /** - * stm32_spi_transfer_one_irq - transfer a single spi_transfer using - * interrupts + * stm32f4_spi_transfer_one_irq - transfer a single spi_transfer using + * interrupts * * It must returns 0 if the transfer is finished or 1 if the transfer is still * in progress. */ -static int stm32_spi_transfer_one_irq(struct stm32_spi *spi) +static int stm32f4_spi_transfer_one_irq(struct stm32_spi *spi) +{ + unsigned long flags; + u32 cr2 = 0; + + /* Enable the interrupts relative to the current communication mode */ + if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) { + cr2 |= STM32F4_SPI_CR2_TXEIE; + } else if (spi->cur_comm == SPI_FULL_DUPLEX) { + /* In transmit-only mode, the OVR flag is set in the SR register + * since the received data are never read. Therefore set OVR + * interrupt only when rx buffer is available. + */ + cr2 |= STM32F4_SPI_CR2_RXNEIE | STM32F4_SPI_CR2_ERRIE; + } else { + return -EINVAL; + } + + spin_lock_irqsave(&spi->lock, flags); + + stm32_spi_set_bits(spi, STM32F4_SPI_CR2, cr2); + + stm32_spi_enable(spi); + + /* starting data transfer when buffer is loaded */ + if (spi->tx_buf) + stm32f4_spi_write_tx(spi); + + spin_unlock_irqrestore(&spi->lock, flags); + + return 1; +} + +/** + * stm32h7_spi_transfer_one_irq - transfer a single spi_transfer using + * interrupts + * + * It must returns 0 if the transfer is finished or 1 if the transfer is still + * in progress. + */ +static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi) { unsigned long flags; u32 ier = 0; /* Enable the interrupts relative to the current communication mode */ if (spi->tx_buf && spi->rx_buf) /* Full Duplex */ - ier |= SPI_IER_DXPIE; + ier |= STM32H7_SPI_IER_DXPIE; else if (spi->tx_buf) /* Half-Duplex TX dir or Simplex TX */ - ier |= SPI_IER_TXPIE; + ier |= STM32H7_SPI_IER_TXPIE; else if (spi->rx_buf) /* Half-Duplex RX dir or Simplex RX */ - ier |= SPI_IER_RXPIE; + ier |= STM32H7_SPI_IER_RXPIE; /* Enable the interrupts relative to the end of transfer */ - ier |= SPI_IER_EOTIE | SPI_IER_TXTFIE | SPI_IER_OVRIE | SPI_IER_MODFIE; + ier |= STM32H7_SPI_IER_EOTIE | STM32H7_SPI_IER_TXTFIE | + STM32H7_SPI_IER_OVRIE | STM32H7_SPI_IER_MODFIE; spin_lock_irqsave(&spi->lock, flags); @@ -735,11 +1217,11 @@ static int stm32_spi_transfer_one_irq(struct stm32_spi *spi) /* Be sure to have data in fifo before starting data transfer */ if (spi->tx_buf) - stm32_spi_write_txfifo(spi); + stm32h7_spi_write_txfifo(spi); - stm32_spi_set_bits(spi, STM32_SPI_CR1, SPI_CR1_CSTART); + stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); - writel_relaxed(ier, spi->base + STM32_SPI_IER); + writel_relaxed(ier, spi->base + STM32H7_SPI_IER); spin_unlock_irqrestore(&spi->lock, flags); @@ -747,6 +1229,43 @@ static int stm32_spi_transfer_one_irq(struct stm32_spi *spi) } /** + * stm32f4_spi_transfer_one_dma_start - Set SPI driver registers to start + * transfer using DMA + */ +static void stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi) +{ + /* In DMA mode end of transfer is handled by DMA TX or RX callback. */ + if (spi->cur_comm == SPI_SIMPLEX_RX || spi->cur_comm == SPI_3WIRE_RX || + spi->cur_comm == SPI_FULL_DUPLEX) { + /* + * In transmit-only mode, the OVR flag is set in the SR register + * since the received data are never read. Therefore set OVR + * interrupt only when rx buffer is available. + */ + stm32_spi_set_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_ERRIE); + } + + stm32_spi_enable(spi); +} + +/** + * stm32h7_spi_transfer_one_dma_start - Set SPI driver registers to start + * transfer using DMA + */ +static void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi) +{ + /* Enable the interrupts relative to the end of transfer */ + stm32_spi_set_bits(spi, STM32H7_SPI_IER, STM32H7_SPI_IER_EOTIE | + STM32H7_SPI_IER_TXTFIE | + STM32H7_SPI_IER_OVRIE | + STM32H7_SPI_IER_MODFIE); + + stm32_spi_enable(spi); + + stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); +} + +/** * stm32_spi_transfer_one_dma - transfer a single spi_transfer using DMA * * It must returns 0 if the transfer is finished or 1 if the transfer is still @@ -758,17 +1277,17 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, struct dma_slave_config tx_dma_conf, rx_dma_conf; struct dma_async_tx_descriptor *tx_dma_desc, *rx_dma_desc; unsigned long flags; - u32 ier = 0; spin_lock_irqsave(&spi->lock, flags); rx_dma_desc = NULL; - if (spi->rx_buf) { + if (spi->rx_buf && spi->dma_rx) { stm32_spi_dma_config(spi, &rx_dma_conf, DMA_DEV_TO_MEM); dmaengine_slave_config(spi->dma_rx, &rx_dma_conf); /* Enable Rx DMA request */ - stm32_spi_set_bits(spi, STM32_SPI_CFG1, SPI_CFG1_RXDMAEN); + stm32_spi_set_bits(spi, spi->cfg->regs->dma_rx_en.reg, + spi->cfg->regs->dma_rx_en.mask); rx_dma_desc = dmaengine_prep_slave_sg( spi->dma_rx, xfer->rx_sg.sgl, @@ -778,7 +1297,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, } tx_dma_desc = NULL; - if (spi->tx_buf) { + if (spi->tx_buf && spi->dma_tx) { stm32_spi_dma_config(spi, &tx_dma_conf, DMA_MEM_TO_DEV); dmaengine_slave_config(spi->dma_tx, &tx_dma_conf); @@ -789,12 +1308,15 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, DMA_PREP_INTERRUPT); } - if ((spi->tx_buf && !tx_dma_desc) || - (spi->rx_buf && !rx_dma_desc)) + if ((spi->tx_buf && spi->dma_tx && !tx_dma_desc) || + (spi->rx_buf && spi->dma_rx && !rx_dma_desc)) + goto dma_desc_error; + + if (spi->cur_comm == SPI_FULL_DUPLEX && (!tx_dma_desc || !rx_dma_desc)) goto dma_desc_error; if (rx_dma_desc) { - rx_dma_desc->callback = stm32_spi_dma_cb; + rx_dma_desc->callback = spi->cfg->dma_rx_cb; rx_dma_desc->callback_param = spi; if (dma_submit_error(dmaengine_submit(rx_dma_desc))) { @@ -806,8 +1328,9 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, } if (tx_dma_desc) { - if (spi->cur_comm == SPI_SIMPLEX_TX) { - tx_dma_desc->callback = stm32_spi_dma_cb; + if (spi->cur_comm == SPI_SIMPLEX_TX || + spi->cur_comm == SPI_3WIRE_TX) { + tx_dma_desc->callback = spi->cfg->dma_tx_cb; tx_dma_desc->callback_param = spi; } @@ -819,130 +1342,278 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, dma_async_issue_pending(spi->dma_tx); /* Enable Tx DMA request */ - stm32_spi_set_bits(spi, STM32_SPI_CFG1, SPI_CFG1_TXDMAEN); + stm32_spi_set_bits(spi, spi->cfg->regs->dma_tx_en.reg, + spi->cfg->regs->dma_tx_en.mask); } - /* Enable the interrupts relative to the end of transfer */ - ier |= SPI_IER_EOTIE | SPI_IER_TXTFIE | SPI_IER_OVRIE | SPI_IER_MODFIE; - writel_relaxed(ier, spi->base + STM32_SPI_IER); - - stm32_spi_enable(spi); - - stm32_spi_set_bits(spi, STM32_SPI_CR1, SPI_CR1_CSTART); + spi->cfg->transfer_one_dma_start(spi); spin_unlock_irqrestore(&spi->lock, flags); return 1; dma_submit_error: - if (spi->rx_buf) + if (spi->dma_rx) dmaengine_terminate_all(spi->dma_rx); dma_desc_error: - stm32_spi_clr_bits(spi, STM32_SPI_CFG1, SPI_CFG1_RXDMAEN); + stm32_spi_clr_bits(spi, spi->cfg->regs->dma_rx_en.reg, + spi->cfg->regs->dma_rx_en.mask); spin_unlock_irqrestore(&spi->lock, flags); dev_info(spi->dev, "DMA issue: fall back to irq transfer\n"); - return stm32_spi_transfer_one_irq(spi); + spi->cur_usedma = false; + return spi->cfg->transfer_one_irq(spi); } /** - * stm32_spi_transfer_one_setup - common setup to transfer a single - * spi_transfer either using DMA or - * interrupts. + * stm32f4_spi_set_bpw - Configure bits per word + * @spi: pointer to the spi controller data structure */ -static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, - struct spi_device *spi_dev, - struct spi_transfer *transfer) +static void stm32f4_spi_set_bpw(struct stm32_spi *spi) { - unsigned long flags; - u32 cfg1_clrb = 0, cfg1_setb = 0, cfg2_clrb = 0, cfg2_setb = 0; - u32 mode, nb_words; - int ret = 0; - - spin_lock_irqsave(&spi->lock, flags); + if (spi->cur_bpw == 16) + stm32_spi_set_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_DFF); + else + stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_DFF); +} - if (spi->cur_bpw != transfer->bits_per_word) { - u32 bpw, fthlv; +/** + * stm32h7_spi_set_bpw - configure bits per word + * @spi: pointer to the spi controller data structure + */ +static void stm32h7_spi_set_bpw(struct stm32_spi *spi) +{ + u32 bpw, fthlv; + u32 cfg1_clrb = 0, cfg1_setb = 0; - spi->cur_bpw = transfer->bits_per_word; - bpw = spi->cur_bpw - 1; + bpw = spi->cur_bpw - 1; - cfg1_clrb |= SPI_CFG1_DSIZE; - cfg1_setb |= (bpw << SPI_CFG1_DSIZE_SHIFT) & SPI_CFG1_DSIZE; + cfg1_clrb |= STM32H7_SPI_CFG1_DSIZE; + cfg1_setb |= (bpw << STM32H7_SPI_CFG1_DSIZE_SHIFT) & + STM32H7_SPI_CFG1_DSIZE; - spi->cur_fthlv = stm32_spi_prepare_fthlv(spi); - fthlv = spi->cur_fthlv - 1; + spi->cur_fthlv = stm32h7_spi_prepare_fthlv(spi); + fthlv = spi->cur_fthlv - 1; - cfg1_clrb |= SPI_CFG1_FTHLV; - cfg1_setb |= (fthlv << SPI_CFG1_FTHLV_SHIFT) & SPI_CFG1_FTHLV; - } + cfg1_clrb |= STM32H7_SPI_CFG1_FTHLV; + cfg1_setb |= (fthlv << STM32H7_SPI_CFG1_FTHLV_SHIFT) & + STM32H7_SPI_CFG1_FTHLV; - if (spi->cur_speed != transfer->speed_hz) { - int mbr; + writel_relaxed( + (readl_relaxed(spi->base + STM32H7_SPI_CFG1) & + ~cfg1_clrb) | cfg1_setb, + spi->base + STM32H7_SPI_CFG1); +} - /* Update spi->cur_speed with real clock speed */ - mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz); - if (mbr < 0) { - ret = mbr; - goto out; - } +/** + * stm32_spi_set_mbr - Configure baud rate divisor in master mode + * @spi: pointer to the spi controller data structure + * @mbrdiv: baud rate divisor value + */ +static void stm32_spi_set_mbr(struct stm32_spi *spi, u32 mbrdiv) +{ + u32 clrb = 0, setb = 0; - transfer->speed_hz = spi->cur_speed; + clrb |= spi->cfg->regs->br.mask; + setb |= ((u32)mbrdiv << spi->cfg->regs->br.shift) & + spi->cfg->regs->br.mask; - cfg1_clrb |= SPI_CFG1_MBR; - cfg1_setb |= ((u32)mbr << SPI_CFG1_MBR_SHIFT) & SPI_CFG1_MBR; - } + writel_relaxed((readl_relaxed(spi->base + spi->cfg->regs->br.reg) & + ~clrb) | setb, + spi->base + spi->cfg->regs->br.reg); +} - if (cfg1_clrb || cfg1_setb) - writel_relaxed((readl_relaxed(spi->base + STM32_SPI_CFG1) & - ~cfg1_clrb) | cfg1_setb, - spi->base + STM32_SPI_CFG1); +/** + * stm32_spi_communication_type - return transfer communication type + * @spi_dev: pointer to the spi device + * transfer: pointer to spi transfer + */ +static unsigned int stm32_spi_communication_type(struct spi_device *spi_dev, + struct spi_transfer *transfer) +{ + unsigned int type = SPI_FULL_DUPLEX; - mode = SPI_FULL_DUPLEX; if (spi_dev->mode & SPI_3WIRE) { /* MISO/MOSI signals shared */ /* * SPI_3WIRE and xfer->tx_buf != NULL and xfer->rx_buf != NULL - * is forbidden und unvalidated by SPI subsystem so depending + * is forbidden and unvalidated by SPI subsystem so depending * on the valid buffer, we can determine the direction of the * transfer. */ - mode = SPI_HALF_DUPLEX; if (!transfer->tx_buf) - stm32_spi_clr_bits(spi, STM32_SPI_CR1, SPI_CR1_HDDIR); - else if (!transfer->rx_buf) - stm32_spi_set_bits(spi, STM32_SPI_CR1, SPI_CR1_HDDIR); + type = SPI_3WIRE_RX; + else + type = SPI_3WIRE_TX; } else { if (!transfer->tx_buf) - mode = SPI_SIMPLEX_RX; + type = SPI_SIMPLEX_RX; else if (!transfer->rx_buf) - mode = SPI_SIMPLEX_TX; + type = SPI_SIMPLEX_TX; + } + + return type; +} + +/** + * stm32f4_spi_set_mode - configure communication mode + * @spi: pointer to the spi controller data structure + * @comm_type: type of communication to configure + */ +static int stm32f4_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type) +{ + if (comm_type == SPI_3WIRE_TX || comm_type == SPI_SIMPLEX_TX) { + stm32_spi_set_bits(spi, STM32F4_SPI_CR1, + STM32F4_SPI_CR1_BIDIMODE | + STM32F4_SPI_CR1_BIDIOE); + } else if (comm_type == SPI_FULL_DUPLEX) { + stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, + STM32F4_SPI_CR1_BIDIMODE | + STM32F4_SPI_CR1_BIDIOE); + } else { + return -EINVAL; } - if (spi->cur_comm != mode) { - spi->cur_comm = mode; - cfg2_clrb |= SPI_CFG2_COMM; - cfg2_setb |= (mode << SPI_CFG2_COMM_SHIFT) & SPI_CFG2_COMM; + return 0; +} + +/** + * stm32h7_spi_set_mode - configure communication mode + * @spi: pointer to the spi controller data structure + * @comm_type: type of communication to configure + */ +static int stm32h7_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type) +{ + u32 mode; + u32 cfg2_clrb = 0, cfg2_setb = 0; + + if (comm_type == SPI_3WIRE_RX) { + mode = STM32H7_SPI_HALF_DUPLEX; + stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_HDDIR); + } else if (comm_type == SPI_3WIRE_TX) { + mode = STM32H7_SPI_HALF_DUPLEX; + stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_HDDIR); + } else if (comm_type == SPI_SIMPLEX_RX) { + mode = STM32H7_SPI_SIMPLEX_RX; + } else if (comm_type == SPI_SIMPLEX_TX) { + mode = STM32H7_SPI_SIMPLEX_TX; + } else { + mode = STM32H7_SPI_FULL_DUPLEX; } - cfg2_clrb |= SPI_CFG2_MIDI; - if ((transfer->len > 1) && (spi->cur_midi > 0)) { + cfg2_clrb |= STM32H7_SPI_CFG2_COMM; + cfg2_setb |= (mode << STM32H7_SPI_CFG2_COMM_SHIFT) & + STM32H7_SPI_CFG2_COMM; + + writel_relaxed( + (readl_relaxed(spi->base + STM32H7_SPI_CFG2) & + ~cfg2_clrb) | cfg2_setb, + spi->base + STM32H7_SPI_CFG2); + + return 0; +} + +/** + * stm32h7_spi_data_idleness - configure minimum time delay inserted between two + * consecutive data frames in master mode + * @spi: pointer to the spi controller data structure + * @len: transfer len + */ +static void stm32h7_spi_data_idleness(struct stm32_spi *spi, u32 len) +{ + u32 cfg2_clrb = 0, cfg2_setb = 0; + + cfg2_clrb |= STM32H7_SPI_CFG2_MIDI; + if ((len > 1) && (spi->cur_midi > 0)) { u32 sck_period_ns = DIV_ROUND_UP(SPI_1HZ_NS, spi->cur_speed); u32 midi = min((u32)DIV_ROUND_UP(spi->cur_midi, sck_period_ns), - (u32)SPI_CFG2_MIDI >> SPI_CFG2_MIDI_SHIFT); + (u32)STM32H7_SPI_CFG2_MIDI >> + STM32H7_SPI_CFG2_MIDI_SHIFT); dev_dbg(spi->dev, "period=%dns, midi=%d(=%dns)\n", sck_period_ns, midi, midi * sck_period_ns); + cfg2_setb |= (midi << STM32H7_SPI_CFG2_MIDI_SHIFT) & + STM32H7_SPI_CFG2_MIDI; + } + + writel_relaxed((readl_relaxed(spi->base + STM32H7_SPI_CFG2) & + ~cfg2_clrb) | cfg2_setb, + spi->base + STM32H7_SPI_CFG2); +} + +/** + * stm32h7_spi_number_of_data - configure number of data at current transfer + * @spi: pointer to the spi controller data structure + * @len: transfer length + */ +static int stm32h7_spi_number_of_data(struct stm32_spi *spi, u32 nb_words) +{ + u32 cr2_clrb = 0, cr2_setb = 0; + + if (nb_words <= (STM32H7_SPI_CR2_TSIZE >> + STM32H7_SPI_CR2_TSIZE_SHIFT)) { + cr2_clrb |= STM32H7_SPI_CR2_TSIZE; + cr2_setb = nb_words << STM32H7_SPI_CR2_TSIZE_SHIFT; + writel_relaxed((readl_relaxed(spi->base + STM32H7_SPI_CR2) & + ~cr2_clrb) | cr2_setb, + spi->base + STM32H7_SPI_CR2); + } else { + return -EMSGSIZE; + } + + return 0; +} + +/** + * stm32_spi_transfer_one_setup - common setup to transfer a single + * spi_transfer either using DMA or + * interrupts. + */ +static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, + struct spi_device *spi_dev, + struct spi_transfer *transfer) +{ + unsigned long flags; + unsigned int comm_type; + int nb_words, ret = 0; + + spin_lock_irqsave(&spi->lock, flags); + + if (spi->cur_bpw != transfer->bits_per_word) { + spi->cur_bpw = transfer->bits_per_word; + spi->cfg->set_bpw(spi); + } - cfg2_setb |= (midi << SPI_CFG2_MIDI_SHIFT) & SPI_CFG2_MIDI; + if (spi->cur_speed != transfer->speed_hz) { + int mbr; + + /* Update spi->cur_speed with real clock speed */ + mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz, + spi->cfg->baud_rate_div_min, + spi->cfg->baud_rate_div_max); + if (mbr < 0) { + ret = mbr; + goto out; + } + + transfer->speed_hz = spi->cur_speed; + stm32_spi_set_mbr(spi, mbr); } - if (cfg2_clrb || cfg2_setb) - writel_relaxed((readl_relaxed(spi->base + STM32_SPI_CFG2) & - ~cfg2_clrb) | cfg2_setb, - spi->base + STM32_SPI_CFG2); + comm_type = stm32_spi_communication_type(spi_dev, transfer); + if (spi->cur_comm != comm_type) { + ret = spi->cfg->set_mode(spi, comm_type); + + if (ret < 0) + goto out; + + spi->cur_comm = comm_type; + } + + if (spi->cfg->set_data_idleness) + spi->cfg->set_data_idleness(spi, transfer->len); if (spi->cur_bpw <= 8) nb_words = transfer->len; @@ -950,13 +1621,11 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, nb_words = DIV_ROUND_UP(transfer->len * 8, 16); else nb_words = DIV_ROUND_UP(transfer->len * 8, 32); - nb_words <<= SPI_CR2_TSIZE_SHIFT; - if (nb_words <= SPI_CR2_TSIZE) { - writel_relaxed(nb_words, spi->base + STM32_SPI_CR2); - } else { - ret = -EMSGSIZE; - goto out; + if (spi->cfg->set_number_of_data) { + ret = spi->cfg->set_number_of_data(spi, nb_words); + if (ret < 0) + goto out; } spi->cur_xferlen = transfer->len; @@ -997,7 +1666,7 @@ static int stm32_spi_transfer_one(struct spi_master *master, spi->rx_len = spi->rx_buf ? transfer->len : 0; spi->cur_usedma = (master->can_dma && - stm32_spi_can_dma(master, spi_dev, transfer)); + master->can_dma(master, spi_dev, transfer)); ret = stm32_spi_transfer_one_setup(spi, spi_dev, transfer); if (ret) { @@ -1008,47 +1677,73 @@ static int stm32_spi_transfer_one(struct spi_master *master, if (spi->cur_usedma) return stm32_spi_transfer_one_dma(spi, transfer); else - return stm32_spi_transfer_one_irq(spi); + return spi->cfg->transfer_one_irq(spi); } /** * stm32_spi_unprepare_msg - relax the hardware - * - * Normally, if TSIZE has been configured, we should relax the hardware at the - * reception of the EOT interrupt. But in case of error, EOT will not be - * raised. So the subsystem unprepare_message call allows us to properly - * complete the transfer from an hardware point of view. */ static int stm32_spi_unprepare_msg(struct spi_master *master, struct spi_message *msg) { struct stm32_spi *spi = spi_master_get_devdata(master); - stm32_spi_disable(spi); + spi->cfg->disable(spi); + + return 0; +} + +/** + * stm32f4_spi_config - Configure SPI controller as SPI master + */ +static int stm32f4_spi_config(struct stm32_spi *spi) +{ + unsigned long flags; + + spin_lock_irqsave(&spi->lock, flags); + + /* Ensure I2SMOD bit is kept cleared */ + stm32_spi_clr_bits(spi, STM32F4_SPI_I2SCFGR, + STM32F4_SPI_I2SCFGR_I2SMOD); + + /* + * - SS input value high + * - transmitter half duplex direction + * - Set the master mode (default Motorola mode) + * - Consider 1 master/n slaves configuration and + * SS input value is determined by the SSI bit + */ + stm32_spi_set_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SSI | + STM32F4_SPI_CR1_BIDIOE | + STM32F4_SPI_CR1_MSTR | + STM32F4_SPI_CR1_SSM); + + spin_unlock_irqrestore(&spi->lock, flags); return 0; } /** - * stm32_spi_config - Configure SPI controller as SPI master + * stm32h7_spi_config - Configure SPI controller as SPI master */ -static int stm32_spi_config(struct stm32_spi *spi) +static int stm32h7_spi_config(struct stm32_spi *spi) { unsigned long flags; spin_lock_irqsave(&spi->lock, flags); /* Ensure I2SMOD bit is kept cleared */ - stm32_spi_clr_bits(spi, STM32_SPI_I2SCFGR, SPI_I2SCFGR_I2SMOD); + stm32_spi_clr_bits(spi, STM32H7_SPI_I2SCFGR, + STM32H7_SPI_I2SCFGR_I2SMOD); /* * - SS input value high * - transmitter half duplex direction * - automatic communication suspend when RX-Fifo is full */ - stm32_spi_set_bits(spi, STM32_SPI_CR1, SPI_CR1_SSI | - SPI_CR1_HDDIR | - SPI_CR1_MASRX); + stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SSI | + STM32H7_SPI_CR1_HDDIR | + STM32H7_SPI_CR1_MASRX); /* * - Set the master mode (default Motorola mode) @@ -1056,17 +1751,56 @@ static int stm32_spi_config(struct stm32_spi *spi) * SS input value is determined by the SSI bit * - keep control of all associated GPIOs */ - stm32_spi_set_bits(spi, STM32_SPI_CFG2, SPI_CFG2_MASTER | - SPI_CFG2_SSM | - SPI_CFG2_AFCNTR); + stm32_spi_set_bits(spi, STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_MASTER | + STM32H7_SPI_CFG2_SSM | + STM32H7_SPI_CFG2_AFCNTR); spin_unlock_irqrestore(&spi->lock, flags); return 0; } +static const struct stm32_spi_cfg stm32f4_spi_cfg = { + .regs = &stm32f4_spi_regspec, + .get_bpw_mask = stm32f4_spi_get_bpw_mask, + .disable = stm32f4_spi_disable, + .config = stm32f4_spi_config, + .set_bpw = stm32f4_spi_set_bpw, + .set_mode = stm32f4_spi_set_mode, + .transfer_one_dma_start = stm32f4_spi_transfer_one_dma_start, + .dma_tx_cb = stm32f4_spi_dma_tx_cb, + .dma_rx_cb = stm32f4_spi_dma_rx_cb, + .transfer_one_irq = stm32f4_spi_transfer_one_irq, + .irq_handler_event = stm32f4_spi_irq_event, + .irq_handler_thread = stm32f4_spi_irq_thread, + .baud_rate_div_min = STM32F4_SPI_BR_DIV_MIN, + .baud_rate_div_max = STM32F4_SPI_BR_DIV_MAX, + .has_fifo = false, +}; + +static const struct stm32_spi_cfg stm32h7_spi_cfg = { + .regs = &stm32h7_spi_regspec, + .get_fifo_size = stm32h7_spi_get_fifo_size, + .get_bpw_mask = stm32h7_spi_get_bpw_mask, + .disable = stm32h7_spi_disable, + .config = stm32h7_spi_config, + .set_bpw = stm32h7_spi_set_bpw, + .set_mode = stm32h7_spi_set_mode, + .set_data_idleness = stm32h7_spi_data_idleness, + .set_number_of_data = stm32h7_spi_number_of_data, + .transfer_one_dma_start = stm32h7_spi_transfer_one_dma_start, + .dma_rx_cb = stm32h7_spi_dma_cb, + .dma_tx_cb = stm32h7_spi_dma_cb, + .transfer_one_irq = stm32h7_spi_transfer_one_irq, + .irq_handler_thread = stm32h7_spi_irq_thread, + .baud_rate_div_min = STM32H7_SPI_MBR_DIV_MIN, + .baud_rate_div_max = STM32H7_SPI_MBR_DIV_MAX, + .has_fifo = true, +}; + static const struct of_device_id stm32_spi_of_match[] = { - { .compatible = "st,stm32h7-spi", }, + { .compatible = "st,stm32h7-spi", .data = (void *)&stm32h7_spi_cfg }, + { .compatible = "st,stm32f4-spi", .data = (void *)&stm32f4_spi_cfg }, {}, }; MODULE_DEVICE_TABLE(of, stm32_spi_of_match); @@ -1090,12 +1824,17 @@ static int stm32_spi_probe(struct platform_device *pdev) spi->master = master; spin_lock_init(&spi->lock); + spi->cfg = (const struct stm32_spi_cfg *) + of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev)->data; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); spi->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(spi->base)) { ret = PTR_ERR(spi->base); goto err_master_put; } + spi->phys_addr = (dma_addr_t)res->start; spi->irq = platform_get_irq(pdev, 0); @@ -1104,16 +1843,17 @@ static int stm32_spi_probe(struct platform_device *pdev) ret = -ENOENT; goto err_master_put; } - ret = devm_request_threaded_irq(&pdev->dev, spi->irq, NULL, - stm32_spi_irq, IRQF_ONESHOT, - pdev->name, master); + ret = devm_request_threaded_irq(&pdev->dev, spi->irq, + spi->cfg->irq_handler_event, + spi->cfg->irq_handler_thread, + IRQF_ONESHOT, pdev->name, master); if (ret) { dev_err(&pdev->dev, "irq%d request failed: %d\n", spi->irq, ret); goto err_master_put; } - spi->clk = devm_clk_get(&pdev->dev, 0); + spi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(spi->clk)) { ret = PTR_ERR(spi->clk); dev_err(&pdev->dev, "clk get failed: %d\n", ret); @@ -1139,9 +1879,10 @@ static int stm32_spi_probe(struct platform_device *pdev) reset_control_deassert(spi->rst); } - spi->fifo_size = stm32_spi_get_fifo_size(spi); + if (spi->cfg->has_fifo) + spi->fifo_size = spi->cfg->get_fifo_size(spi); - ret = stm32_spi_config(spi); + ret = spi->cfg->config(spi); if (ret) { dev_err(&pdev->dev, "controller configuration failed: %d\n", ret); @@ -1151,11 +1892,11 @@ static int stm32_spi_probe(struct platform_device *pdev) master->dev.of_node = pdev->dev.of_node; master->auto_runtime_pm = true; master->bus_num = pdev->id; - master->mode_bits = SPI_MODE_3 | SPI_CS_HIGH | SPI_LSB_FIRST | - SPI_3WIRE | SPI_LOOP; - master->bits_per_word_mask = stm32_spi_get_bpw_mask(spi); - master->max_speed_hz = spi->clk_rate / SPI_MBR_DIV_MIN; - master->min_speed_hz = spi->clk_rate / SPI_MBR_DIV_MAX; + master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | + SPI_3WIRE; + master->bits_per_word_mask = spi->cfg->get_bpw_mask(spi); + master->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min; + master->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max; master->setup = stm32_spi_setup; master->prepare_message = stm32_spi_prepare_msg; master->transfer_one = stm32_spi_transfer_one; @@ -1233,7 +1974,7 @@ static int stm32_spi_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct stm32_spi *spi = spi_master_get_devdata(master); - stm32_spi_disable(spi); + spi->cfg->disable(spi); if (master->dma_tx) dma_release_channel(master->dma_tx); diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 5f19016bbf10..b9fb6493cd6b 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -490,8 +490,8 @@ static void ti_qspi_enable_memory_map(struct spi_device *spi) ti_qspi_write(qspi, MM_SWITCH, QSPI_SPI_SWITCH_REG); if (qspi->ctrl_base) { regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg, - MEM_CS_EN(spi->chip_select), - MEM_CS_MASK); + MEM_CS_MASK, + MEM_CS_EN(spi->chip_select)); } qspi->mmap_enabled = true; } @@ -503,7 +503,7 @@ static void ti_qspi_disable_memory_map(struct spi_device *spi) ti_qspi_write(qspi, 0, QSPI_SPI_SWITCH_REG); if (qspi->ctrl_base) regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg, - 0, MEM_CS_MASK); + MEM_CS_MASK, 0); qspi->mmap_enabled = false; } diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 97d137591b18..e7e8ea1edcce 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1008,6 +1008,9 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) /* RX */ dma->sg_rx_p = kcalloc(num, sizeof(*dma->sg_rx_p), GFP_ATOMIC); + if (!dma->sg_rx_p) + return; + sg_init_table(dma->sg_rx_p, num); /* Initialize SG table */ /* offset, length setting */ sg = dma->sg_rx_p; @@ -1068,6 +1071,9 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) } dma->sg_tx_p = kcalloc(num, sizeof(*dma->sg_tx_p), GFP_ATOMIC); + if (!dma->sg_tx_p) + return; + sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */ /* offset, length setting */ sg = dma->sg_tx_p; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9a7def7c3237..93986f879b09 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -19,6 +19,7 @@ #include <linux/spi/spi.h> #include <linux/spi/spi-mem.h> #include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/pm_runtime.h> #include <linux/pm_domain.h> #include <linux/property.h> @@ -578,7 +579,10 @@ int spi_add_device(struct spi_device *spi) goto done; } - if (ctlr->cs_gpios) + /* Descriptors take precedence */ + if (ctlr->cs_gpiods) + spi->cs_gpiod = ctlr->cs_gpiods[spi->chip_select]; + else if (ctlr->cs_gpios) spi->cs_gpio = ctlr->cs_gpios[spi->chip_select]; /* Drivers may modify this initial i/o setup, but will @@ -772,10 +776,21 @@ static void spi_set_cs(struct spi_device *spi, bool enable) if (spi->mode & SPI_CS_HIGH) enable = !enable; - if (gpio_is_valid(spi->cs_gpio)) { - /* Honour the SPI_NO_CS flag */ - if (!(spi->mode & SPI_NO_CS)) - gpio_set_value(spi->cs_gpio, !enable); + if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio)) { + /* + * Honour the SPI_NO_CS flag and invert the enable line, as + * active low is default for SPI. Execution paths that handle + * polarity inversion in gpiolib (such as device tree) will + * enforce active high using the SPI_CS_HIGH resulting in a + * double inversion through the code above. + */ + if (!(spi->mode & SPI_NO_CS)) { + if (spi->cs_gpiod) + gpiod_set_value_cansleep(spi->cs_gpiod, + !enable); + else + gpio_set_value_cansleep(spi->cs_gpio, !enable); + } /* Some SPI masters need both GPIO CS & slave_select */ if ((spi->controller->flags & SPI_MASTER_GPIO_SS) && spi->controller->set_cs) @@ -1615,13 +1630,21 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, spi->mode |= SPI_CPHA; if (of_property_read_bool(nc, "spi-cpol")) spi->mode |= SPI_CPOL; - if (of_property_read_bool(nc, "spi-cs-high")) - spi->mode |= SPI_CS_HIGH; if (of_property_read_bool(nc, "spi-3wire")) spi->mode |= SPI_3WIRE; if (of_property_read_bool(nc, "spi-lsb-first")) spi->mode |= SPI_LSB_FIRST; + /* + * For descriptors associated with the device, polarity inversion is + * handled in the gpiolib, so all chip selects are "active high" in + * the logical sense, the gpiolib will invert the line if need be. + */ + if (ctlr->use_gpio_descriptors) + spi->mode |= SPI_CS_HIGH; + else if (of_property_read_bool(nc, "spi-cs-high")) + spi->mode |= SPI_CS_HIGH; + /* Device DUAL/QUAD mode */ if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) { switch (value) { @@ -2137,6 +2160,60 @@ static int of_spi_register_master(struct spi_controller *ctlr) } #endif +/** + * spi_get_gpio_descs() - grab chip select GPIOs for the master + * @ctlr: The SPI master to grab GPIO descriptors for + */ +static int spi_get_gpio_descs(struct spi_controller *ctlr) +{ + int nb, i; + struct gpio_desc **cs; + struct device *dev = &ctlr->dev; + + nb = gpiod_count(dev, "cs"); + ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect); + + /* No GPIOs at all is fine, else return the error */ + if (nb == 0 || nb == -ENOENT) + return 0; + else if (nb < 0) + return nb; + + cs = devm_kcalloc(dev, ctlr->num_chipselect, sizeof(*cs), + GFP_KERNEL); + if (!cs) + return -ENOMEM; + ctlr->cs_gpiods = cs; + + for (i = 0; i < nb; i++) { + /* + * Most chipselects are active low, the inverted + * semantics are handled by special quirks in gpiolib, + * so initializing them GPIOD_OUT_LOW here means + * "unasserted", in most cases this will drive the physical + * line high. + */ + cs[i] = devm_gpiod_get_index_optional(dev, "cs", i, + GPIOD_OUT_LOW); + + if (cs[i]) { + /* + * If we find a CS GPIO, name it after the device and + * chip select line. + */ + char *gpioname; + + gpioname = devm_kasprintf(dev, GFP_KERNEL, "%s CS%d", + dev_name(dev), i); + if (!gpioname) + return -ENOMEM; + gpiod_set_consumer_name(cs[i], gpioname); + } + } + + return 0; +} + static int spi_controller_check_ops(struct spi_controller *ctlr) { /* @@ -2199,9 +2276,21 @@ int spi_register_controller(struct spi_controller *ctlr) return status; if (!spi_controller_is_slave(ctlr)) { - status = of_spi_register_master(ctlr); - if (status) - return status; + if (ctlr->use_gpio_descriptors) { + status = spi_get_gpio_descs(ctlr); + if (status) + return status; + /* + * A controller using GPIO descriptors always + * supports SPI_CS_HIGH if need be. + */ + ctlr->mode_bits |= SPI_CS_HIGH; + } else { + /* Legacy code path for GPIOs from DT */ + status = of_spi_register_master(ctlr); + if (status) + return status; + } } /* even if it's just one always-selected device, there must @@ -2915,6 +3004,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) * cs_change is set for each transfer. */ if ((spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) || + spi->cs_gpiod || gpio_is_valid(spi->cs_gpio))) { size_t maxsize; int ret; @@ -2961,6 +3051,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) * it is not set for this transfer. * Set transfer tx_nbits and rx_nbits as single transfer default * (SPI_NBITS_SINGLE) if it is not set for this transfer. + * Ensure transfer word_delay is at least as long as that required by + * device itself. */ message->frame_length = 0; list_for_each_entry(xfer, &message->transfers, transfer_list) { @@ -3031,6 +3123,9 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) !(spi->mode & SPI_RX_QUAD)) return -EINVAL; } + + if (xfer->word_delay_usecs < spi->word_delay_usecs) + xfer->word_delay_usecs = spi->word_delay_usecs; } message->status = -EINPROGRESS; diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index a0802de8c3a1..6f5afab7c1a1 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -248,10 +248,10 @@ static void ion_dma_buf_detatch(struct dma_buf *dmabuf, struct ion_dma_buf_attachment *a = attachment->priv; struct ion_buffer *buffer = dmabuf->priv; - free_duped_table(a->table); mutex_lock(&buffer->lock); list_del(&a->list); mutex_unlock(&buffer->lock); + free_duped_table(a->table); kfree(a); } diff --git a/drivers/staging/mt7621-eth/mtk_eth_soc.c b/drivers/staging/mt7621-eth/mtk_eth_soc.c index 21a76a8ccc26..6027b19f7bc2 100644 --- a/drivers/staging/mt7621-eth/mtk_eth_soc.c +++ b/drivers/staging/mt7621-eth/mtk_eth_soc.c @@ -1396,8 +1396,7 @@ static int mtk_qdma_tx_alloc_tx(struct mtk_eth *eth) if (!ring->tx_buf) goto no_tx_mem; - ring->tx_dma = dma_zalloc_coherent(eth->dev, - ring->tx_ring_size * sz, + ring->tx_dma = dma_alloc_coherent(eth->dev, ring->tx_ring_size * sz, &ring->tx_phys, GFP_ATOMIC | __GFP_ZERO); if (!ring->tx_dma) diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 2848fa71a33d..d6248eecf123 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -170,7 +170,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev) return -ENODEV; priv->last_link = 0; - phy_start_aneg(phydev); + phy_start(phydev); return 0; no_phy: diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index 364d6ea14bf8..2f90f60f1681 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -154,7 +154,7 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe) pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset; - crypto_ops = try_then_request_module(lib80211_get_crypto_ops("WEP"), "lib80211_crypt_wep"); + crypto_ops = lib80211_get_crypto_ops("WEP"); if (!crypto_ops) return; @@ -210,7 +210,7 @@ int rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe) void *crypto_private = NULL; int status = _SUCCESS; const int keyindex = prxattrib->key_index; - struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("WEP"), "lib80211_crypt_wep"); + struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("WEP"); char iv[4], icv[4]; if (!crypto_ops) { @@ -1291,7 +1291,7 @@ u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe) struct sk_buff *skb = ((struct recv_frame *)precvframe)->pkt; void *crypto_private = NULL; u8 *key, *pframe = skb->data; - struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("CCMP"), "lib80211_crypt_ccmp"); + struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("CCMP"); struct security_priv *psecuritypriv = &padapter->securitypriv; char iv[8], icv[8]; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 28cbd6b3d26c..dfee6985efa6 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -35,6 +35,7 @@ static const struct usb_device_id rtw_usb_id_tbl[] = { {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(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */ {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */ {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */ diff --git a/drivers/staging/rtl8723bs/include/ieee80211.h b/drivers/staging/rtl8723bs/include/ieee80211.h index bcc8dfa8e672..9efb4dcb9d3a 100644 --- a/drivers/staging/rtl8723bs/include/ieee80211.h +++ b/drivers/staging/rtl8723bs/include/ieee80211.h @@ -850,18 +850,18 @@ enum ieee80211_state { #define IP_FMT "%pI4" #define IP_ARG(x) (x) -extern __inline int is_multicast_mac_addr(const u8 *addr) +static inline int is_multicast_mac_addr(const u8 *addr) { return ((addr[0] != 0xff) && (0x01 & addr[0])); } -extern __inline int is_broadcast_mac_addr(const u8 *addr) +static inline int is_broadcast_mac_addr(const u8 *addr) { return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \ (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); } -extern __inline int is_zero_mac_addr(const u8 *addr) +static inline int is_zero_mac_addr(const u8 *addr) { return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && \ (addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00)); diff --git a/drivers/staging/rtl8723bs/os_dep/osdep_service.c b/drivers/staging/rtl8723bs/os_dep/osdep_service.c index e14d7cc411c9..73b87da15eb2 100644 --- a/drivers/staging/rtl8723bs/os_dep/osdep_service.c +++ b/drivers/staging/rtl8723bs/os_dep/osdep_service.c @@ -137,7 +137,7 @@ static int isFileReadable(char *path) ret = PTR_ERR(fp); } else { - oldfs = get_fs(); set_fs(get_ds()); + oldfs = get_fs(); set_fs(KERNEL_DS); if (1!=readFile(fp, &buf, 1)) ret = -EINVAL; @@ -165,7 +165,7 @@ static int retriveFromFile(char *path, u8 *buf, u32 sz) if (0 == (ret =openFile(&fp, path, O_RDONLY, 0))) { DBG_871X("%s openFile path:%s fp =%p\n", __func__, path , fp); - oldfs = get_fs(); set_fs(get_ds()); + oldfs = get_fs(); set_fs(KERNEL_DS); ret =readFile(fp, buf, sz); set_fs(oldfs); closeFile(fp); diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c index 7c03b69b8ed3..6d02904de63f 100644 --- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c +++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c @@ -22,7 +22,7 @@ static const struct sdio_device_id sdio_ids[] = { SDIO_DEVICE(0x024c, 0xb723), }, { /* end: all zeroes */ }, }; -static const struct acpi_device_id acpi_ids[] __used = { +static const struct acpi_device_id acpi_ids[] = { {"OBDA8723", 0x0000}, {} }; diff --git a/drivers/staging/speakup/spk_ttyio.c b/drivers/staging/speakup/spk_ttyio.c index c92bbd05516e..005de0024dd4 100644 --- a/drivers/staging/speakup/spk_ttyio.c +++ b/drivers/staging/speakup/spk_ttyio.c @@ -265,7 +265,8 @@ static void spk_ttyio_send_xchar(char ch) return; } - speakup_tty->ops->send_xchar(speakup_tty, ch); + if (speakup_tty->ops->send_xchar) + speakup_tty->ops->send_xchar(speakup_tty, ch); mutex_unlock(&speakup_tty_mutex); } @@ -277,7 +278,8 @@ static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear) return; } - speakup_tty->ops->tiocmset(speakup_tty, set, clear); + if (speakup_tty->ops->tiocmset) + speakup_tty->ops->tiocmset(speakup_tty, set, clear); mutex_unlock(&speakup_tty_mutex); } diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 338b6e952515..dd4898861b83 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -407,10 +407,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type) /* Allocate enough storage to hold the page pointers and the page * list */ - pagelist = dma_zalloc_coherent(g_dev, - pagelist_size, - &dma_addr, - GFP_KERNEL); + pagelist = dma_alloc_coherent(g_dev, pagelist_size, &dma_addr, + GFP_KERNEL); vchiq_log_trace(vchiq_arm_log_level, "%s - %pK", __func__, pagelist); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 9e17ec651bde..53f5a1cb4636 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -446,6 +446,7 @@ remote_event_wait(wait_queue_head_t *wq, struct remote_event *event) static inline void remote_event_signal_local(wait_queue_head_t *wq, struct remote_event *event) { + event->fired = 1; event->armed = 0; wake_up_all(wq); } diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 1ab0e8562d40..c9097e7367d8 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -440,12 +440,9 @@ static bool device_init_rings(struct vnt_private *priv) void *vir_pool; /*allocate all RD/TD rings a single pool*/ - vir_pool = dma_zalloc_coherent(&priv->pcid->dev, - priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + - priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + - priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + - priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc), - &priv->pool_dma, GFP_ATOMIC); + vir_pool = dma_alloc_coherent(&priv->pcid->dev, + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc), + &priv->pool_dma, GFP_ATOMIC); if (!vir_pool) { dev_err(&priv->pcid->dev, "allocate desc dma memory failed\n"); return false; @@ -459,13 +456,9 @@ static bool device_init_rings(struct vnt_private *priv) priv->rd1_pool_dma = priv->rd0_pool_dma + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc); - priv->tx0_bufs = dma_zalloc_coherent(&priv->pcid->dev, - priv->opts.tx_descs[0] * PKT_BUF_SZ + - priv->opts.tx_descs[1] * PKT_BUF_SZ + - CB_BEACON_BUF_SIZE + - CB_MAX_BUF_SIZE, - &priv->tx_bufs_dma0, - GFP_ATOMIC); + priv->tx0_bufs = dma_alloc_coherent(&priv->pcid->dev, + priv->opts.tx_descs[0] * PKT_BUF_SZ + priv->opts.tx_descs[1] * PKT_BUF_SZ + CB_BEACON_BUF_SIZE + CB_MAX_BUF_SIZE, + &priv->tx_bufs_dma0, GFP_ATOMIC); if (!priv->tx0_bufs) { dev_err(&priv->pcid->dev, "allocate buf dma memory failed\n"); diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 70c854d939ce..3d0badc34825 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -36,7 +36,7 @@ struct wilc_op_mode { struct wilc_reg_frame { bool reg; u8 reg_id; - __le32 frame_type; + __le16 frame_type; } __packed; struct wilc_drv_handler { @@ -1744,7 +1744,6 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, ARRAY_SIZE(wid_list), wilc_get_vif_idx(vif)); - kfree(gtk_key); } else if (mode == WILC_STATION_MODE) { struct wid wid; @@ -1754,9 +1753,9 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, wid.val = (u8 *)gtk_key; result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); - kfree(gtk_key); } + kfree(gtk_key); return result; } diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 3c5e9e030cad..489e5a5038f8 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1252,21 +1252,22 @@ static u32 init_chip(struct net_device *dev) ret = wilc->hif_func->hif_read_reg(wilc, 0x1118, ®); if (!ret) { netdev_err(dev, "fail read reg 0x1118\n"); - return ret; + goto release; } reg |= BIT(0); ret = wilc->hif_func->hif_write_reg(wilc, 0x1118, reg); if (!ret) { netdev_err(dev, "fail write reg 0x1118\n"); - return ret; + goto release; } ret = wilc->hif_func->hif_write_reg(wilc, 0xc0000, 0x71); if (!ret) { netdev_err(dev, "fail write reg 0xc0000\n"); - return ret; + goto release; } } +release: release_bus(wilc, WILC_BUS_RELEASE_ONLY); return ret; diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 984941e036c8..bd15a564fe24 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -714,7 +714,7 @@ static int __init iscsi_target_init_module(void) sizeof(struct iscsi_queue_req), __alignof__(struct iscsi_queue_req), 0, NULL); if (!lio_qr_cache) { - pr_err("nable to kmem_cache_create() for" + pr_err("Unable to kmem_cache_create() for" " lio_qr_cache\n"); goto bitmap_out; } diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 72016d0dfca5..8e7fffbb8802 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -852,6 +852,12 @@ static ssize_t pi_prot_type_store(struct config_item *item, return count; } +/* always zero, but attr needs to remain RW to avoid userspace breakage */ +static ssize_t pi_prot_format_show(struct config_item *item, char *page) +{ + return snprintf(page, PAGE_SIZE, "0\n"); +} + static ssize_t pi_prot_format_store(struct config_item *item, const char *page, size_t count) { @@ -1132,7 +1138,7 @@ CONFIGFS_ATTR(, emulate_3pc); CONFIGFS_ATTR(, emulate_pr); CONFIGFS_ATTR(, pi_prot_type); CONFIGFS_ATTR_RO(, hw_pi_prot_type); -CONFIGFS_ATTR_WO(, pi_prot_format); +CONFIGFS_ATTR(, pi_prot_format); CONFIGFS_ATTR(, pi_prot_verify); CONFIGFS_ATTR(, enforce_pr_isids); CONFIGFS_ATTR(, is_nonrot); diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 1e6d24943565..5831e0eecea1 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -148,7 +148,7 @@ struct tcmu_dev { size_t ring_size; struct mutex cmdr_lock; - struct list_head cmdr_queue; + struct list_head qfull_queue; uint32_t dbi_max; uint32_t dbi_thresh; @@ -159,6 +159,7 @@ struct tcmu_dev { struct timer_list cmd_timer; unsigned int cmd_time_out; + struct list_head inflight_queue; struct timer_list qfull_timer; int qfull_time_out; @@ -179,7 +180,7 @@ struct tcmu_dev { struct tcmu_cmd { struct se_cmd *se_cmd; struct tcmu_dev *tcmu_dev; - struct list_head cmdr_queue_entry; + struct list_head queue_entry; uint16_t cmd_id; @@ -192,6 +193,7 @@ struct tcmu_cmd { unsigned long deadline; #define TCMU_CMD_BIT_EXPIRED 0 +#define TCMU_CMD_BIT_INFLIGHT 1 unsigned long flags; }; /* @@ -586,7 +588,7 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd) if (!tcmu_cmd) return NULL; - INIT_LIST_HEAD(&tcmu_cmd->cmdr_queue_entry); + INIT_LIST_HEAD(&tcmu_cmd->queue_entry); tcmu_cmd->se_cmd = se_cmd; tcmu_cmd->tcmu_dev = udev; @@ -915,11 +917,13 @@ setup_timer: return 0; tcmu_cmd->deadline = round_jiffies_up(jiffies + msecs_to_jiffies(tmo)); - mod_timer(timer, tcmu_cmd->deadline); + if (!timer_pending(timer)) + mod_timer(timer, tcmu_cmd->deadline); + return 0; } -static int add_to_cmdr_queue(struct tcmu_cmd *tcmu_cmd) +static int add_to_qfull_queue(struct tcmu_cmd *tcmu_cmd) { struct tcmu_dev *udev = tcmu_cmd->tcmu_dev; unsigned int tmo; @@ -942,7 +946,7 @@ static int add_to_cmdr_queue(struct tcmu_cmd *tcmu_cmd) if (ret) return ret; - list_add_tail(&tcmu_cmd->cmdr_queue_entry, &udev->cmdr_queue); + list_add_tail(&tcmu_cmd->queue_entry, &udev->qfull_queue); pr_debug("adding cmd %u on dev %s to ring space wait queue\n", tcmu_cmd->cmd_id, udev->name); return 0; @@ -999,7 +1003,7 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err) base_command_size = tcmu_cmd_get_base_cmd_size(tcmu_cmd->dbi_cnt); command_size = tcmu_cmd_get_cmd_size(tcmu_cmd, base_command_size); - if (!list_empty(&udev->cmdr_queue)) + if (!list_empty(&udev->qfull_queue)) goto queue; mb = udev->mb_addr; @@ -1096,13 +1100,16 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err) UPDATE_HEAD(mb->cmd_head, command_size, udev->cmdr_size); tcmu_flush_dcache_range(mb, sizeof(*mb)); + list_add_tail(&tcmu_cmd->queue_entry, &udev->inflight_queue); + set_bit(TCMU_CMD_BIT_INFLIGHT, &tcmu_cmd->flags); + /* TODO: only if FLUSH and FUA? */ uio_event_notify(&udev->uio_info); return 0; queue: - if (add_to_cmdr_queue(tcmu_cmd)) { + if (add_to_qfull_queue(tcmu_cmd)) { *scsi_err = TCM_OUT_OF_RESOURCES; return -1; } @@ -1145,6 +1152,8 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry * if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) goto out; + list_del_init(&cmd->queue_entry); + tcmu_cmd_reset_dbi_cur(cmd); if (entry->hdr.uflags & TCMU_UFLAG_UNKNOWN_OP) { @@ -1194,9 +1203,29 @@ out: tcmu_free_cmd(cmd); } +static void tcmu_set_next_deadline(struct list_head *queue, + struct timer_list *timer) +{ + struct tcmu_cmd *tcmu_cmd, *tmp_cmd; + unsigned long deadline = 0; + + list_for_each_entry_safe(tcmu_cmd, tmp_cmd, queue, queue_entry) { + if (!time_after(jiffies, tcmu_cmd->deadline)) { + deadline = tcmu_cmd->deadline; + break; + } + } + + if (deadline) + mod_timer(timer, deadline); + else + del_timer(timer); +} + static unsigned int tcmu_handle_completions(struct tcmu_dev *udev) { struct tcmu_mailbox *mb; + struct tcmu_cmd *cmd; int handled = 0; if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) { @@ -1210,7 +1239,6 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev) while (udev->cmdr_last_cleaned != READ_ONCE(mb->cmd_tail)) { struct tcmu_cmd_entry *entry = (void *) mb + CMDR_OFF + udev->cmdr_last_cleaned; - struct tcmu_cmd *cmd; tcmu_flush_dcache_range(entry, sizeof(*entry)); @@ -1243,7 +1271,7 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev) /* no more pending commands */ del_timer(&udev->cmd_timer); - if (list_empty(&udev->cmdr_queue)) { + if (list_empty(&udev->qfull_queue)) { /* * no more pending or waiting commands so try to * reclaim blocks if needed. @@ -1252,6 +1280,8 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev) tcmu_global_max_blocks) schedule_delayed_work(&tcmu_unmap_work, 0); } + } else if (udev->cmd_time_out) { + tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer); } return handled; @@ -1271,7 +1301,7 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data) if (!time_after(jiffies, cmd->deadline)) return 0; - is_running = list_empty(&cmd->cmdr_queue_entry); + is_running = test_bit(TCMU_CMD_BIT_INFLIGHT, &cmd->flags); se_cmd = cmd->se_cmd; if (is_running) { @@ -1287,9 +1317,9 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data) * target_complete_cmd will translate this to LUN COMM FAILURE */ scsi_status = SAM_STAT_CHECK_CONDITION; + list_del_init(&cmd->queue_entry); } else { - list_del_init(&cmd->cmdr_queue_entry); - + list_del_init(&cmd->queue_entry); idr_remove(&udev->commands, id); tcmu_free_cmd(cmd); scsi_status = SAM_STAT_TASK_SET_FULL; @@ -1372,7 +1402,8 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name) INIT_LIST_HEAD(&udev->node); INIT_LIST_HEAD(&udev->timedout_entry); - INIT_LIST_HEAD(&udev->cmdr_queue); + INIT_LIST_HEAD(&udev->qfull_queue); + INIT_LIST_HEAD(&udev->inflight_queue); idr_init(&udev->commands); timer_setup(&udev->qfull_timer, tcmu_qfull_timedout, 0); @@ -1383,7 +1414,7 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name) return &udev->se_dev; } -static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail) +static bool run_qfull_queue(struct tcmu_dev *udev, bool fail) { struct tcmu_cmd *tcmu_cmd, *tmp_cmd; LIST_HEAD(cmds); @@ -1391,15 +1422,15 @@ static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail) sense_reason_t scsi_ret; int ret; - if (list_empty(&udev->cmdr_queue)) + if (list_empty(&udev->qfull_queue)) return true; pr_debug("running %s's cmdr queue forcefail %d\n", udev->name, fail); - list_splice_init(&udev->cmdr_queue, &cmds); + list_splice_init(&udev->qfull_queue, &cmds); - list_for_each_entry_safe(tcmu_cmd, tmp_cmd, &cmds, cmdr_queue_entry) { - list_del_init(&tcmu_cmd->cmdr_queue_entry); + list_for_each_entry_safe(tcmu_cmd, tmp_cmd, &cmds, queue_entry) { + list_del_init(&tcmu_cmd->queue_entry); pr_debug("removing cmd %u on dev %s from queue\n", tcmu_cmd->cmd_id, udev->name); @@ -1437,14 +1468,13 @@ static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail) * cmd was requeued, so just put all cmds back in * the queue */ - list_splice_tail(&cmds, &udev->cmdr_queue); + list_splice_tail(&cmds, &udev->qfull_queue); drained = false; - goto done; + break; } } - if (list_empty(&udev->cmdr_queue)) - del_timer(&udev->qfull_timer); -done: + + tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer); return drained; } @@ -1454,7 +1484,7 @@ static int tcmu_irqcontrol(struct uio_info *info, s32 irq_on) mutex_lock(&udev->cmdr_lock); tcmu_handle_completions(udev); - run_cmdr_queue(udev, false); + run_qfull_queue(udev, false); mutex_unlock(&udev->cmdr_lock); return 0; @@ -1982,7 +2012,7 @@ static void tcmu_block_dev(struct tcmu_dev *udev) /* complete IO that has executed successfully */ tcmu_handle_completions(udev); /* fail IO waiting to be queued */ - run_cmdr_queue(udev, true); + run_qfull_queue(udev, true); unlock: mutex_unlock(&udev->cmdr_lock); @@ -1997,7 +2027,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level) mutex_lock(&udev->cmdr_lock); idr_for_each_entry(&udev->commands, cmd, i) { - if (!list_empty(&cmd->cmdr_queue_entry)) + if (!test_bit(TCMU_CMD_BIT_INFLIGHT, &cmd->flags)) continue; pr_debug("removing cmd %u on dev %s from ring (is expired %d)\n", @@ -2006,6 +2036,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level) idr_remove(&udev->commands, i); if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) { + list_del_init(&cmd->queue_entry); if (err_level == 1) { /* * Userspace was not able to start the @@ -2666,6 +2697,10 @@ static void check_timedout_devices(void) mutex_lock(&udev->cmdr_lock); idr_for_each(&udev->commands, tcmu_check_expired_cmd, NULL); + + tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer); + tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer); + mutex_unlock(&udev->cmdr_lock); spin_lock_bh(&timed_out_udevs_lock); diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index e5efce3c08e2..947f9b28de9e 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -699,8 +699,10 @@ static int __init optee_driver_init(void) return -ENODEV; np = of_find_matching_node(fw_np, optee_match); - if (!np || !of_device_is_available(np)) + if (!np || !of_device_is_available(np)) { + of_node_put(np); return -ENODEV; + } optee = optee_probe(np); of_node_put(np); diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index dfd23245f778..6fff16113628 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -774,7 +774,7 @@ of_cpufreq_cooling_register(struct cpufreq_policy *policy) cdev = __cpufreq_cooling_register(np, policy, capacitance); if (IS_ERR(cdev)) { - pr_err("cpu_cooling: cpu%d is not running as cooling device: %ld\n", + pr_err("cpu_cooling: cpu%d failed to register as cooling device: %ld\n", policy->cpu, PTR_ERR(cdev)); cdev = NULL; } diff --git a/drivers/thermal/intel/int340x_thermal/Kconfig b/drivers/thermal/intel/int340x_thermal/Kconfig index 0582bd12a239..0ca908d12750 100644 --- a/drivers/thermal/intel/int340x_thermal/Kconfig +++ b/drivers/thermal/intel/int340x_thermal/Kconfig @@ -4,7 +4,7 @@ config INT340X_THERMAL tristate "ACPI INT340X thermal drivers" - depends on X86 && ACPI + depends on X86 && ACPI && PCI select THERMAL_GOV_USER_SPACE select ACPI_THERMAL_REL select ACPI_FAN diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c index 284cf2c5a8fd..8e1cf4d789be 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c @@ -84,7 +84,12 @@ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \ struct pci_dev *pci_dev; \ struct platform_device *pdev; \ struct proc_thermal_device *proc_dev; \ -\ + \ + if (proc_thermal_emum_mode == PROC_THERMAL_NONE) { \ + dev_warn(dev, "Attempted to get power limit before device was initialized!\n"); \ + return 0; \ + } \ + \ if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { \ pdev = to_platform_device(dev); \ proc_dev = platform_get_drvdata(pdev); \ @@ -298,11 +303,6 @@ static int proc_thermal_add(struct device *dev, *priv = proc_priv; ret = proc_thermal_read_ppcc(proc_priv); - if (!ret) { - ret = sysfs_create_group(&dev->kobj, - &power_limit_attribute_group); - - } if (ret) return ret; @@ -316,8 +316,7 @@ static int proc_thermal_add(struct device *dev, proc_priv->int340x_zone = int340x_thermal_zone_add(adev, ops); if (IS_ERR(proc_priv->int340x_zone)) { - ret = PTR_ERR(proc_priv->int340x_zone); - goto remove_group; + return PTR_ERR(proc_priv->int340x_zone); } else ret = 0; @@ -331,9 +330,6 @@ static int proc_thermal_add(struct device *dev, remove_zone: int340x_thermal_zone_remove(proc_priv->int340x_zone); -remove_group: - sysfs_remove_group(&proc_priv->dev->kobj, - &power_limit_attribute_group); return ret; } @@ -364,7 +360,10 @@ static int int3401_add(struct platform_device *pdev) platform_set_drvdata(pdev, proc_priv); proc_thermal_emum_mode = PROC_THERMAL_PLATFORM_DEV; - return 0; + dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PLATFORM_DEV\n"); + + return sysfs_create_group(&pdev->dev.kobj, + &power_limit_attribute_group); } static int int3401_remove(struct platform_device *pdev) @@ -423,7 +422,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, proc_priv->soc_dts = intel_soc_dts_iosf_init( INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0); - if (proc_priv->soc_dts && pdev->irq) { + if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) { ret = pci_enable_msi(pdev); if (!ret) { ret = request_threaded_irq(pdev->irq, NULL, @@ -441,7 +440,10 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, dev_err(&pdev->dev, "No auxiliary DTSs enabled\n"); } - return 0; + dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PCI\n"); + + return sysfs_create_group(&pdev->dev.kobj, + &power_limit_attribute_group); } static void proc_thermal_pci_remove(struct pci_dev *pdev) diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index 4bfdb4a1e47d..2df059cc07e2 100644 --- a/drivers/thermal/of-thermal.c +++ b/drivers/thermal/of-thermal.c @@ -867,14 +867,14 @@ __init *thermal_of_build_thermal_zone(struct device_node *np) ret = of_property_read_u32(np, "polling-delay-passive", &prop); if (ret < 0) { - pr_err("missing polling-delay-passive property\n"); + pr_err("%pOFn: missing polling-delay-passive property\n", np); goto free_tz; } tz->passive_delay = prop; ret = of_property_read_u32(np, "polling-delay", &prop); if (ret < 0) { - pr_err("missing polling-delay property\n"); + pr_err("%pOFn: missing polling-delay property\n", np); goto free_tz; } tz->polling_delay = prop; diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 4164414d4c64..8bdf42bc8fc8 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -597,6 +597,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, /* too large for caller's buffer */ ret = -EOVERFLOW; } else { + __set_current_state(TASK_RUNNING); if (copy_to_user(buf, rbuf->buf, rbuf->count)) ret = -EFAULT; else diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 189ab1212d9a..e441221e04b9 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1070,15 +1070,16 @@ int serial8250_register_8250_port(struct uart_8250_port *up) ret = 0; } - } - /* Initialise interrupt backoff work if required */ - if (up->overrun_backoff_time_ms > 0) { - uart->overrun_backoff_time_ms = up->overrun_backoff_time_ms; - INIT_DELAYED_WORK(&uart->overrun_backoff, - serial_8250_overrun_backoff_work); - } else { - uart->overrun_backoff_time_ms = 0; + /* Initialise interrupt backoff work if required */ + if (up->overrun_backoff_time_ms > 0) { + uart->overrun_backoff_time_ms = + up->overrun_backoff_time_ms; + INIT_DELAYED_WORK(&uart->overrun_backoff, + serial_8250_overrun_backoff_work); + } else { + uart->overrun_backoff_time_ms = 0; + } } mutex_unlock(&serial_mutex); diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c index e2c407656fa6..c1fdbc0b6840 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -357,6 +357,9 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p, if (dmacnt == 2) { data->dma = devm_kzalloc(&pdev->dev, sizeof(*data->dma), GFP_KERNEL); + if (!data->dma) + return -ENOMEM; + data->dma->fn = mtk8250_dma_filter; data->dma->rx_size = MTK_UART_RX_SIZE; data->dma->rxconf.src_maxburst = MTK_UART_RX_TRIGGER; diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index f80a300b5d68..48bd694a5fa1 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -3420,6 +3420,11 @@ static int serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board) { int num_iomem, num_port, first_port = -1, i; + int rc; + + rc = serial_pci_is_class_communication(dev); + if (rc) + return rc; /* * Should we try to make guesses for multiport serial devices later? @@ -3647,10 +3652,6 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) board = &pci_boards[ent->driver_data]; - rc = serial_pci_is_class_communication(dev); - if (rc) - return rc; - rc = serial_pci_is_blacklisted(dev); if (rc) return rc; diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 67b9bf3b500e..089a6f285d5e 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -85,6 +85,18 @@ config SERIAL_EARLYCON_ARM_SEMIHOST with "earlycon=smh" on the kernel command line. The console is enabled when early_param is processed. +config SERIAL_EARLYCON_RISCV_SBI + bool "Early console using RISC-V SBI" + depends on RISCV + select SERIAL_CORE + select SERIAL_CORE_CONSOLE + select SERIAL_EARLYCON + help + Support for early debug console using RISC-V SBI. This enables + the console before standard serial driver is probed. This is enabled + with "earlycon=sbi" on the kernel command line. The console is + enabled when early_param is processed. + config SERIAL_SB1250_DUART tristate "BCM1xxx on-chip DUART serial support" depends on SIBYTE_SB1xxx_SOC=y diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 8c303736b7e8..1511e8a9f856 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_SERIAL_CORE) += serial_core.o obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o obj-$(CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST) += earlycon-arm-semihost.o +obj-$(CONFIG_SERIAL_EARLYCON_RISCV_SBI) += earlycon-riscv-sbi.o # These Sparc drivers have to appear before others such as 8250 # which share ttySx minor node space. Otherwise console device diff --git a/drivers/tty/serial/earlycon-riscv-sbi.c b/drivers/tty/serial/earlycon-riscv-sbi.c new file mode 100644 index 000000000000..ce81523c3113 --- /dev/null +++ b/drivers/tty/serial/earlycon-riscv-sbi.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RISC-V SBI based earlycon + * + * Copyright (C) 2018 Anup Patel <anup@brainfault.org> + */ +#include <linux/kernel.h> +#include <linux/console.h> +#include <linux/init.h> +#include <linux/serial_core.h> +#include <asm/sbi.h> + +static void sbi_putc(struct uart_port *port, int c) +{ + sbi_console_putchar(c); +} + +static void sbi_console_write(struct console *con, + const char *s, unsigned n) +{ + struct earlycon_device *dev = con->data; + uart_console_write(&dev->port, s, n, sbi_putc); +} + +static int __init early_sbi_setup(struct earlycon_device *device, + const char *opt) +{ + device->con->write = sbi_console_write; + return 0; +} +EARLYCON_DECLARE(sbi, early_sbi_setup); diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 241a48e5052c..debdd1b9e01a 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1697,7 +1697,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, } /* ask the core to calculate the divisor */ - baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16); + baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 4); spin_lock_irqsave(&sport->port.lock, flags); diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index e052b69ceb98..9de9f0f239a1 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -114,9 +114,9 @@ struct ltq_uart_port { static inline void asc_update_bits(u32 clear, u32 set, void __iomem *reg) { - u32 tmp = readl(reg); + u32 tmp = __raw_readl(reg); - writel((tmp & ~clear) | set, reg); + __raw_writel((tmp & ~clear) | set, reg); } static inline struct @@ -144,7 +144,7 @@ lqasc_start_tx(struct uart_port *port) static void lqasc_stop_rx(struct uart_port *port) { - writel(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE); + __raw_writel(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE); } static int @@ -153,11 +153,12 @@ lqasc_rx_chars(struct uart_port *port) struct tty_port *tport = &port->state->port; unsigned int ch = 0, rsr = 0, fifocnt; - fifocnt = readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK; + fifocnt = __raw_readl(port->membase + LTQ_ASC_FSTAT) & + ASCFSTAT_RXFFLMASK; while (fifocnt--) { u8 flag = TTY_NORMAL; ch = readb(port->membase + LTQ_ASC_RBUF); - rsr = (readl(port->membase + LTQ_ASC_STATE) + rsr = (__raw_readl(port->membase + LTQ_ASC_STATE) & ASCSTATE_ANY) | UART_DUMMY_UER_RX; tty_flip_buffer_push(tport); port->icount.rx++; @@ -217,7 +218,7 @@ lqasc_tx_chars(struct uart_port *port) return; } - while (((readl(port->membase + LTQ_ASC_FSTAT) & + while (((__raw_readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) { if (port->x_char) { writeb(port->x_char, port->membase + LTQ_ASC_TBUF); @@ -245,7 +246,7 @@ lqasc_tx_int(int irq, void *_port) unsigned long flags; struct uart_port *port = (struct uart_port *)_port; spin_lock_irqsave(<q_asc_lock, flags); - writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR); + __raw_writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR); spin_unlock_irqrestore(<q_asc_lock, flags); lqasc_start_tx(port); return IRQ_HANDLED; @@ -270,7 +271,7 @@ lqasc_rx_int(int irq, void *_port) unsigned long flags; struct uart_port *port = (struct uart_port *)_port; spin_lock_irqsave(<q_asc_lock, flags); - writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR); + __raw_writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR); lqasc_rx_chars(port); spin_unlock_irqrestore(<q_asc_lock, flags); return IRQ_HANDLED; @@ -280,7 +281,8 @@ static unsigned int lqasc_tx_empty(struct uart_port *port) { int status; - status = readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK; + status = __raw_readl(port->membase + LTQ_ASC_FSTAT) & + ASCFSTAT_TXFFLMASK; return status ? 0 : TIOCSER_TEMT; } @@ -313,12 +315,12 @@ lqasc_startup(struct uart_port *port) asc_update_bits(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET), port->membase + LTQ_ASC_CLC); - writel(0, port->membase + LTQ_ASC_PISEL); - writel( + __raw_writel(0, port->membase + LTQ_ASC_PISEL); + __raw_writel( ((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) | ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU, port->membase + LTQ_ASC_TXFCON); - writel( + __raw_writel( ((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK) | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU, port->membase + LTQ_ASC_RXFCON); @@ -350,7 +352,7 @@ lqasc_startup(struct uart_port *port) goto err2; } - writel(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX, + __raw_writel(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX, port->membase + LTQ_ASC_IRNREN); return 0; @@ -369,7 +371,7 @@ lqasc_shutdown(struct uart_port *port) free_irq(ltq_port->rx_irq, port); free_irq(ltq_port->err_irq, port); - writel(0, port->membase + LTQ_ASC_CON); + __raw_writel(0, port->membase + LTQ_ASC_CON); asc_update_bits(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU, port->membase + LTQ_ASC_RXFCON); asc_update_bits(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU, @@ -461,13 +463,13 @@ lqasc_set_termios(struct uart_port *port, asc_update_bits(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON); /* now we can write the new baudrate into the register */ - writel(divisor, port->membase + LTQ_ASC_BG); + __raw_writel(divisor, port->membase + LTQ_ASC_BG); /* turn the baudrate generator back on */ asc_update_bits(0, ASCCON_R, port->membase + LTQ_ASC_CON); /* enable rx */ - writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE); + __raw_writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE); spin_unlock_irqrestore(<q_asc_lock, flags); @@ -578,7 +580,7 @@ lqasc_console_putchar(struct uart_port *port, int ch) return; do { - fifofree = (readl(port->membase + LTQ_ASC_FSTAT) + fifofree = (__raw_readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF; } while (fifofree == 0); writeb(ch, port->membase + LTQ_ASC_TBUF); diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index a72d6d9fb983..38016609c7fa 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -225,7 +225,7 @@ static unsigned int qcom_geni_serial_get_mctrl(struct uart_port *uport) unsigned int mctrl = TIOCM_DSR | TIOCM_CAR; u32 geni_ios; - if (uart_console(uport) || !uart_cts_enabled(uport)) { + if (uart_console(uport)) { mctrl |= TIOCM_CTS; } else { geni_ios = readl_relaxed(uport->membase + SE_GENI_IOS); @@ -241,7 +241,7 @@ static void qcom_geni_serial_set_mctrl(struct uart_port *uport, { u32 uart_manual_rfr = 0; - if (uart_console(uport) || !uart_cts_enabled(uport)) + if (uart_console(uport)) return; if (!(mctrl & TIOCM_RTS)) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index d4cca5bdaf1c..556f50aa1b58 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -130,6 +130,9 @@ static void uart_start(struct tty_struct *tty) struct uart_port *port; unsigned long flags; + if (!state) + return; + port = uart_port_lock(state, flags); __uart_start(tty); uart_port_unlock(port, flags); @@ -550,10 +553,12 @@ static int uart_put_char(struct tty_struct *tty, unsigned char c) int ret = 0; circ = &state->xmit; - if (!circ->buf) + port = uart_port_lock(state, flags); + if (!circ->buf) { + uart_port_unlock(port, flags); return 0; + } - port = uart_port_lock(state, flags); if (port && uart_circ_chars_free(circ) != 0) { circ->buf[circ->head] = c; circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1); @@ -586,11 +591,13 @@ static int uart_write(struct tty_struct *tty, return -EL3HLT; } + port = uart_port_lock(state, flags); circ = &state->xmit; - if (!circ->buf) + if (!circ->buf) { + uart_port_unlock(port, flags); return 0; + } - port = uart_port_lock(state, flags); while (port) { c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); if (count < c) @@ -723,6 +730,9 @@ static void uart_unthrottle(struct tty_struct *tty) upstat_t mask = UPSTAT_SYNC_FIFO; struct uart_port *port; + if (!state) + return; + port = uart_port_ref(state); if (!port) return; diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 8df0fd824520..64bbeb7d7e0c 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1921,7 +1921,7 @@ out_nomem: static void sci_free_irq(struct sci_port *port) { - int i; + int i, j; /* * Intentionally in reverse order so we iterate over the muxed @@ -1937,6 +1937,13 @@ static void sci_free_irq(struct sci_port *port) if (unlikely(irq < 0)) continue; + /* Check if already freed (irq was muxed) */ + for (j = 0; j < i; j++) + if (port->irqs[j] == irq) + j = i + 1; + if (j > i) + continue; + free_irq(port->irqs[i], port); kfree(port->irqstr[i]); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index bfe9ad85b362..21ffcce16927 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1256,7 +1256,8 @@ static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct * static int tty_reopen(struct tty_struct *tty) { struct tty_driver *driver = tty->driver; - int retval; + struct tty_ldisc *ld; + int retval = 0; if (driver->type == TTY_DRIVER_TYPE_PTY && driver->subtype == PTY_TYPE_MASTER) @@ -1268,13 +1269,18 @@ static int tty_reopen(struct tty_struct *tty) if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN)) return -EBUSY; - retval = tty_ldisc_lock(tty, 5 * HZ); - if (retval) - return retval; + ld = tty_ldisc_ref_wait(tty); + if (ld) { + tty_ldisc_deref(ld); + } else { + retval = tty_ldisc_lock(tty, 5 * HZ); + if (retval) + return retval; - if (!tty->ldisc) - retval = tty_ldisc_reinit(tty, tty->termios.c_line); - tty_ldisc_unlock(tty); + if (!tty->ldisc) + retval = tty_ldisc_reinit(tty, tty->termios.c_line); + tty_ldisc_unlock(tty); + } if (retval == 0) tty->count++; @@ -2183,7 +2189,8 @@ static int tiocsti(struct tty_struct *tty, char __user *p) ld = tty_ldisc_ref_wait(tty); if (!ld) return -EIO; - ld->ops->receive_buf(tty, &ch, &mbz, 1); + if (ld->ops->receive_buf) + ld->ops->receive_buf(tty, &ch, &mbz, 1); tty_ldisc_deref(ld); return 0; } diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 41ec8e5010f3..bba75560d11e 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1272,6 +1272,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, if (con_is_visible(vc)) update_screen(vc); vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num); + notify_update(vc); return err; } @@ -2764,8 +2765,8 @@ rescan_last_byte: con_flush(vc, draw_from, draw_to, &draw_x); vc_uniscr_debug_check(vc); console_conditional_schedule(); - console_unlock(); notify_update(vc); + console_unlock(); return n; } @@ -2884,8 +2885,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) unsigned char c; static DEFINE_SPINLOCK(printing_lock); const ushort *start; - ushort cnt = 0; - ushort myx; + ushort start_x, cnt; int kmsg_console; /* console busy or not yet initialized */ @@ -2898,10 +2898,6 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) if (kmsg_console && vc_cons_allocated(kmsg_console - 1)) vc = vc_cons[kmsg_console - 1].d; - /* read `x' only after setting currcons properly (otherwise - the `x' macro will read the x of the foreground console). */ - myx = vc->vc_x; - if (!vc_cons_allocated(fg_console)) { /* impossible */ /* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */ @@ -2916,53 +2912,41 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) hide_cursor(vc); start = (ushort *)vc->vc_pos; - - /* Contrived structure to try to emulate original need_wrap behaviour - * Problems caused when we have need_wrap set on '\n' character */ + start_x = vc->vc_x; + cnt = 0; while (count--) { c = *b++; if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) { - if (cnt > 0) { - if (con_is_visible(vc)) - vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x); - vc->vc_x += cnt; - if (vc->vc_need_wrap) - vc->vc_x--; - cnt = 0; - } + if (cnt && con_is_visible(vc)) + vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x); + cnt = 0; if (c == 8) { /* backspace */ bs(vc); start = (ushort *)vc->vc_pos; - myx = vc->vc_x; + start_x = vc->vc_x; continue; } if (c != 13) lf(vc); cr(vc); start = (ushort *)vc->vc_pos; - myx = vc->vc_x; + start_x = vc->vc_x; if (c == 10 || c == 13) continue; } + vc_uniscr_putc(vc, c); scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos); notify_write(vc, c); cnt++; - if (myx == vc->vc_cols - 1) { - vc->vc_need_wrap = 1; - continue; - } - vc->vc_pos += 2; - myx++; - } - if (cnt > 0) { - if (con_is_visible(vc)) - vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x); - vc->vc_x += cnt; - if (vc->vc_x == vc->vc_cols) { - vc->vc_x--; + if (vc->vc_x == vc->vc_cols - 1) { vc->vc_need_wrap = 1; + } else { + vc->vc_pos += 2; + vc->vc_x++; } } + if (cnt && con_is_visible(vc)) + vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x); set_cursor(vc); notify_update(vc); diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index e81de9ca8729..9b45aa422e69 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -316,7 +316,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) if (IS_ERR(data->usbmisc_data)) return PTR_ERR(data->usbmisc_data); - if (of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) { + if ((of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) + && data->usbmisc_data) { pdata.flags |= CI_HDRC_IMX_IS_HSIC; data->usbmisc_data->hsic = 1; data->pinctrl = devm_pinctrl_get(dev); diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index ed8c62b2d9d1..739f8960811a 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1865,6 +1865,13 @@ static const struct usb_device_id acm_ids[] = { .driver_info = IGNORE_DEVICE, }, + { USB_DEVICE(0x1bc7, 0x0021), /* Telit 3G ACM only composition */ + .driver_info = SEND_ZERO_PACKET, + }, + { USB_DEVICE(0x1bc7, 0x0023), /* Telit 3G ACM + ECM composition */ + .driver_info = SEND_ZERO_PACKET, + }, + /* control interfaces without any protocol set */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_PROTO_NONE) }, diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 356b05c82dbc..f713cecc1f41 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -143,9 +143,12 @@ int usb_choose_configuration(struct usb_device *udev) continue; } - if (i > 0 && desc && is_audio(desc) && is_uac3_config(desc)) { - best = c; - break; + if (i > 0 && desc && is_audio(desc)) { + if (is_uac3_config(desc)) { + best = c; + break; + } + continue; } /* From the remaining configs, choose the first one whose diff --git a/drivers/usb/core/ledtrig-usbport.c b/drivers/usb/core/ledtrig-usbport.c index dc7f7fd71684..c12ac56606c3 100644 --- a/drivers/usb/core/ledtrig-usbport.c +++ b/drivers/usb/core/ledtrig-usbport.c @@ -119,11 +119,6 @@ static const struct attribute_group ports_group = { .attrs = ports_attrs, }; -static const struct attribute_group *ports_groups[] = { - &ports_group, - NULL -}; - /*************************************** * Adding & removing ports ***************************************/ @@ -307,6 +302,7 @@ static int usbport_trig_notify(struct notifier_block *nb, unsigned long action, static int usbport_trig_activate(struct led_classdev *led_cdev) { struct usbport_trig_data *usbport_data; + int err; usbport_data = kzalloc(sizeof(*usbport_data), GFP_KERNEL); if (!usbport_data) @@ -315,6 +311,9 @@ static int usbport_trig_activate(struct led_classdev *led_cdev) /* List of ports */ INIT_LIST_HEAD(&usbport_data->ports); + err = sysfs_create_group(&led_cdev->dev->kobj, &ports_group); + if (err) + goto err_free; usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports); usbport_trig_update_count(usbport_data); @@ -322,8 +321,11 @@ static int usbport_trig_activate(struct led_classdev *led_cdev) usbport_data->nb.notifier_call = usbport_trig_notify; led_set_trigger_data(led_cdev, usbport_data); usb_register_notify(&usbport_data->nb); - return 0; + +err_free: + kfree(usbport_data); + return err; } static void usbport_trig_deactivate(struct led_classdev *led_cdev) @@ -335,6 +337,8 @@ static void usbport_trig_deactivate(struct led_classdev *led_cdev) usbport_trig_remove_port(usbport_data, port); } + sysfs_remove_group(&led_cdev->dev->kobj, &ports_group); + usb_unregister_notify(&usbport_data->nb); kfree(usbport_data); @@ -344,7 +348,6 @@ static struct led_trigger usbport_led_trigger = { .name = "usbport", .activate = usbport_trig_activate, .deactivate = usbport_trig_deactivate, - .groups = ports_groups, }; static int __init usbport_trig_init(void) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 514c5214ddb2..8bc35d53408b 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -394,7 +394,8 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x1a40, 0x0101), .driver_info = USB_QUIRK_HUB_SLOW_RESET }, /* Corsair K70 RGB */ - { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT }, + { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT | + USB_QUIRK_DELAY_CTRL_MSG }, /* Corsair Strafe */ { USB_DEVICE(0x1b1c, 0x1b15), .driver_info = USB_QUIRK_DELAY_INIT | diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 68ad75a7460d..55ef3cc2701b 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -261,7 +261,7 @@ static void dwc2_gadget_wkup_alert_handler(struct dwc2_hsotg *hsotg) if (gintsts2 & GINTSTS2_WKUP_ALERT_INT) { dev_dbg(hsotg->dev, "%s: Wkup_Alert_Int\n", __func__); - dwc2_clear_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT); + dwc2_set_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT); dwc2_set_bit(hsotg, DCTL, DCTL_RMTWKUPSIG); } } diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index cb7fcd7c0ad8..c1e9ea621f41 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -78,7 +78,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev) for (i = 0; i < exynos->num_clks; i++) { ret = clk_prepare_enable(exynos->clks[i]); if (ret) { - while (--i > 0) + while (i-- > 0) clk_disable_unprepare(exynos->clks[i]); return ret; } @@ -223,7 +223,7 @@ static int dwc3_exynos_resume(struct device *dev) for (i = 0; i < exynos->num_clks; i++) { ret = clk_prepare_enable(exynos->clks[i]); if (ret) { - while (--i > 0) + while (i-- > 0) clk_disable_unprepare(exynos->clks[i]); return ret; } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 07bd31bb2f8a..6c9b76bcc2e1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -177,6 +177,7 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep, req->started = false; list_del(&req->list); req->remaining = 0; + req->needs_extra_trb = false; if (req->request.status == -EINPROGRESS) req->request.status = status; @@ -1118,7 +1119,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); unsigned int rem = length % maxp; - if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) { + if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc)) { struct dwc3 *dwc = dep->dwc; struct dwc3_trb *trb; @@ -1984,6 +1985,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) /* begin to receive SETUP packets */ dwc->ep0state = EP0_SETUP_PHASE; + dwc->link_state = DWC3_LINK_STATE_SS_DIS; dwc3_ep0_out_start(dwc); dwc3_gadget_enable_irq(dwc); @@ -3379,6 +3381,8 @@ int dwc3_gadget_suspend(struct dwc3 *dwc) dwc3_disconnect_gadget(dwc); __dwc3_gadget_stop(dwc); + synchronize_irq(dwc->irq_gadget); + return 0; } diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c index 9cdef108fb1b..ed68a4860b7d 100644 --- a/drivers/usb/gadget/function/f_sourcesink.c +++ b/drivers/usb/gadget/function/f_sourcesink.c @@ -838,7 +838,7 @@ static struct usb_function *source_sink_alloc_func( ss = kzalloc(sizeof(*ss), GFP_KERNEL); if (!ss) - return NULL; + return ERR_PTR(-ENOMEM); ss_opts = container_of(fi, struct f_ss_opts, func_inst); diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c index 01b44e159623..ccbd1d34eb2a 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_core.c +++ b/drivers/usb/gadget/udc/bdc/bdc_core.c @@ -172,8 +172,9 @@ static int scratchpad_setup(struct bdc *bdc) /* Refer to BDC spec, Table 4 for description of SPB */ sp_buff_size = 1 << (sp_buff_size + 5); dev_dbg(bdc->dev, "Allocating %d bytes for scratchpad\n", sp_buff_size); - bdc->scratchpad.buff = dma_zalloc_coherent(bdc->dev, sp_buff_size, - &bdc->scratchpad.sp_dma, GFP_KERNEL); + bdc->scratchpad.buff = dma_alloc_coherent(bdc->dev, sp_buff_size, + &bdc->scratchpad.sp_dma, + GFP_KERNEL); if (!bdc->scratchpad.buff) goto fail; @@ -202,11 +203,9 @@ static int setup_srr(struct bdc *bdc, int interrupter) bdc_writel(bdc->regs, BDC_SRRINT(0), BDC_SRR_RWS | BDC_SRR_RST); bdc->srr.dqp_index = 0; /* allocate the status report descriptors */ - bdc->srr.sr_bds = dma_zalloc_coherent( - bdc->dev, - NUM_SR_ENTRIES * sizeof(struct bdc_bd), - &bdc->srr.dma_addr, - GFP_KERNEL); + bdc->srr.sr_bds = dma_alloc_coherent(bdc->dev, + NUM_SR_ENTRIES * sizeof(struct bdc_bd), + &bdc->srr.dma_addr, GFP_KERNEL); if (!bdc->srr.sr_bds) return -ENOMEM; diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index 660878a19505..b77f3126580e 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -2083,7 +2083,7 @@ static irqreturn_t net2272_irq(int irq, void *_dev) #if defined(PLX_PCI_RDK2) /* see if PCI int for us by checking irqstat */ intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT); - if (!intcsr & (1 << NET2272_PCI_IRQ)) { + if (!(intcsr & (1 << NET2272_PCI_IRQ))) { spin_unlock(&dev->lock); return IRQ_NONE; } diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index f26109eafdbf..66ec1fdf9fe7 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -302,3 +302,4 @@ MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>"); MODULE_AUTHOR("Neil Zhang <zhangwm@marvell.com>"); MODULE_ALIAS("mv-ehci"); MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(of, ehci_mv_dt_ids); diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 6218bfe54f52..98deb5f64268 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -596,9 +596,9 @@ static int uhci_start(struct usb_hcd *hcd) &uhci_debug_operations); #endif - uhci->frame = dma_zalloc_coherent(uhci_dev(uhci), - UHCI_NUMFRAMES * sizeof(*uhci->frame), - &uhci->frame_dma_handle, GFP_KERNEL); + uhci->frame = dma_alloc_coherent(uhci_dev(uhci), + UHCI_NUMFRAMES * sizeof(*uhci->frame), + &uhci->frame_dma_handle, GFP_KERNEL); if (!uhci->frame) { dev_err(uhci_dev(uhci), "unable to allocate consistent memory for frame list\n"); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 36a3eb8849f1..8067f178fa84 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1672,8 +1672,8 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma); for (i = 0; i < num_sp; i++) { dma_addr_t dma; - void *buf = dma_zalloc_coherent(dev, xhci->page_size, &dma, - flags); + void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma, + flags); if (!buf) goto fail_sp4; @@ -1799,8 +1799,8 @@ int xhci_alloc_erst(struct xhci_hcd *xhci, struct xhci_erst_entry *entry; size = sizeof(struct xhci_erst_entry) * evt_ring->num_segs; - erst->entries = dma_zalloc_coherent(xhci_to_hcd(xhci)->self.sysdev, - size, &erst->erst_dma_addr, flags); + erst->entries = dma_alloc_coherent(xhci_to_hcd(xhci)->self.sysdev, + size, &erst->erst_dma_addr, flags); if (!erst->entries) return -ENOMEM; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index eae8b1b1b45b..ffe462a657b1 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -452,13 +452,10 @@ void musb_g_tx(struct musb *musb, u8 epnum) } if (request) { - u8 is_dma = 0; - bool short_packet = false; trace_musb_req_tx(req); if (dma && (csr & MUSB_TXCSR_DMAENAB)) { - is_dma = 1; csr |= MUSB_TXCSR_P_WZC_BITS; csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET); @@ -476,16 +473,8 @@ void musb_g_tx(struct musb *musb, u8 epnum) */ if ((request->zero && request->length) && (request->length % musb_ep->packet_sz == 0) - && (request->actual == request->length)) - short_packet = true; + && (request->actual == request->length)) { - if ((musb_dma_inventra(musb) || musb_dma_ux500(musb)) && - (is_dma && (!dma->desired_mode || - (request->actual & - (musb_ep->packet_sz - 1))))) - short_packet = true; - - if (short_packet) { /* * On DMA completion, FIFO may not be * available yet... diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index a688f7f87829..5fc6825745f2 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -346,12 +346,10 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) channel->status = MUSB_DMA_STATUS_FREE; /* completed */ - if ((devctl & MUSB_DEVCTL_HM) - && (musb_channel->transmit) - && ((channel->desired_mode == 0) - || (channel->actual_len & - (musb_channel->max_packet_sz - 1))) - ) { + if (musb_channel->transmit && + (!channel->desired_mode || + (channel->actual_len % + musb_channel->max_packet_sz))) { u8 epnum = musb_channel->epnum; int offset = musb->io.ep_offset(epnum, MUSB_TXCSR); @@ -363,11 +361,14 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) */ musb_ep_select(mbase, epnum); txcsr = musb_readw(mbase, offset); - txcsr &= ~(MUSB_TXCSR_DMAENAB + if (channel->desired_mode == 1) { + txcsr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_AUTOSET); - musb_writew(mbase, offset, txcsr); - /* Send out the packet */ - txcsr &= ~MUSB_TXCSR_DMAMODE; + musb_writew(mbase, offset, txcsr); + /* Send out the packet */ + txcsr &= ~MUSB_TXCSR_DMAMODE; + txcsr |= MUSB_TXCSR_DMAENAB; + } txcsr |= MUSB_TXCSR_TXPKTRDY; musb_writew(mbase, offset, txcsr); } diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index d7312eed6088..91ea3083e7ad 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -21,7 +21,7 @@ config AB8500_USB config FSL_USB2_OTG bool "Freescale USB OTG Transceiver Driver" - depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM && PM + depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM=y && PM depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y' select USB_PHY help diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c index 27bdb7222527..f5f0568d8533 100644 --- a/drivers/usb/phy/phy-am335x.c +++ b/drivers/usb/phy/phy-am335x.c @@ -61,9 +61,6 @@ static int am335x_phy_probe(struct platform_device *pdev) if (ret) return ret; - ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy); - if (ret) - return ret; am_phy->usb_phy_gen.phy.init = am335x_init; am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown; @@ -82,7 +79,7 @@ static int am335x_phy_probe(struct platform_device *pdev) device_set_wakeup_enable(dev, false); phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, false); - return 0; + return usb_add_phy_dev(&am_phy->usb_phy_gen.phy); } static int am335x_phy_remove(struct platform_device *pdev) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1ab2a6191013..77ef4c481f3c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1783,6 +1783,10 @@ static int ftdi_set_bitmode(struct usb_serial_port *port, u8 mode) int result; u16 val; + result = usb_autopm_get_interface(serial->interface); + if (result) + return result; + val = (mode << 8) | (priv->gpio_output << 4) | priv->gpio_value; result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), @@ -1795,6 +1799,8 @@ static int ftdi_set_bitmode(struct usb_serial_port *port, u8 mode) val, result); } + usb_autopm_put_interface(serial->interface); + return result; } @@ -1846,9 +1852,15 @@ static int ftdi_read_cbus_pins(struct usb_serial_port *port) unsigned char *buf; int result; + result = usb_autopm_get_interface(serial->interface); + if (result) + return result; + buf = kmalloc(1, GFP_KERNEL); - if (!buf) + if (!buf) { + usb_autopm_put_interface(serial->interface); return -ENOMEM; + } result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -1863,6 +1875,7 @@ static int ftdi_read_cbus_pins(struct usb_serial_port *port) } kfree(buf); + usb_autopm_put_interface(serial->interface); return result; } diff --git a/drivers/usb/serial/keyspan_usa26msg.h b/drivers/usb/serial/keyspan_usa26msg.h index 09e21e84fc4e..a68f1fb25b8a 100644 --- a/drivers/usb/serial/keyspan_usa26msg.h +++ b/drivers/usb/serial/keyspan_usa26msg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ /* usa26msg.h diff --git a/drivers/usb/serial/keyspan_usa28msg.h b/drivers/usb/serial/keyspan_usa28msg.h index dee454c4609a..a19f3fe5d98d 100644 --- a/drivers/usb/serial/keyspan_usa28msg.h +++ b/drivers/usb/serial/keyspan_usa28msg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ /* usa28msg.h diff --git a/drivers/usb/serial/keyspan_usa49msg.h b/drivers/usb/serial/keyspan_usa49msg.h index 163b2dea2ec5..8c3970fdd868 100644 --- a/drivers/usb/serial/keyspan_usa49msg.h +++ b/drivers/usb/serial/keyspan_usa49msg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ /* usa49msg.h diff --git a/drivers/usb/serial/keyspan_usa67msg.h b/drivers/usb/serial/keyspan_usa67msg.h index 20fa3e2f7187..dcf502fdbb44 100644 --- a/drivers/usb/serial/keyspan_usa67msg.h +++ b/drivers/usb/serial/keyspan_usa67msg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ /* usa67msg.h diff --git a/drivers/usb/serial/keyspan_usa90msg.h b/drivers/usb/serial/keyspan_usa90msg.h index 86708ecd8735..c4ca0f631d20 100644 --- a/drivers/usb/serial/keyspan_usa90msg.h +++ b/drivers/usb/serial/keyspan_usa90msg.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ /* usa90msg.h diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 98e7a5df0f6d..bb3f9aa4a909 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -46,6 +46,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_TB) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID), diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 4e2554d55362..559941ca884d 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -8,6 +8,7 @@ #define PL2303_VENDOR_ID 0x067b #define PL2303_PRODUCT_ID 0x2303 +#define PL2303_PRODUCT_ID_TB 0x2304 #define PL2303_PRODUCT_ID_RSAQ2 0x04bb #define PL2303_PRODUCT_ID_DCU11 0x1234 #define PL2303_PRODUCT_ID_PHAROS 0xaaa0 @@ -20,6 +21,7 @@ #define PL2303_PRODUCT_ID_MOTOROLA 0x0307 #define PL2303_PRODUCT_ID_ZTEK 0xe1f1 + #define ATEN_VENDOR_ID 0x0557 #define ATEN_VENDOR_ID2 0x0547 #define ATEN_PRODUCT_ID 0x2008 diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c index 4d0273508043..edbbb13d6de6 100644 --- a/drivers/usb/serial/usb-serial-simple.c +++ b/drivers/usb/serial/usb-serial-simple.c @@ -85,7 +85,8 @@ DEVICE(moto_modem, MOTO_IDS); /* Motorola Tetra driver */ #define MOTOROLA_TETRA_IDS() \ { USB_DEVICE(0x0cad, 0x9011) }, /* Motorola Solutions TETRA PEI */ \ - { USB_DEVICE(0x0cad, 0x9012) } /* MTP6550 */ + { USB_DEVICE(0x0cad, 0x9012) }, /* MTP6550 */ \ + { USB_DEVICE(0x0cad, 0x9016) } /* TPG2200 */ DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS); /* Novatel Wireless GPS driver */ diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index fde2e71a6ade..a73ea495d5a7 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -235,8 +235,12 @@ static int slave_configure(struct scsi_device *sdev) if (!(us->fflags & US_FL_NEEDS_CAP16)) sdev->try_rc_10_first = 1; - /* assume SPC3 or latter devices support sense size > 18 */ - if (sdev->scsi_level > SCSI_SPC_2) + /* + * assume SPC3 or latter devices support sense size > 18 + * unless US_FL_BAD_SENSE quirk is specified. + */ + if (sdev->scsi_level > SCSI_SPC_2 && + !(us->fflags & US_FL_BAD_SENSE)) us->fflags |= US_FL_SANE_SENSE; /* diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index f7f83b21dc74..ea0d27a94afe 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1266,6 +1266,18 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, US_FL_FIX_CAPACITY ), /* + * Reported by Icenowy Zheng <icenowy@aosc.io> + * The SMI SM3350 USB-UFS bridge controller will enter a wrong state + * that do not process read/write command if a long sense is requested, + * so force to use 18-byte sense. + */ +UNUSUAL_DEV( 0x090c, 0x3350, 0x0000, 0xffff, + "SMI", + "SM3350 UFS-to-USB-Mass-Storage bridge", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_BAD_SENSE ), + +/* * Reported by Paul Hartman <paul.hartman+linux@gmail.com> * This card reader returns "Illegal Request, Logical Block Address * Out of Range" for the first READ(10) after a new card is inserted. diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 4bc29b586698..f1c39a3c7534 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -2297,7 +2297,8 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port) pdo_pps_apdo_max_voltage(snk)); port->pps_data.max_curr = min_pps_apdo_current(src, snk); port->pps_data.out_volt = min(port->pps_data.max_volt, - port->pps_data.out_volt); + max(port->pps_data.min_volt, + port->pps_data.out_volt)); port->pps_data.op_curr = min(port->pps_data.max_curr, port->pps_data.op_curr); } diff --git a/drivers/usb/usbip/README b/drivers/usb/usbip/README deleted file mode 100644 index 41a2cf2e77a6..000000000000 --- a/drivers/usb/usbip/README +++ /dev/null @@ -1,7 +0,0 @@ -TODO: - - more discussion about the protocol - - testing - - review of the userspace interface - - document the protocol - -Please send patches for this code to Greg Kroah-Hartman <greg@kroah.com> diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c index 0212f0ee8aea..b96fedc77ee5 100644 --- a/drivers/vfio/mdev/mdev_core.c +++ b/drivers/vfio/mdev/mdev_core.c @@ -60,9 +60,9 @@ struct mdev_device *mdev_from_dev(struct device *dev) } EXPORT_SYMBOL(mdev_from_dev); -uuid_le mdev_uuid(struct mdev_device *mdev) +const guid_t *mdev_uuid(struct mdev_device *mdev) { - return mdev->uuid; + return &mdev->uuid; } EXPORT_SYMBOL(mdev_uuid); @@ -88,8 +88,7 @@ static void mdev_release_parent(struct kref *kref) put_device(dev); } -static -inline struct mdev_parent *mdev_get_parent(struct mdev_parent *parent) +static inline struct mdev_parent *mdev_get_parent(struct mdev_parent *parent) { if (parent) kref_get(&parent->ref); @@ -276,7 +275,8 @@ static void mdev_device_release(struct device *dev) kfree(mdev); } -int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid) +int mdev_device_create(struct kobject *kobj, + struct device *dev, const guid_t *uuid) { int ret; struct mdev_device *mdev, *tmp; @@ -291,7 +291,7 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid) /* Check for duplicate */ list_for_each_entry(tmp, &mdev_list, next) { - if (!uuid_le_cmp(tmp->uuid, uuid)) { + if (guid_equal(&tmp->uuid, uuid)) { mutex_unlock(&mdev_list_lock); ret = -EEXIST; goto mdev_fail; @@ -305,7 +305,7 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid) goto mdev_fail; } - memcpy(&mdev->uuid, &uuid, sizeof(uuid_le)); + guid_copy(&mdev->uuid, uuid); list_add(&mdev->next, &mdev_list); mutex_unlock(&mdev_list_lock); @@ -315,7 +315,7 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid) mdev->dev.parent = dev; mdev->dev.bus = &mdev_bus_type; mdev->dev.release = mdev_device_release; - dev_set_name(&mdev->dev, "%pUl", uuid.b); + dev_set_name(&mdev->dev, "%pUl", uuid); ret = device_register(&mdev->dev); if (ret) { diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h index b5819b7d7ef7..379758c52b1b 100644 --- a/drivers/vfio/mdev/mdev_private.h +++ b/drivers/vfio/mdev/mdev_private.h @@ -28,7 +28,7 @@ struct mdev_parent { struct mdev_device { struct device dev; struct mdev_parent *parent; - uuid_le uuid; + guid_t uuid; void *driver_data; struct kref ref; struct list_head next; @@ -58,7 +58,8 @@ void parent_remove_sysfs_files(struct mdev_parent *parent); int mdev_create_sysfs_files(struct device *dev, struct mdev_type *type); void mdev_remove_sysfs_files(struct device *dev, struct mdev_type *type); -int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid); +int mdev_device_create(struct kobject *kobj, + struct device *dev, const guid_t *uuid); int mdev_device_remove(struct device *dev, bool force_remove); #endif /* MDEV_PRIVATE_H */ diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c index ce5dd219f2c8..5193a0e0ce5a 100644 --- a/drivers/vfio/mdev/mdev_sysfs.c +++ b/drivers/vfio/mdev/mdev_sysfs.c @@ -55,7 +55,7 @@ static ssize_t create_store(struct kobject *kobj, struct device *dev, const char *buf, size_t count) { char *str; - uuid_le uuid; + guid_t uuid; int ret; if ((count < UUID_STRING_LEN) || (count > UUID_STRING_LEN + 1)) @@ -65,12 +65,12 @@ static ssize_t create_store(struct kobject *kobj, struct device *dev, if (!str) return -ENOMEM; - ret = uuid_le_to_bin(str, &uuid); + ret = guid_parse(str, &uuid); kfree(str); if (ret) return ret; - ret = mdev_device_create(kobj, dev, uuid); + ret = mdev_device_create(kobj, dev, &uuid); if (ret) return ret; diff --git a/drivers/vfio/pci/trace.h b/drivers/vfio/pci/trace.h index 228ccdb8d1c8..b2aa986ab9ed 100644 --- a/drivers/vfio/pci/trace.h +++ b/drivers/vfio/pci/trace.h @@ -1,13 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * VFIO PCI mmap/mmap_fault tracepoints * * Copyright (C) 2018 IBM Corp. All rights reserved. * Author: Alexey Kardashevskiy <aik@ozlabs.ru> - * - * 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. */ #undef TRACE_SYSTEM @@ -94,7 +90,7 @@ TRACE_EVENT(vfio_pci_npu2_mmap, #endif /* _TRACE_VFIO_PCI_H */ #undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_PATH ../../drivers/vfio/pci #undef TRACE_INCLUDE_FILE #define TRACE_INCLUDE_FILE trace diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index ff60bd1ea587..a25659b5a5d1 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -209,6 +209,57 @@ static bool vfio_pci_nointx(struct pci_dev *pdev) return false; } +static void vfio_pci_probe_power_state(struct vfio_pci_device *vdev) +{ + struct pci_dev *pdev = vdev->pdev; + u16 pmcsr; + + if (!pdev->pm_cap) + return; + + pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmcsr); + + vdev->needs_pm_restore = !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET); +} + +/* + * pci_set_power_state() wrapper handling devices which perform a soft reset on + * D3->D0 transition. Save state prior to D0/1/2->D3, stash it on the vdev, + * restore when returned to D0. Saved separately from pci_saved_state for use + * by PM capability emulation and separately from pci_dev internal saved state + * to avoid it being overwritten and consumed around other resets. + */ +int vfio_pci_set_power_state(struct vfio_pci_device *vdev, pci_power_t state) +{ + struct pci_dev *pdev = vdev->pdev; + bool needs_restore = false, needs_save = false; + int ret; + + if (vdev->needs_pm_restore) { + if (pdev->current_state < PCI_D3hot && state >= PCI_D3hot) { + pci_save_state(pdev); + needs_save = true; + } + + if (pdev->current_state >= PCI_D3hot && state <= PCI_D0) + needs_restore = true; + } + + ret = pci_set_power_state(pdev, state); + + if (!ret) { + /* D3 might be unsupported via quirk, skip unless in D3 */ + if (needs_save && pdev->current_state >= PCI_D3hot) { + vdev->pm_save = pci_store_saved_state(pdev); + } else if (needs_restore) { + pci_load_and_free_saved_state(pdev, &vdev->pm_save); + pci_restore_state(pdev); + } + } + + return ret; +} + static int vfio_pci_enable(struct vfio_pci_device *vdev) { struct pci_dev *pdev = vdev->pdev; @@ -216,7 +267,7 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) u16 cmd; u8 msix_pos; - pci_set_power_state(pdev, PCI_D0); + vfio_pci_set_power_state(vdev, PCI_D0); /* Don't allow our initial saved state to include busmaster */ pci_clear_master(pdev); @@ -407,7 +458,7 @@ out: vfio_pci_try_bus_reset(vdev); if (!disable_idle_d3) - pci_set_power_state(pdev, PCI_D3hot); + vfio_pci_set_power_state(vdev, PCI_D3hot); } static void vfio_pci_release(void *device_data) @@ -708,6 +759,7 @@ static long vfio_pci_ioctl(void *device_data, { void __iomem *io; size_t size; + u16 orig_cmd; info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); info.flags = 0; @@ -723,15 +775,23 @@ static long vfio_pci_ioctl(void *device_data, break; } - /* Is it really there? */ + /* + * Is it really there? Enable memory decode for + * implicit access in pci_map_rom(). + */ + pci_read_config_word(pdev, PCI_COMMAND, &orig_cmd); + pci_write_config_word(pdev, PCI_COMMAND, + orig_cmd | PCI_COMMAND_MEMORY); + io = pci_map_rom(pdev, &size); - if (!io || !size) { + if (io) { + info.flags = VFIO_REGION_INFO_FLAG_READ; + pci_unmap_rom(pdev, io); + } else { info.size = 0; - break; } - pci_unmap_rom(pdev, io); - info.flags = VFIO_REGION_INFO_FLAG_READ; + pci_write_config_word(pdev, PCI_COMMAND, orig_cmd); break; } case VFIO_PCI_VGA_REGION_INDEX: @@ -1286,6 +1346,8 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) vfio_pci_set_vga_decode(vdev, false)); } + vfio_pci_probe_power_state(vdev); + if (!disable_idle_d3) { /* * pci-core sets the device power state to an unknown value at @@ -1296,8 +1358,8 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) * be able to get to D3. Therefore first do a D0 transition * before going to D3. */ - pci_set_power_state(pdev, PCI_D0); - pci_set_power_state(pdev, PCI_D3hot); + vfio_pci_set_power_state(vdev, PCI_D0); + vfio_pci_set_power_state(vdev, PCI_D3hot); } return ret; @@ -1316,6 +1378,11 @@ static void vfio_pci_remove(struct pci_dev *pdev) vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev); kfree(vdev->region); mutex_destroy(&vdev->ioeventfds_lock); + + if (!disable_idle_d3) + vfio_pci_set_power_state(vdev, PCI_D0); + + kfree(vdev->pm_save); kfree(vdev); if (vfio_pci_is_vga(pdev)) { @@ -1324,9 +1391,6 @@ static void vfio_pci_remove(struct pci_dev *pdev) VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM | VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM); } - - if (!disable_idle_d3) - pci_set_power_state(pdev, PCI_D0); } static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev, @@ -1551,7 +1615,7 @@ put_devs: tmp->needs_reset = false; if (tmp != vdev && !disable_idle_d3) - pci_set_power_state(tmp->pdev, PCI_D3hot); + vfio_pci_set_power_state(tmp, PCI_D3hot); } vfio_device_put(devs.devices[i]); diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index 423ea1f98441..e82b51114687 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c @@ -691,7 +691,7 @@ static int vfio_pm_config_write(struct vfio_pci_device *vdev, int pos, break; } - pci_set_power_state(vdev->pdev, state); + vfio_pci_set_power_state(vdev, state); } return count; diff --git a/drivers/vfio/pci/vfio_pci_nvlink2.c b/drivers/vfio/pci/vfio_pci_nvlink2.c index 054a2cf9dd8e..32f695ffe128 100644 --- a/drivers/vfio/pci/vfio_pci_nvlink2.c +++ b/drivers/vfio/pci/vfio_pci_nvlink2.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0-only /* * VFIO PCI NVIDIA Whitherspoon GPU support a.k.a. NVLink2. * * Copyright (C) 2018 IBM Corp. All rights reserved. * Author: Alexey Kardashevskiy <aik@ozlabs.ru> * - * 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. - * * Register an on-GPU RAM region for cacheable access. * * Derived from original vfio_pci_igd.c: @@ -178,11 +174,11 @@ static int vfio_pci_nvgpu_add_capability(struct vfio_pci_device *vdev, struct vfio_pci_region *region, struct vfio_info_cap *caps) { struct vfio_pci_nvgpu_data *data = region->data; - struct vfio_region_info_cap_nvlink2_ssatgt cap = { 0 }; - - cap.header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT; - cap.header.version = 1; - cap.tgt = data->gpu_tgt; + struct vfio_region_info_cap_nvlink2_ssatgt cap = { + .header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT, + .header.version = 1, + .tgt = data->gpu_tgt + }; return vfio_info_add_capability(caps, &cap.header, sizeof(cap)); } @@ -365,18 +361,18 @@ static int vfio_pci_npu2_add_capability(struct vfio_pci_device *vdev, struct vfio_pci_region *region, struct vfio_info_cap *caps) { struct vfio_pci_npu2_data *data = region->data; - struct vfio_region_info_cap_nvlink2_ssatgt captgt = { 0 }; - struct vfio_region_info_cap_nvlink2_lnkspd capspd = { 0 }; + struct vfio_region_info_cap_nvlink2_ssatgt captgt = { + .header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT, + .header.version = 1, + .tgt = data->gpu_tgt + }; + struct vfio_region_info_cap_nvlink2_lnkspd capspd = { + .header.id = VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD, + .header.version = 1, + .link_speed = data->link_speed + }; int ret; - captgt.header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT; - captgt.header.version = 1; - captgt.tgt = data->gpu_tgt; - - capspd.header.id = VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD; - capspd.header.version = 1; - capspd.link_speed = data->link_speed; - ret = vfio_info_add_capability(caps, &captgt.header, sizeof(captgt)); if (ret) return ret; diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h index 8c0009f00818..1812cf22fc4f 100644 --- a/drivers/vfio/pci/vfio_pci_private.h +++ b/drivers/vfio/pci/vfio_pci_private.h @@ -114,7 +114,9 @@ struct vfio_pci_device { bool has_vga; bool needs_reset; bool nointx; + bool needs_pm_restore; struct pci_saved_state *pci_saved_state; + struct pci_saved_state *pm_save; struct vfio_pci_reflck *reflck; int refcnt; int ioeventfds_nr; @@ -161,6 +163,10 @@ extern int vfio_pci_register_dev_region(struct vfio_pci_device *vdev, unsigned int type, unsigned int subtype, const struct vfio_pci_regops *ops, size_t size, u32 flags, void *data); + +extern int vfio_pci_set_power_state(struct vfio_pci_device *vdev, + pci_power_t state); + #ifdef CONFIG_VFIO_PCI_IGD extern int vfio_pci_igd_init(struct vfio_pci_device *vdev); #else diff --git a/drivers/vfio/platform/reset/Makefile b/drivers/vfio/platform/reset/Makefile index 57abd4f0ac5b..7294c5ea122e 100644 --- a/drivers/vfio/platform/reset/Makefile +++ b/drivers/vfio/platform/reset/Makefile @@ -2,8 +2,6 @@ vfio-platform-calxedaxgmac-y := vfio_platform_calxedaxgmac.o vfio-platform-amdxgbe-y := vfio_platform_amdxgbe.o -ccflags-y += -Idrivers/vfio/platform - obj-$(CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET) += vfio-platform-calxedaxgmac.o obj-$(CONFIG_VFIO_PLATFORM_AMDXGBE_RESET) += vfio-platform-amdxgbe.o obj-$(CONFIG_VFIO_PLATFORM_BCMFLEXRM_RESET) += vfio_platform_bcmflexrm.o diff --git a/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c b/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c index bcd419cfd79c..3ddb2704221d 100644 --- a/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c +++ b/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c @@ -25,7 +25,7 @@ #include <uapi/linux/mdio.h> #include <linux/delay.h> -#include "vfio_platform_private.h" +#include "../vfio_platform_private.h" #define DMA_MR 0x3000 #define MAC_VR 0x0110 diff --git a/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c b/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c index d45c3be71198..16165a62b86d 100644 --- a/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c +++ b/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c @@ -23,7 +23,7 @@ #include <linux/kernel.h> #include <linux/module.h> -#include "vfio_platform_private.h" +#include "../vfio_platform_private.h" /* FlexRM configuration */ #define RING_REGS_SIZE 0x10000 diff --git a/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c b/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c index 49e5df6e8f29..e0356de5df54 100644 --- a/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c +++ b/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c @@ -24,7 +24,7 @@ #include <linux/init.h> #include <linux/io.h> -#include "vfio_platform_private.h" +#include "../vfio_platform_private.h" #define DRIVER_VERSION "0.1" #define DRIVER_AUTHOR "Eric Auger <eric.auger@linaro.org>" diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 64833879f75d..a3030cdf3c18 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -2219,12 +2219,12 @@ static int __init vfio_init(void) vfio.class->devnode = vfio_devnode; - ret = alloc_chrdev_region(&vfio.group_devt, 0, MINORMASK, "vfio"); + ret = alloc_chrdev_region(&vfio.group_devt, 0, MINORMASK + 1, "vfio"); if (ret) goto err_alloc_chrdev; cdev_init(&vfio.group_cdev, &vfio_group_fops); - ret = cdev_add(&vfio.group_cdev, vfio.group_devt, MINORMASK); + ret = cdev_add(&vfio.group_cdev, vfio.group_devt, MINORMASK + 1); if (ret) goto err_cdev_add; @@ -2236,7 +2236,7 @@ static int __init vfio_init(void) return 0; err_cdev_add: - unregister_chrdev_region(vfio.group_devt, MINORMASK); + unregister_chrdev_region(vfio.group_devt, MINORMASK + 1); err_alloc_chrdev: class_destroy(vfio.class); vfio.class = NULL; @@ -2254,7 +2254,7 @@ static void __exit vfio_cleanup(void) #endif idr_destroy(&vfio.group_idr); cdev_del(&vfio.group_cdev); - unregister_chrdev_region(vfio.group_devt, MINORMASK); + unregister_chrdev_region(vfio.group_devt, MINORMASK + 1); class_destroy(vfio.class); vfio.class = NULL; misc_deregister(&vfio_dev); diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c index c424913324e3..8dbb270998f4 100644 --- a/drivers/vfio/vfio_iommu_spapr_tce.c +++ b/drivers/vfio/vfio_iommu_spapr_tce.c @@ -1235,7 +1235,8 @@ static void tce_iommu_release_ownership_ddw(struct tce_container *container, } for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) - table_group->ops->unset_window(table_group, i); + if (container->tables[i]) + table_group->ops->unset_window(table_group, i); table_group->ops->release_ownership(table_group); } diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 7651cfb14836..73652e21efec 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -878,7 +878,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu, return -EINVAL; if (!unmap->size || unmap->size & mask) return -EINVAL; - if (unmap->iova + unmap->size < unmap->iova || + if (unmap->iova + unmap->size - 1 < unmap->iova || unmap->size > SIZE_MAX) return -EINVAL; diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 36f3d0f49e60..df51a35cf537 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -1236,7 +1236,8 @@ static void handle_rx(struct vhost_net *net) if (nvq->done_idx > VHOST_NET_BATCH) vhost_net_signal_used(nvq); if (unlikely(vq_log)) - vhost_log_write(vq, vq_log, log, vhost_len); + vhost_log_write(vq, vq_log, log, vhost_len, + vq->iov, in); total_len += vhost_len; if (unlikely(vhost_exceeds_weight(++recv_pkts, total_len))) { vhost_poll_queue(&vq->poll); @@ -1336,7 +1337,8 @@ static int vhost_net_open(struct inode *inode, struct file *f) n->vqs[i].rx_ring = NULL; vhost_net_buf_init(&n->vqs[i].rxq); } - vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX); + vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX, + UIO_MAXIOV + VHOST_NET_BATCH); vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev); vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev); diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 8e10ab436d1f..23593cb23dd0 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1127,16 +1127,18 @@ vhost_scsi_send_tmf_reject(struct vhost_scsi *vs, struct vhost_virtqueue *vq, struct vhost_scsi_ctx *vc) { - struct virtio_scsi_ctrl_tmf_resp __user *resp; struct virtio_scsi_ctrl_tmf_resp rsp; + struct iov_iter iov_iter; int ret; pr_debug("%s\n", __func__); memset(&rsp, 0, sizeof(rsp)); rsp.response = VIRTIO_SCSI_S_FUNCTION_REJECTED; - resp = vq->iov[vc->out].iov_base; - ret = __copy_to_user(resp, &rsp, sizeof(rsp)); - if (!ret) + + iov_iter_init(&iov_iter, READ, &vq->iov[vc->out], vc->in, sizeof(rsp)); + + ret = copy_to_iter(&rsp, sizeof(rsp), &iov_iter); + if (likely(ret == sizeof(rsp))) vhost_add_used_and_signal(&vs->dev, vq, vc->head, 0); else pr_err("Faulted on virtio_scsi_ctrl_tmf_resp\n"); @@ -1147,16 +1149,18 @@ vhost_scsi_send_an_resp(struct vhost_scsi *vs, struct vhost_virtqueue *vq, struct vhost_scsi_ctx *vc) { - struct virtio_scsi_ctrl_an_resp __user *resp; struct virtio_scsi_ctrl_an_resp rsp; + struct iov_iter iov_iter; int ret; pr_debug("%s\n", __func__); memset(&rsp, 0, sizeof(rsp)); /* event_actual = 0 */ rsp.response = VIRTIO_SCSI_S_OK; - resp = vq->iov[vc->out].iov_base; - ret = __copy_to_user(resp, &rsp, sizeof(rsp)); - if (!ret) + + iov_iter_init(&iov_iter, READ, &vq->iov[vc->out], vc->in, sizeof(rsp)); + + ret = copy_to_iter(&rsp, sizeof(rsp), &iov_iter); + if (likely(ret == sizeof(rsp))) vhost_add_used_and_signal(&vs->dev, vq, vc->head, 0); else pr_err("Faulted on virtio_scsi_ctrl_an_resp\n"); @@ -1623,7 +1627,7 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) vqs[i] = &vs->vqs[i].vq; vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick; } - vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ); + vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV); vhost_scsi_init_inflight(vs, NULL); diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 9f7942cbcbb2..a2e5dc7716e2 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -390,9 +390,9 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev) vq->indirect = kmalloc_array(UIO_MAXIOV, sizeof(*vq->indirect), GFP_KERNEL); - vq->log = kmalloc_array(UIO_MAXIOV, sizeof(*vq->log), + vq->log = kmalloc_array(dev->iov_limit, sizeof(*vq->log), GFP_KERNEL); - vq->heads = kmalloc_array(UIO_MAXIOV, sizeof(*vq->heads), + vq->heads = kmalloc_array(dev->iov_limit, sizeof(*vq->heads), GFP_KERNEL); if (!vq->indirect || !vq->log || !vq->heads) goto err_nomem; @@ -414,7 +414,7 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev) } void vhost_dev_init(struct vhost_dev *dev, - struct vhost_virtqueue **vqs, int nvqs) + struct vhost_virtqueue **vqs, int nvqs, int iov_limit) { struct vhost_virtqueue *vq; int i; @@ -427,6 +427,7 @@ void vhost_dev_init(struct vhost_dev *dev, dev->iotlb = NULL; dev->mm = NULL; dev->worker = NULL; + dev->iov_limit = iov_limit; init_llist_head(&dev->work_list); init_waitqueue_head(&dev->wait); INIT_LIST_HEAD(&dev->read_list); @@ -1034,8 +1035,10 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev, int type, ret; ret = copy_from_iter(&type, sizeof(type), from); - if (ret != sizeof(type)) + if (ret != sizeof(type)) { + ret = -EINVAL; goto done; + } switch (type) { case VHOST_IOTLB_MSG: @@ -1054,8 +1057,10 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev, iov_iter_advance(from, offset); ret = copy_from_iter(&msg, sizeof(msg), from); - if (ret != sizeof(msg)) + if (ret != sizeof(msg)) { + ret = -EINVAL; goto done; + } if (vhost_process_iotlb_msg(dev, &msg)) { ret = -EFAULT; goto done; @@ -1733,13 +1738,87 @@ static int log_write(void __user *log_base, return r; } +static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len) +{ + struct vhost_umem *umem = vq->umem; + struct vhost_umem_node *u; + u64 start, end, l, min; + int r; + bool hit = false; + + while (len) { + min = len; + /* More than one GPAs can be mapped into a single HVA. So + * iterate all possible umems here to be safe. + */ + list_for_each_entry(u, &umem->umem_list, link) { + if (u->userspace_addr > hva - 1 + len || + u->userspace_addr - 1 + u->size < hva) + continue; + start = max(u->userspace_addr, hva); + end = min(u->userspace_addr - 1 + u->size, + hva - 1 + len); + l = end - start + 1; + r = log_write(vq->log_base, + u->start + start - u->userspace_addr, + l); + if (r < 0) + return r; + hit = true; + min = min(l, min); + } + + if (!hit) + return -EFAULT; + + len -= min; + hva += min; + } + + return 0; +} + +static int log_used(struct vhost_virtqueue *vq, u64 used_offset, u64 len) +{ + struct iovec iov[64]; + int i, ret; + + if (!vq->iotlb) + return log_write(vq->log_base, vq->log_addr + used_offset, len); + + ret = translate_desc(vq, (uintptr_t)vq->used + used_offset, + len, iov, 64, VHOST_ACCESS_WO); + if (ret < 0) + return ret; + + for (i = 0; i < ret; i++) { + ret = log_write_hva(vq, (uintptr_t)iov[i].iov_base, + iov[i].iov_len); + if (ret) + return ret; + } + + return 0; +} + int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, - unsigned int log_num, u64 len) + unsigned int log_num, u64 len, struct iovec *iov, int count) { int i, r; /* Make sure data written is seen before log. */ smp_wmb(); + + if (vq->iotlb) { + for (i = 0; i < count; i++) { + r = log_write_hva(vq, (uintptr_t)iov[i].iov_base, + iov[i].iov_len); + if (r < 0) + return r; + } + return 0; + } + for (i = 0; i < log_num; ++i) { u64 l = min(log[i].len, len); r = log_write(vq->log_base, log[i].addr, l); @@ -1769,9 +1848,8 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq) smp_wmb(); /* Log used flag write. */ used = &vq->used->flags; - log_write(vq->log_base, vq->log_addr + - (used - (void __user *)vq->used), - sizeof vq->used->flags); + log_used(vq, (used - (void __user *)vq->used), + sizeof vq->used->flags); if (vq->log_ctx) eventfd_signal(vq->log_ctx, 1); } @@ -1789,9 +1867,8 @@ static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event) smp_wmb(); /* Log avail event write */ used = vhost_avail_event(vq); - log_write(vq->log_base, vq->log_addr + - (used - (void __user *)vq->used), - sizeof *vhost_avail_event(vq)); + log_used(vq, (used - (void __user *)vq->used), + sizeof *vhost_avail_event(vq)); if (vq->log_ctx) eventfd_signal(vq->log_ctx, 1); } @@ -2191,10 +2268,8 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq, /* Make sure data is seen before log. */ smp_wmb(); /* Log used ring entry write. */ - log_write(vq->log_base, - vq->log_addr + - ((void __user *)used - (void __user *)vq->used), - count * sizeof *used); + log_used(vq, ((void __user *)used - (void __user *)vq->used), + count * sizeof *used); } old = vq->last_used_idx; new = (vq->last_used_idx += count); @@ -2236,9 +2311,8 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads, /* Make sure used idx is seen before log. */ smp_wmb(); /* Log used index update. */ - log_write(vq->log_base, - vq->log_addr + offsetof(struct vring_used, idx), - sizeof vq->used->idx); + log_used(vq, offsetof(struct vring_used, idx), + sizeof vq->used->idx); if (vq->log_ctx) eventfd_signal(vq->log_ctx, 1); } diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 466ef7542291..9490e7ddb340 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -170,9 +170,11 @@ struct vhost_dev { struct list_head read_list; struct list_head pending_list; wait_queue_head_t wait; + int iov_limit; }; -void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs); +void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, + int nvqs, int iov_limit); long vhost_dev_set_owner(struct vhost_dev *dev); bool vhost_dev_has_owner(struct vhost_dev *dev); long vhost_dev_check_owner(struct vhost_dev *); @@ -205,7 +207,8 @@ bool vhost_vq_avail_empty(struct vhost_dev *, struct vhost_virtqueue *); bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *); int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, - unsigned int log_num, u64 len); + unsigned int log_num, u64 len, + struct iovec *iov, int count); int vq_iotlb_prefetch(struct vhost_virtqueue *vq); struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type); diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index bc42d38ae031..bb5fc0e9fbc2 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -531,7 +531,7 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file) vsock->vqs[VSOCK_VQ_TX].handle_kick = vhost_vsock_handle_tx_kick; vsock->vqs[VSOCK_VQ_RX].handle_kick = vhost_vsock_handle_rx_kick; - vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs)); + vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs), UIO_MAXIOV); file->private_data = vsock; spin_lock_init(&vsock->send_pkt_list_lock); @@ -642,7 +642,7 @@ static int vhost_vsock_set_cid(struct vhost_vsock *vsock, u64 guest_cid) hash_del_rcu(&vsock->hash); vsock->guest_cid = guest_cid; - hash_add_rcu(vhost_vsock_hash, &vsock->hash, guest_cid); + hash_add_rcu(vhost_vsock_hash, &vsock->hash, vsock->guest_cid); mutex_unlock(&vhost_vsock_mutex); return 0; diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index 6d8dc2c77520..51e0c4be08df 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c @@ -174,7 +174,7 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev, return -ENODEV; } for_each_child_of_node(nproot, np) { - if (!of_node_cmp(np->name, name)) { + if (of_node_name_eq(np, name)) { of_property_read_u32(np, "marvell,88pm860x-iset", &iset); data->iset = PM8606_WLED_CURRENT(iset); diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index f9ef0673a083..feb90764a811 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -30,6 +30,7 @@ struct pwm_bl_data { struct device *dev; unsigned int lth_brightness; unsigned int *levels; + bool enabled; struct regulator *power_supply; struct gpio_desc *enable_gpio; unsigned int scale; @@ -50,7 +51,7 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb) int err; pwm_get_state(pb->pwm, &state); - if (state.enabled) + if (pb->enabled) return; err = regulator_enable(pb->power_supply); @@ -65,6 +66,8 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb) if (pb->enable_gpio) gpiod_set_value_cansleep(pb->enable_gpio, 1); + + pb->enabled = true; } static void pwm_backlight_power_off(struct pwm_bl_data *pb) @@ -72,7 +75,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb) struct pwm_state state; pwm_get_state(pb->pwm, &state); - if (!state.enabled) + if (!pb->enabled) return; if (pb->enable_gpio) @@ -86,6 +89,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb) pwm_apply_state(pb->pwm, &state); regulator_disable(pb->power_supply); + pb->enabled = false; } static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness) @@ -269,6 +273,16 @@ static int pwm_backlight_parse_dt(struct device *dev, memset(data, 0, sizeof(*data)); /* + * These values are optional and set as 0 by default, the out values + * are modified only if a valid u32 value can be decoded. + */ + of_property_read_u32(node, "post-pwm-on-delay-ms", + &data->post_pwm_on_delay); + of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay); + + data->enable_gpio = -EINVAL; + + /* * Determine the number of brightness levels, if this property is not * set a default table of brightness levels will be used. */ @@ -380,15 +394,6 @@ static int pwm_backlight_parse_dt(struct device *dev, data->max_brightness--; } - /* - * These values are optional and set as 0 by default, the out values - * are modified only if a valid u32 value can be decoded. - */ - of_property_read_u32(node, "post-pwm-on-delay-ms", - &data->post_pwm_on_delay); - of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay); - - data->enable_gpio = -EINVAL; return 0; } @@ -483,6 +488,7 @@ static int pwm_backlight_probe(struct platform_device *pdev) pb->check_fb = data->check_fb; pb->exit = data->exit; pb->dev = &pdev->dev; + pb->enabled = false; pb->post_pwm_on_delay = data->post_pwm_on_delay; pb->pwm_off_delay = data->pwm_off_delay; diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 09731b2f6815..c6b3bdbbdbc9 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -271,6 +271,7 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count) static void vgacon_restore_screen(struct vc_data *c) { + c->vc_origin = c->vc_visible_origin; vgacon_scrollback_cur->save = 0; if (!vga_is_gfx && !vgacon_scrollback_cur->restore) { @@ -287,8 +288,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines) int start, end, count, soff; if (!lines) { - c->vc_visible_origin = c->vc_origin; - vga_set_mem_top(c); + vgacon_restore_screen(c); return; } @@ -298,6 +298,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines) if (!vgacon_scrollback_cur->save) { vgacon_cursor(c, CM_ERASE); vgacon_save_screen(c); + c->vc_origin = (unsigned long)c->vc_screenbuf; vgacon_scrollback_cur->save = 1; } @@ -335,7 +336,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines) int copysize; int diff = c->vc_rows - count; - void *d = (void *) c->vc_origin; + void *d = (void *) c->vc_visible_origin; void *s = (void *) c->vc_screenbuf; count *= c->vc_size_row; diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 8976190b6c1f..bfa1360ec750 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -510,6 +510,13 @@ static int __init fb_console_setup(char *this_opt) continue; } #endif + + if (!strncmp(options, "logo-pos:", 9)) { + options += 9; + if (!strcmp(options, "center")) + fb_center_logo = true; + continue; + } } return 1; } diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 558ed2ed3124..cb43a2258c51 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -53,6 +53,9 @@ EXPORT_SYMBOL(registered_fb); int num_registered_fb __read_mostly; EXPORT_SYMBOL(num_registered_fb); +bool fb_center_logo __read_mostly; +EXPORT_SYMBOL(fb_center_logo); + static struct fb_info *get_fb_info(unsigned int idx) { struct fb_info *fb_info; @@ -506,8 +509,7 @@ static int fb_show_logo_line(struct fb_info *info, int rotate, fb_set_logo(info, logo, logo_new, fb_logo.depth); } -#ifdef CONFIG_FB_LOGO_CENTER - { + if (fb_center_logo) { int xres = info->var.xres; int yres = info->var.yres; @@ -520,11 +522,11 @@ static int fb_show_logo_line(struct fb_info *info, int rotate, --n; image.dx = (xres - n * (logo->width + 8) - 8) / 2; image.dy = y ?: (yres - logo->height) / 2; + } else { + image.dx = 0; + image.dy = y; } -#else - image.dx = 0; - image.dy = y; -#endif + image.width = logo->width; image.height = logo->height; @@ -684,9 +686,8 @@ int fb_prepare_logo(struct fb_info *info, int rotate) } height = fb_logo.logo->height; -#ifdef CONFIG_FB_LOGO_CENTER - height += (yres - fb_logo.logo->height) / 2; -#endif + if (fb_center_logo) + height += (yres - fb_logo.logo->height) / 2; return fb_prepare_extra_logos(info, height, yres); } diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c index a74096c53cb5..43f2a4816860 100644 --- a/drivers/video/fbdev/da8xx-fb.c +++ b/drivers/video/fbdev/da8xx-fb.c @@ -1446,9 +1446,9 @@ static int fb_probe(struct platform_device *device) da8xx_fb_fix.line_length - 1; /* allocate palette buffer */ - par->v_palette_base = dma_zalloc_coherent(NULL, PALETTE_SIZE, - &par->p_palette_base, - GFP_KERNEL | GFP_DMA); + par->v_palette_base = dma_alloc_coherent(NULL, PALETTE_SIZE, + &par->p_palette_base, + GFP_KERNEL | GFP_DMA); if (!par->v_palette_base) { dev_err(&device->dev, "GLCD: kmalloc for palette buffer failed\n"); diff --git a/drivers/video/fbdev/offb.c b/drivers/video/fbdev/offb.c index 31f769d67195..057d3cdef92e 100644 --- a/drivers/video/fbdev/offb.c +++ b/drivers/video/fbdev/offb.c @@ -318,28 +318,28 @@ static void __iomem *offb_map_reg(struct device_node *np, int index, } static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp, - const char *name, unsigned long address) + unsigned long address) { struct offb_par *par = (struct offb_par *) info->par; - if (dp && !strncmp(name, "ATY,Rage128", 11)) { + if (of_node_name_prefix(dp, "ATY,Rage128")) { par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); if (par->cmap_adr) par->cmap_type = cmap_r128; - } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12) - || !strncmp(name, "ATY,RageM3p12A", 14))) { + } else if (of_node_name_prefix(dp, "ATY,RageM3pA") || + of_node_name_prefix(dp, "ATY,RageM3p12A")) { par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); if (par->cmap_adr) par->cmap_type = cmap_M3A; - } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) { + } else if (of_node_name_prefix(dp, "ATY,RageM3pB")) { par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); if (par->cmap_adr) par->cmap_type = cmap_M3B; - } else if (dp && !strncmp(name, "ATY,Rage6", 9)) { + } else if (of_node_name_prefix(dp, "ATY,Rage6")) { par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff); if (par->cmap_adr) par->cmap_type = cmap_radeon; - } else if (!strncmp(name, "ATY,", 4)) { + } else if (of_node_name_prefix(dp, "ATY,")) { unsigned long base = address & 0xff000000UL; par->cmap_adr = ioremap(base + 0x7ff000, 0x1000) + 0xcc0; @@ -350,7 +350,7 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000); if (par->cmap_adr) par->cmap_type = cmap_gxt2000; - } else if (dp && !strncmp(name, "vga,Display-", 12)) { + } else if (of_node_name_prefix(dp, "vga,Display-")) { /* Look for AVIVO initialized by SLOF */ struct device_node *pciparent = of_get_parent(dp); const u32 *vid, *did; @@ -438,7 +438,7 @@ static void __init offb_init_fb(const char *name, par->cmap_type = cmap_unknown; if (depth == 8) - offb_init_palette_hacks(info, dp, name, address); + offb_init_palette_hacks(info, dp, address); else fix->visual = FB_VISUAL_TRUECOLOR; diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c index 53f93616c671..8e23160ec59f 100644 --- a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c @@ -609,6 +609,8 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) int r = 0; + memset(&p, 0, sizeof(p)); + switch (cmd) { case OMAPFB_SYNC_GFX: DBG("ioctl SYNC_GFX\n"); diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig index 1e972c4e88b1..d1f6196c8b9a 100644 --- a/drivers/video/logo/Kconfig +++ b/drivers/video/logo/Kconfig @@ -10,15 +10,6 @@ menuconfig LOGO if LOGO -config FB_LOGO_CENTER - bool "Center the logo" - depends on FB=y - help - When this option is selected, the bootup logo is centered both - horizontally and vertically. If more than one logo is displayed - due to multiple CPUs, the collected line of logos is centered - as a whole. - config FB_LOGO_EXTRA bool depends on FB=y diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 728ecd1eea30..fb12fe205f86 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -61,6 +61,10 @@ enum virtio_balloon_vq { VIRTIO_BALLOON_VQ_MAX }; +enum virtio_balloon_config_read { + VIRTIO_BALLOON_CONFIG_READ_CMD_ID = 0, +}; + struct virtio_balloon { struct virtio_device *vdev; struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *free_page_vq; @@ -77,14 +81,20 @@ struct virtio_balloon { /* Prevent updating balloon when it is being canceled. */ spinlock_t stop_update_lock; bool stop_update; + /* Bitmap to indicate if reading the related config fields are needed */ + unsigned long config_read_bitmap; /* The list of allocated free pages, waiting to be given back to mm */ struct list_head free_page_list; spinlock_t free_page_list_lock; /* The number of free page blocks on the above list */ unsigned long num_free_page_blocks; - /* The cmd id received from host */ - u32 cmd_id_received; + /* + * The cmd id received from host. + * Read it via virtio_balloon_cmd_id_received to get the latest value + * sent from host. + */ + u32 cmd_id_received_cache; /* The cmd id that is actively in use */ __virtio32 cmd_id_active; /* Buffer to store the stop sign */ @@ -390,37 +400,31 @@ static unsigned long return_free_pages_to_mm(struct virtio_balloon *vb, return num_returned; } +static void virtio_balloon_queue_free_page_work(struct virtio_balloon *vb) +{ + if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) + return; + + /* No need to queue the work if the bit was already set. */ + if (test_and_set_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID, + &vb->config_read_bitmap)) + return; + + queue_work(vb->balloon_wq, &vb->report_free_page_work); +} + static void virtballoon_changed(struct virtio_device *vdev) { struct virtio_balloon *vb = vdev->priv; unsigned long flags; - s64 diff = towards_target(vb); - - if (diff) { - spin_lock_irqsave(&vb->stop_update_lock, flags); - if (!vb->stop_update) - queue_work(system_freezable_wq, - &vb->update_balloon_size_work); - spin_unlock_irqrestore(&vb->stop_update_lock, flags); - } - if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { - virtio_cread(vdev, struct virtio_balloon_config, - free_page_report_cmd_id, &vb->cmd_id_received); - if (vb->cmd_id_received == VIRTIO_BALLOON_CMD_ID_DONE) { - /* Pass ULONG_MAX to give back all the free pages */ - return_free_pages_to_mm(vb, ULONG_MAX); - } else if (vb->cmd_id_received != VIRTIO_BALLOON_CMD_ID_STOP && - vb->cmd_id_received != - virtio32_to_cpu(vdev, vb->cmd_id_active)) { - spin_lock_irqsave(&vb->stop_update_lock, flags); - if (!vb->stop_update) { - queue_work(vb->balloon_wq, - &vb->report_free_page_work); - } - spin_unlock_irqrestore(&vb->stop_update_lock, flags); - } + spin_lock_irqsave(&vb->stop_update_lock, flags); + if (!vb->stop_update) { + queue_work(system_freezable_wq, + &vb->update_balloon_size_work); + virtio_balloon_queue_free_page_work(vb); } + spin_unlock_irqrestore(&vb->stop_update_lock, flags); } static void update_balloon_size(struct virtio_balloon *vb) @@ -527,6 +531,17 @@ static int init_vqs(struct virtio_balloon *vb) return 0; } +static u32 virtio_balloon_cmd_id_received(struct virtio_balloon *vb) +{ + if (test_and_clear_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID, + &vb->config_read_bitmap)) + virtio_cread(vb->vdev, struct virtio_balloon_config, + free_page_report_cmd_id, + &vb->cmd_id_received_cache); + + return vb->cmd_id_received_cache; +} + static int send_cmd_id_start(struct virtio_balloon *vb) { struct scatterlist sg; @@ -537,7 +552,8 @@ static int send_cmd_id_start(struct virtio_balloon *vb) while (virtqueue_get_buf(vq, &unused)) ; - vb->cmd_id_active = cpu_to_virtio32(vb->vdev, vb->cmd_id_received); + vb->cmd_id_active = virtio32_to_cpu(vb->vdev, + virtio_balloon_cmd_id_received(vb)); sg_init_one(&sg, &vb->cmd_id_active, sizeof(vb->cmd_id_active)); err = virtqueue_add_outbuf(vq, &sg, 1, &vb->cmd_id_active, GFP_KERNEL); if (!err) @@ -620,7 +636,8 @@ static int send_free_pages(struct virtio_balloon *vb) * stop the reporting. */ cmd_id_active = virtio32_to_cpu(vb->vdev, vb->cmd_id_active); - if (cmd_id_active != vb->cmd_id_received) + if (unlikely(cmd_id_active != + virtio_balloon_cmd_id_received(vb))) break; /* @@ -637,11 +654,9 @@ static int send_free_pages(struct virtio_balloon *vb) return 0; } -static void report_free_page_func(struct work_struct *work) +static void virtio_balloon_report_free_page(struct virtio_balloon *vb) { int err; - struct virtio_balloon *vb = container_of(work, struct virtio_balloon, - report_free_page_work); struct device *dev = &vb->vdev->dev; /* Start by sending the received cmd id to host with an outbuf. */ @@ -659,6 +674,23 @@ static void report_free_page_func(struct work_struct *work) dev_err(dev, "Failed to send a stop id, err = %d\n", err); } +static void report_free_page_func(struct work_struct *work) +{ + struct virtio_balloon *vb = container_of(work, struct virtio_balloon, + report_free_page_work); + u32 cmd_id_received; + + cmd_id_received = virtio_balloon_cmd_id_received(vb); + if (cmd_id_received == VIRTIO_BALLOON_CMD_ID_DONE) { + /* Pass ULONG_MAX to give back all the free pages */ + return_free_pages_to_mm(vb, ULONG_MAX); + } else if (cmd_id_received != VIRTIO_BALLOON_CMD_ID_STOP && + cmd_id_received != + virtio32_to_cpu(vb->vdev, vb->cmd_id_active)) { + virtio_balloon_report_free_page(vb); + } +} + #ifdef CONFIG_BALLOON_COMPACTION /* * virtballoon_migratepage - perform the balloon page migration on behalf of @@ -885,7 +917,7 @@ static int virtballoon_probe(struct virtio_device *vdev) goto out_del_vqs; } INIT_WORK(&vb->report_free_page_work, report_free_page_func); - vb->cmd_id_received = VIRTIO_BALLOON_CMD_ID_STOP; + vb->cmd_id_received_cache = VIRTIO_BALLOON_CMD_ID_STOP; vb->cmd_id_active = cpu_to_virtio32(vb->vdev, VIRTIO_BALLOON_CMD_ID_STOP); vb->cmd_id_stop = cpu_to_virtio32(vb->vdev, diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 4cd9ea5c75be..d9dd0f789279 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -468,7 +468,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs, { struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); unsigned int irq = platform_get_irq(vm_dev->pdev, 0); - int i, err; + int i, err, queue_idx = 0; err = request_irq(irq, vm_interrupt, IRQF_SHARED, dev_name(&vdev->dev), vm_dev); @@ -476,7 +476,12 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs, return err; for (i = 0; i < nvqs; ++i) { - vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i], + if (!names[i]) { + vqs[i] = NULL; + continue; + } + + vqs[i] = vm_setup_vq(vdev, queue_idx++, callbacks[i], names[i], ctx ? ctx[i] : false); if (IS_ERR(vqs[i])) { vm_del_vqs(vdev); diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 465a6f5142cc..d0584c040c60 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c @@ -285,7 +285,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs, { struct virtio_pci_device *vp_dev = to_vp_device(vdev); u16 msix_vec; - int i, err, nvectors, allocated_vectors; + int i, err, nvectors, allocated_vectors, queue_idx = 0; vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL); if (!vp_dev->vqs) @@ -321,7 +321,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs, msix_vec = allocated_vectors++; else msix_vec = VP_MSIX_VQ_VECTOR; - vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i], + vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i], ctx ? ctx[i] : false, msix_vec); if (IS_ERR(vqs[i])) { @@ -356,7 +356,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs, const char * const names[], const bool *ctx) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); - int i, err; + int i, err, queue_idx = 0; vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL); if (!vp_dev->vqs) @@ -374,7 +374,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs, vqs[i] = NULL; continue; } - vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i], + vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i], ctx ? ctx[i] : false, VIRTIO_MSI_NO_VECTOR); if (IS_ERR(vqs[i])) { diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index cd7e755484e3..a0b07c331255 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -152,7 +152,12 @@ struct vring_virtqueue { /* Available for packed ring */ struct { /* Actual memory layout for this queue. */ - struct vring_packed vring; + struct { + unsigned int num; + struct vring_packed_desc *desc; + struct vring_packed_desc_event *driver; + struct vring_packed_desc_event *device; + } vring; /* Driver ring wrap counter. */ bool avail_wrap_counter; @@ -1609,6 +1614,9 @@ static struct virtqueue *vring_create_virtqueue_packed( !context; vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX); + if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM)) + vq->weak_barriers = false; + vq->packed.ring_dma_addr = ring_dma_addr; vq->packed.driver_event_dma_addr = driver_event_dma_addr; vq->packed.device_event_dma_addr = device_event_dma_addr; @@ -2079,6 +2087,9 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index, !context; vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX); + if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM)) + vq->weak_barriers = false; + vq->split.queue_dma_addr = 0; vq->split.queue_size_in_bytes = 0; @@ -2213,6 +2224,8 @@ void vring_transport_features(struct virtio_device *vdev) break; case VIRTIO_F_RING_PACKED: break; + case VIRTIO_F_ORDER_PLATFORM: + break; default: /* We don't understand this bit. */ __virtio_clear_bit(vdev, i); diff --git a/drivers/watchdog/mt7621_wdt.c b/drivers/watchdog/mt7621_wdt.c index 5c4a764717c4..81208cd3f4ec 100644 --- a/drivers/watchdog/mt7621_wdt.c +++ b/drivers/watchdog/mt7621_wdt.c @@ -17,6 +17,7 @@ #include <linux/watchdog.h> #include <linux/moduleparam.h> #include <linux/platform_device.h> +#include <linux/mod_devicetable.h> #include <asm/mach-ralink/ralink_regs.h> diff --git a/drivers/watchdog/rt2880_wdt.c b/drivers/watchdog/rt2880_wdt.c index 98967f0a7d10..db7c57d82cfd 100644 --- a/drivers/watchdog/rt2880_wdt.c +++ b/drivers/watchdog/rt2880_wdt.c @@ -18,6 +18,7 @@ #include <linux/watchdog.h> #include <linux/moduleparam.h> #include <linux/platform_device.h> +#include <linux/mod_devicetable.h> #include <asm/mach-ralink/ralink_regs.h> diff --git a/drivers/watchdog/tqmx86_wdt.c b/drivers/watchdog/tqmx86_wdt.c index 0d3a0fbbd7a5..52941207a12a 100644 --- a/drivers/watchdog/tqmx86_wdt.c +++ b/drivers/watchdog/tqmx86_wdt.c @@ -79,13 +79,13 @@ static int tqmx86_wdt_probe(struct platform_device *pdev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (IS_ERR(res)) - return PTR_ERR(res); + if (!res) + return -ENODEV; priv->io_base = devm_ioport_map(&pdev->dev, res->start, resource_size(res)); - if (IS_ERR(priv->io_base)) - return PTR_ERR(priv->io_base); + if (!priv->io_base) + return -ENOMEM; watchdog_set_drvdata(&priv->wdd, priv); diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 93194f3e7540..117e76b2f939 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -1650,7 +1650,7 @@ void xen_callback_vector(void) xen_have_vector_callback = 0; return; } - pr_info("Xen HVM callback vector for event delivery is enabled\n"); + pr_info_once("Xen HVM callback vector for event delivery is enabled\n"); alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, xen_hvm_callback_vector); } diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c index 2e5d845b5091..7aa64d1b119c 100644 --- a/drivers/xen/pvcalls-back.c +++ b/drivers/xen/pvcalls-back.c @@ -160,9 +160,10 @@ static void pvcalls_conn_back_read(void *opaque) /* write the data, then modify the indexes */ virt_wmb(); - if (ret < 0) + if (ret < 0) { + atomic_set(&map->read, 0); intf->in_error = ret; - else + } else intf->in_prod = prod + ret; /* update the indexes, then notify the other end */ virt_wmb(); @@ -282,13 +283,11 @@ static int pvcalls_back_socket(struct xenbus_device *dev, static void pvcalls_sk_state_change(struct sock *sock) { struct sock_mapping *map = sock->sk_user_data; - struct pvcalls_data_intf *intf; if (map == NULL) return; - intf = map->ring; - intf->in_error = -ENOTCONN; + atomic_inc(&map->read); notify_remote_via_irq(map->irq); } diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c index 77224d8f3e6f..8a249c95c193 100644 --- a/drivers/xen/pvcalls-front.c +++ b/drivers/xen/pvcalls-front.c @@ -31,6 +31,12 @@ #define PVCALLS_NR_RSP_PER_RING __CONST_RING_SIZE(xen_pvcalls, XEN_PAGE_SIZE) #define PVCALLS_FRONT_MAX_SPIN 5000 +static struct proto pvcalls_proto = { + .name = "PVCalls", + .owner = THIS_MODULE, + .obj_size = sizeof(struct sock), +}; + struct pvcalls_bedata { struct xen_pvcalls_front_ring ring; grant_ref_t ref; @@ -335,6 +341,42 @@ int pvcalls_front_socket(struct socket *sock) return ret; } +static void free_active_ring(struct sock_mapping *map) +{ + if (!map->active.ring) + return; + + free_pages((unsigned long)map->active.data.in, + map->active.ring->ring_order); + free_page((unsigned long)map->active.ring); +} + +static int alloc_active_ring(struct sock_mapping *map) +{ + void *bytes; + + map->active.ring = (struct pvcalls_data_intf *) + get_zeroed_page(GFP_KERNEL); + if (!map->active.ring) + goto out; + + map->active.ring->ring_order = PVCALLS_RING_ORDER; + bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, + PVCALLS_RING_ORDER); + if (!bytes) + goto out; + + map->active.data.in = bytes; + map->active.data.out = bytes + + XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER); + + return 0; + +out: + free_active_ring(map); + return -ENOMEM; +} + static int create_active(struct sock_mapping *map, int *evtchn) { void *bytes; @@ -343,15 +385,7 @@ static int create_active(struct sock_mapping *map, int *evtchn) *evtchn = -1; init_waitqueue_head(&map->active.inflight_conn_req); - map->active.ring = (struct pvcalls_data_intf *) - __get_free_page(GFP_KERNEL | __GFP_ZERO); - if (map->active.ring == NULL) - goto out_error; - map->active.ring->ring_order = PVCALLS_RING_ORDER; - bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, - PVCALLS_RING_ORDER); - if (bytes == NULL) - goto out_error; + bytes = map->active.data.in; for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++) map->active.ring->ref[i] = gnttab_grant_foreign_access( pvcalls_front_dev->otherend_id, @@ -361,10 +395,6 @@ static int create_active(struct sock_mapping *map, int *evtchn) pvcalls_front_dev->otherend_id, pfn_to_gfn(virt_to_pfn((void *)map->active.ring)), 0); - map->active.data.in = bytes; - map->active.data.out = bytes + - XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER); - ret = xenbus_alloc_evtchn(pvcalls_front_dev, evtchn); if (ret) goto out_error; @@ -385,8 +415,6 @@ static int create_active(struct sock_mapping *map, int *evtchn) out_error: if (*evtchn >= 0) xenbus_free_evtchn(pvcalls_front_dev, *evtchn); - free_pages((unsigned long)map->active.data.in, PVCALLS_RING_ORDER); - free_page((unsigned long)map->active.ring); return ret; } @@ -406,17 +434,24 @@ int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr, return PTR_ERR(map); bedata = dev_get_drvdata(&pvcalls_front_dev->dev); + ret = alloc_active_ring(map); + if (ret < 0) { + pvcalls_exit_sock(sock); + return ret; + } spin_lock(&bedata->socket_lock); ret = get_request(bedata, &req_id); if (ret < 0) { spin_unlock(&bedata->socket_lock); + free_active_ring(map); pvcalls_exit_sock(sock); return ret; } ret = create_active(map, &evtchn); if (ret < 0) { spin_unlock(&bedata->socket_lock); + free_active_ring(map); pvcalls_exit_sock(sock); return ret; } @@ -469,8 +504,10 @@ static int __write_ring(struct pvcalls_data_intf *intf, virt_mb(); size = pvcalls_queued(prod, cons, array_size); - if (size >= array_size) + if (size > array_size) return -EINVAL; + if (size == array_size) + return 0; if (len > array_size - size) len = array_size - size; @@ -560,15 +597,13 @@ static int __read_ring(struct pvcalls_data_intf *intf, error = intf->in_error; /* get pointers before reading from the ring */ virt_rmb(); - if (error < 0) - return error; size = pvcalls_queued(prod, cons, array_size); masked_prod = pvcalls_mask(prod, array_size); masked_cons = pvcalls_mask(cons, array_size); if (size == 0) - return 0; + return error ?: size; if (len > size) len = size; @@ -780,25 +815,36 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags) } } - spin_lock(&bedata->socket_lock); - ret = get_request(bedata, &req_id); - if (ret < 0) { + map2 = kzalloc(sizeof(*map2), GFP_KERNEL); + if (map2 == NULL) { clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, (void *)&map->passive.flags); - spin_unlock(&bedata->socket_lock); + pvcalls_exit_sock(sock); + return -ENOMEM; + } + ret = alloc_active_ring(map2); + if (ret < 0) { + clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, + (void *)&map->passive.flags); + kfree(map2); pvcalls_exit_sock(sock); return ret; } - map2 = kzalloc(sizeof(*map2), GFP_ATOMIC); - if (map2 == NULL) { + spin_lock(&bedata->socket_lock); + ret = get_request(bedata, &req_id); + if (ret < 0) { clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, (void *)&map->passive.flags); spin_unlock(&bedata->socket_lock); + free_active_ring(map2); + kfree(map2); pvcalls_exit_sock(sock); - return -ENOMEM; + return ret; } + ret = create_active(map2, &evtchn); if (ret < 0) { + free_active_ring(map2); kfree(map2); clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, (void *)&map->passive.flags); @@ -839,7 +885,7 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags) received: map2->sock = newsock; - newsock->sk = kzalloc(sizeof(*newsock->sk), GFP_KERNEL); + newsock->sk = sk_alloc(sock_net(sock->sk), PF_INET, GFP_KERNEL, &pvcalls_proto, false); if (!newsock->sk) { bedata->rsp[req_id].req_id = PVCALLS_INVALID_ID; map->passive.inflight_req_id = PVCALLS_INVALID_ID; @@ -1032,8 +1078,8 @@ int pvcalls_front_release(struct socket *sock) spin_lock(&bedata->socket_lock); list_del(&map->list); spin_unlock(&bedata->socket_lock); - if (READ_ONCE(map->passive.inflight_req_id) != - PVCALLS_INVALID_ID) { + if (READ_ONCE(map->passive.inflight_req_id) != PVCALLS_INVALID_ID && + READ_ONCE(map->passive.inflight_req_id) != 0) { pvcalls_front_free_map(bedata, map->passive.accept_map); } diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 989cf872b98c..bb7888429be6 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -645,7 +645,7 @@ xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma, void *cpu_addr, dma_addr_t dma_addr, size_t size, unsigned long attrs) { -#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) +#ifdef CONFIG_ARM if (xen_get_dma_ops(dev)->mmap) return xen_get_dma_ops(dev)->mmap(dev, vma, cpu_addr, dma_addr, size, attrs); @@ -662,7 +662,7 @@ xen_swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt, void *cpu_addr, dma_addr_t handle, size_t size, unsigned long attrs) { -#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) +#ifdef CONFIG_ARM if (xen_get_dma_ops(dev)->get_sgtable) { #if 0 /* |