diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/auxiliary.c | 4 | ||||
-rw-r--r-- | drivers/base/base.h | 3 | ||||
-rw-r--r-- | drivers/base/bus.c | 6 | ||||
-rw-r--r-- | drivers/base/cacheinfo.c | 1 | ||||
-rw-r--r-- | drivers/base/core.c | 43 | ||||
-rw-r--r-- | drivers/base/cpu.c | 4 | ||||
-rw-r--r-- | drivers/base/dd.c | 16 | ||||
-rw-r--r-- | drivers/base/firmware_loader/main.c | 20 | ||||
-rw-r--r-- | drivers/base/isa.c | 4 | ||||
-rw-r--r-- | drivers/base/map.c | 12 | ||||
-rw-r--r-- | drivers/base/node.c | 71 | ||||
-rw-r--r-- | drivers/base/platform-msi.c | 20 | ||||
-rw-r--r-- | drivers/base/platform.c | 24 | ||||
-rw-r--r-- | drivers/base/power/clock_ops.c | 17 | ||||
-rw-r--r-- | drivers/base/power/domain.c | 30 | ||||
-rw-r--r-- | drivers/base/power/runtime.c | 17 | ||||
-rw-r--r-- | drivers/base/power/wakeup.c | 2 | ||||
-rw-r--r-- | drivers/base/property.c | 30 | ||||
-rw-r--r-- | drivers/base/regmap/internal.h | 4 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-debugfs.c | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-mmio.c | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 49 | ||||
-rw-r--r-- | drivers/base/swnode.c | 61 | ||||
-rw-r--r-- | drivers/base/topology.c | 115 |
24 files changed, 340 insertions, 217 deletions
diff --git a/drivers/base/auxiliary.c b/drivers/base/auxiliary.c index 6a30264ab2ba..9230c9472bb0 100644 --- a/drivers/base/auxiliary.c +++ b/drivers/base/auxiliary.c @@ -79,7 +79,7 @@ static int auxiliary_bus_probe(struct device *dev) return ret; } -static int auxiliary_bus_remove(struct device *dev) +static void auxiliary_bus_remove(struct device *dev) { struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver); struct auxiliary_device *auxdev = to_auxiliary_dev(dev); @@ -87,8 +87,6 @@ static int auxiliary_bus_remove(struct device *dev) if (auxdrv->remove) auxdrv->remove(auxdev); dev_pm_domain_detach(dev, true); - - return 0; } static void auxiliary_bus_shutdown(struct device *dev) diff --git a/drivers/base/base.h b/drivers/base/base.h index 404db83ee5ec..2882af26392a 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -202,3 +202,6 @@ int devtmpfs_delete_node(struct device *dev); static inline int devtmpfs_create_node(struct device *dev) { return 0; } static inline int devtmpfs_delete_node(struct device *dev) { return 0; } #endif + +void software_node_notify(struct device *dev); +void software_node_notify_remove(struct device *dev); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 1f6b4bd61056..bdc98c5713d5 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -195,7 +195,7 @@ static ssize_t unbind_store(struct device_driver *drv, const char *buf, bus_put(bus); return err; } -static DRIVER_ATTR_IGNORE_LOCKDEP(unbind, S_IWUSR, NULL, unbind_store); +static DRIVER_ATTR_IGNORE_LOCKDEP(unbind, 0200, NULL, unbind_store); /* * Manually attach a device to a driver. @@ -221,7 +221,7 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf, bus_put(bus); return err; } -static DRIVER_ATTR_IGNORE_LOCKDEP(bind, S_IWUSR, NULL, bind_store); +static DRIVER_ATTR_IGNORE_LOCKDEP(bind, 0200, NULL, bind_store); static ssize_t drivers_autoprobe_show(struct bus_type *bus, char *buf) { @@ -767,7 +767,7 @@ static ssize_t bus_uevent_store(struct bus_type *bus, * DEVICE_ATTR_WO(uevent), which would cause a clash with the with the store * function name. */ -static struct bus_attribute bus_attr_uevent = __ATTR(uevent, S_IWUSR, NULL, +static struct bus_attribute bus_attr_uevent = __ATTR(uevent, 0200, NULL, bus_uevent_store); /** diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index bfc095956dd1..dad296229161 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -297,6 +297,7 @@ static void free_cache_attributes(unsigned int cpu) kfree(per_cpu_cacheinfo(cpu)); per_cpu_cacheinfo(cpu) = NULL; + cache_leaves(cpu) = 0; } int __weak init_cache_level(unsigned int cpu) diff --git a/drivers/base/core.c b/drivers/base/core.c index 6c0ef9d55a34..688a592ad569 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -886,6 +886,8 @@ static void device_link_put_kref(struct device_link *link) { if (link->flags & DL_FLAG_STATELESS) kref_put(&link->kref, __device_link_del); + else if (!device_is_registered(link->consumer)) + __device_link_del(&link->kref); else WARN(1, "Unable to drop a managed device link reference\n"); } @@ -2002,24 +2004,24 @@ static inline int device_is_not_partition(struct device *dev) } #endif -static int -device_platform_notify(struct device *dev, enum kobject_action action) +static void device_platform_notify(struct device *dev) { - int ret; + acpi_device_notify(dev); - ret = acpi_platform_notify(dev, action); - if (ret) - return ret; - - ret = software_node_notify(dev, action); - if (ret) - return ret; + software_node_notify(dev); - if (platform_notify && action == KOBJ_ADD) + if (platform_notify) platform_notify(dev); - else if (platform_notify_remove && action == KOBJ_REMOVE) +} + +static void device_platform_notify_remove(struct device *dev) +{ + acpi_device_notify_remove(dev); + + software_node_notify_remove(dev); + + if (platform_notify_remove) platform_notify_remove(dev); - return 0; } /** @@ -3292,9 +3294,7 @@ int device_add(struct device *dev) } /* notify platform of device entry */ - error = device_platform_notify(dev, KOBJ_ADD); - if (error) - goto platform_error; + device_platform_notify(dev); error = device_create_file(dev, &dev_attr_uevent); if (error) @@ -3397,8 +3397,7 @@ done: SymlinkError: device_remove_file(dev, &dev_attr_uevent); attrError: - device_platform_notify(dev, KOBJ_REMOVE); -platform_error: + device_platform_notify_remove(dev); kobject_uevent(&dev->kobj, KOBJ_REMOVE); glue_dir = get_glue_dir(dev); kobject_del(&dev->kobj); @@ -3543,7 +3542,7 @@ void device_del(struct device *dev) bus_remove_device(dev); device_pm_remove(dev); driver_deferred_probe_del(dev); - device_platform_notify(dev, KOBJ_REMOVE); + device_platform_notify_remove(dev); device_remove_properties(dev); device_links_purge(dev); @@ -4582,8 +4581,8 @@ static void __dev_printk(const char *level, const struct device *dev, printk("%s(NULL device *): %pV", level, vaf); } -void dev_printk(const char *level, const struct device *dev, - const char *fmt, ...) +void _dev_printk(const char *level, const struct device *dev, + const char *fmt, ...) { struct va_format vaf; va_list args; @@ -4597,7 +4596,7 @@ void dev_printk(const char *level, const struct device *dev, va_end(args); } -EXPORT_SYMBOL(dev_printk); +EXPORT_SYMBOL(_dev_printk); #define define_dev_printk_level(func, kern_level) \ void func(const struct device *dev, const char *fmt, ...) \ diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 5ef14db97904..5fc258073bc7 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -388,7 +388,7 @@ int register_cpu(struct cpu *cpu, int num) return 0; } -struct device *get_cpu_device(unsigned cpu) +struct device *get_cpu_device(unsigned int cpu) { if (cpu < nr_cpu_ids && cpu_possible(cpu)) return per_cpu(cpu_sys_devices, cpu); @@ -484,7 +484,7 @@ static const struct attribute_group *cpu_root_attr_groups[] = { NULL, }; -bool cpu_is_hotpluggable(unsigned cpu) +bool cpu_is_hotpluggable(unsigned int cpu) { struct device *dev = get_cpu_device(cpu); return dev && container_of(dev, struct cpu, dev)->hotpluggable; diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 437cd61343b2..68ea1f949daa 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -580,7 +580,8 @@ re_probe: goto probe_failed; } - if (driver_sysfs_add(dev)) { + ret = driver_sysfs_add(dev); + if (ret) { pr_err("%s: driver_sysfs_add(%s) failed\n", __func__, dev_name(dev)); goto probe_failed; @@ -602,15 +603,18 @@ re_probe: goto probe_failed; } - if (device_add_groups(dev, drv->dev_groups)) { + ret = device_add_groups(dev, drv->dev_groups); + if (ret) { dev_err(dev, "device_add_groups() failed\n"); goto dev_groups_failed; } - if (dev_has_sync_state(dev) && - device_create_file(dev, &dev_attr_state_synced)) { - dev_err(dev, "state_synced sysfs add failed\n"); - goto dev_sysfs_state_synced_failed; + if (dev_has_sync_state(dev)) { + ret = device_create_file(dev, &dev_attr_state_synced); + if (ret) { + dev_err(dev, "state_synced sysfs add failed\n"); + goto dev_sysfs_state_synced_failed; + } } if (test_remove) { diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index 68c549d71230..bdbedc6660a8 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -165,7 +165,7 @@ static inline int fw_state_wait(struct fw_priv *fw_priv) return __fw_state_wait_common(fw_priv, MAX_SCHEDULE_TIMEOUT); } -static int fw_cache_piggyback_on_request(const char *name); +static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv); static struct fw_priv *__allocate_fw_priv(const char *fw_name, struct firmware_cache *fwc, @@ -707,10 +707,8 @@ int assign_fw(struct firmware *fw, struct device *device) * on request firmware. */ if (!(fw_priv->opt_flags & FW_OPT_NOCACHE) && - fw_priv->fwc->state == FW_LOADER_START_CACHE) { - if (fw_cache_piggyback_on_request(fw_priv->fw_name)) - kref_get(&fw_priv->ref); - } + fw_priv->fwc->state == FW_LOADER_START_CACHE) + fw_cache_piggyback_on_request(fw_priv); /* pass the pages buffer to driver at the last minute */ fw_set_page_data(fw_priv, fw); @@ -1259,11 +1257,11 @@ static int __fw_entry_found(const char *name) return 0; } -static int fw_cache_piggyback_on_request(const char *name) +static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv) { - struct firmware_cache *fwc = &fw_cache; + const char *name = fw_priv->fw_name; + struct firmware_cache *fwc = fw_priv->fwc; struct fw_cache_entry *fce; - int ret = 0; spin_lock(&fwc->name_lock); if (__fw_entry_found(name)) @@ -1271,13 +1269,12 @@ static int fw_cache_piggyback_on_request(const char *name) fce = alloc_fw_cache_entry(name); if (fce) { - ret = 1; list_add(&fce->list, &fwc->fw_names); + kref_get(&fw_priv->ref); pr_debug("%s: fw: %s\n", __func__, name); } found: spin_unlock(&fwc->name_lock); - return ret; } static void free_fw_cache_entry(struct fw_cache_entry *fce) @@ -1508,9 +1505,8 @@ static inline void unregister_fw_pm_ops(void) unregister_pm_notifier(&fw_cache.pm_notify); } #else -static int fw_cache_piggyback_on_request(const char *name) +static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv) { - return 0; } static inline int register_fw_pm_ops(void) { diff --git a/drivers/base/isa.c b/drivers/base/isa.c index aa4737667026..55e3ee2da98f 100644 --- a/drivers/base/isa.c +++ b/drivers/base/isa.c @@ -46,14 +46,12 @@ static int isa_bus_probe(struct device *dev) return 0; } -static int isa_bus_remove(struct device *dev) +static void isa_bus_remove(struct device *dev) { struct isa_driver *isa_driver = dev->platform_data; if (isa_driver && isa_driver->remove) isa_driver->remove(dev, to_isa_dev(dev)->id); - - return 0; } static void isa_bus_shutdown(struct device *dev) diff --git a/drivers/base/map.c b/drivers/base/map.c index 5650ab2b247a..83aeb09ca161 100644 --- a/drivers/base/map.c +++ b/drivers/base/map.c @@ -33,9 +33,9 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, struct module *module, kobj_probe_t *probe, int (*lock)(dev_t, void *), void *data) { - unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; - unsigned index = MAJOR(dev); - unsigned i; + unsigned int n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; + unsigned int index = MAJOR(dev); + unsigned int i; struct probe *p; if (n > 255) @@ -67,9 +67,9 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range) { - unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; - unsigned index = MAJOR(dev); - unsigned i; + unsigned int n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; + unsigned int index = MAJOR(dev); + unsigned int i; struct probe *found = NULL; if (n > 255) diff --git a/drivers/base/node.c b/drivers/base/node.c index 4a4ae868ad9f..be16bbff11cc 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -26,43 +26,47 @@ static struct bus_type node_subsys = { .dev_name = "node", }; - -static ssize_t node_read_cpumap(struct device *dev, bool list, char *buf) +static inline ssize_t cpumap_read(struct file *file, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) { - ssize_t n; - cpumask_var_t mask; + struct device *dev = kobj_to_dev(kobj); struct node *node_dev = to_node(dev); - - /* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */ - BUILD_BUG_ON((NR_CPUS/32 * 9) > (PAGE_SIZE-1)); + cpumask_var_t mask; + ssize_t n; if (!alloc_cpumask_var(&mask, GFP_KERNEL)) return 0; cpumask_and(mask, cpumask_of_node(node_dev->dev.id), cpu_online_mask); - n = cpumap_print_to_pagebuf(list, buf, mask); + n = cpumap_print_bitmask_to_buf(buf, mask, off, count); free_cpumask_var(mask); return n; } -static inline ssize_t cpumap_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static BIN_ATTR_RO(cpumap, 0); + +static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) { - return node_read_cpumap(dev, false, buf); -} + struct device *dev = kobj_to_dev(kobj); + struct node *node_dev = to_node(dev); + cpumask_var_t mask; + ssize_t n; + + if (!alloc_cpumask_var(&mask, GFP_KERNEL)) + return 0; -static DEVICE_ATTR_RO(cpumap); + cpumask_and(mask, cpumask_of_node(node_dev->dev.id), cpu_online_mask); + n = cpumap_print_list_to_buf(buf, mask, off, count); + free_cpumask_var(mask); -static inline ssize_t cpulist_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return node_read_cpumap(dev, true, buf); + return n; } -static DEVICE_ATTR_RO(cpulist); +static BIN_ATTR_RO(cpulist, 0); /** * struct node_access_nodes - Access class device to hold user visible @@ -75,7 +79,7 @@ static DEVICE_ATTR_RO(cpulist); struct node_access_nodes { struct device dev; struct list_head list_node; - unsigned access; + unsigned int access; #ifdef CONFIG_HMEM_REPORTING struct node_hmem_attrs hmem_attrs; #endif @@ -122,7 +126,7 @@ static void node_access_release(struct device *dev) } static struct node_access_nodes *node_init_node_access(struct node *node, - unsigned access) + unsigned int access) { struct node_access_nodes *access_node; struct device *dev; @@ -187,7 +191,7 @@ static struct attribute *access_attrs[] = { * @access: The access class the for the given attributes */ void node_set_perf_attrs(unsigned int nid, struct node_hmem_attrs *hmem_attrs, - unsigned access) + unsigned int access) { struct node_access_nodes *c; struct node *node; @@ -557,15 +561,28 @@ static ssize_t node_read_distance(struct device *dev, static DEVICE_ATTR(distance, 0444, node_read_distance, NULL); static struct attribute *node_dev_attrs[] = { - &dev_attr_cpumap.attr, - &dev_attr_cpulist.attr, &dev_attr_meminfo.attr, &dev_attr_numastat.attr, &dev_attr_distance.attr, &dev_attr_vmstat.attr, NULL }; -ATTRIBUTE_GROUPS(node_dev); + +static struct bin_attribute *node_dev_bin_attrs[] = { + &bin_attr_cpumap, + &bin_attr_cpulist, + NULL +}; + +static const struct attribute_group node_dev_group = { + .attrs = node_dev_attrs, + .bin_attrs = node_dev_bin_attrs +}; + +static const struct attribute_group *node_dev_groups[] = { + &node_dev_group, + NULL +}; #ifdef CONFIG_HUGETLBFS /* @@ -711,7 +728,7 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid) */ int register_memory_node_under_compute_node(unsigned int mem_nid, unsigned int cpu_nid, - unsigned access) + unsigned int access) { struct node *init_node, *targ_node; struct node_access_nodes *initiator, *target; diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c index 0b72b134a304..3d6c8f9caf43 100644 --- a/drivers/base/platform-msi.c +++ b/drivers/base/platform-msi.c @@ -21,11 +21,12 @@ * and the callback to write the MSI message. */ struct platform_msi_priv_data { - struct device *dev; - void *host_data; - msi_alloc_info_t arg; - irq_write_msi_msg_t write_msg; - int devid; + struct device *dev; + void *host_data; + const struct attribute_group **msi_irq_groups; + msi_alloc_info_t arg; + irq_write_msi_msg_t write_msg; + int devid; }; /* The devid allocator */ @@ -272,8 +273,16 @@ int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec, if (err) goto out_free_desc; + priv_data->msi_irq_groups = msi_populate_sysfs(dev); + if (IS_ERR(priv_data->msi_irq_groups)) { + err = PTR_ERR(priv_data->msi_irq_groups); + goto out_free_irqs; + } + return 0; +out_free_irqs: + msi_domain_free_irqs(dev->msi_domain, dev); out_free_desc: platform_msi_free_descs(dev, 0, nvec); out_free_priv_data: @@ -293,6 +302,7 @@ void platform_msi_domain_free_irqs(struct device *dev) struct msi_desc *desc; desc = first_msi_entry(dev); + msi_destroy_sysfs(dev, desc->platform.msi_priv_data->msi_irq_groups); platform_msi_free_priv_data(desc->platform.msi_priv_data); } diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 8640578f45e9..652531f67135 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -642,22 +642,6 @@ int platform_device_add_data(struct platform_device *pdev, const void *data, EXPORT_SYMBOL_GPL(platform_device_add_data); /** - * platform_device_add_properties - add built-in properties to a platform device - * @pdev: platform device to add properties to - * @properties: null terminated array of properties to add - * - * The function will take deep copy of @properties and attach the copy to the - * platform device. The memory associated with properties will be freed when the - * platform device is released. - */ -int platform_device_add_properties(struct platform_device *pdev, - const struct property_entry *properties) -{ - return device_add_properties(&pdev->dev, properties); -} -EXPORT_SYMBOL_GPL(platform_device_add_properties); - -/** * platform_device_add - add a platform device to device hierarchy * @pdev: platform device we're adding * @@ -842,8 +826,8 @@ struct platform_device *platform_device_register_full( goto err; if (pdevinfo->properties) { - ret = platform_device_add_properties(pdev, - pdevinfo->properties); + ret = device_create_managed_software_node(&pdev->dev, + pdevinfo->properties, NULL); if (ret) goto err; } @@ -1438,7 +1422,7 @@ out: return ret; } -static int platform_remove(struct device *_dev) +static void platform_remove(struct device *_dev) { struct platform_driver *drv = to_platform_driver(_dev->driver); struct platform_device *dev = to_platform_device(_dev); @@ -1450,8 +1434,6 @@ static int platform_remove(struct device *_dev) dev_warn(_dev, "remove callback returned a non-zero value. This will be ignored.\n"); } dev_pm_domain_detach(_dev, true); - - return 0; } static void platform_shutdown(struct device *_dev) diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 0251f3e6e61d..4110c19c08dc 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -519,6 +519,23 @@ void pm_clk_destroy(struct device *dev) } EXPORT_SYMBOL_GPL(pm_clk_destroy); +static void pm_clk_destroy_action(void *data) +{ + pm_clk_destroy(data); +} + +int devm_pm_clk_create(struct device *dev) +{ + int ret; + + ret = pm_clk_create(dev); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, pm_clk_destroy_action, dev); +} +EXPORT_SYMBOL_GPL(devm_pm_clk_create); + /** * pm_clk_suspend - Disable clocks in a device's PM clock list. * @dev: Device to disable the clocks for. diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index f10688e83226..5db704f02e71 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2604,6 +2604,12 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); + /* Drop the default performance state */ + if (dev_gpd_data(dev)->default_pstate) { + dev_pm_genpd_set_performance_state(dev, 0); + dev_gpd_data(dev)->default_pstate = 0; + } + for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { ret = genpd_remove_device(pd, dev); if (ret != -EAGAIN) @@ -2643,6 +2649,7 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev, { struct of_phandle_args pd_args; struct generic_pm_domain *pd; + int pstate; int ret; ret = of_parse_phandle_with_args(dev->of_node, "power-domains", @@ -2681,10 +2688,29 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev, genpd_unlock(pd); } - if (ret) + if (ret) { genpd_remove_device(pd, dev); + return -EPROBE_DEFER; + } - return ret ? -EPROBE_DEFER : 1; + /* Set the default performance state */ + pstate = of_get_required_opp_performance_state(dev->of_node, index); + if (pstate < 0 && pstate != -ENODEV && pstate != -EOPNOTSUPP) { + ret = pstate; + goto err; + } else if (pstate > 0) { + ret = dev_pm_genpd_set_performance_state(dev, pstate); + if (ret) + goto err; + dev_gpd_data(dev)->default_pstate = pstate; + } + return 1; + +err: + dev_err(dev, "failed to set required performance state for power-domain %s: %d\n", + pd->name, ret); + genpd_remove_device(pd, dev); + return ret; } /** diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 8a66eaf731e4..ec94049442b9 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1447,6 +1447,23 @@ void pm_runtime_enable(struct device *dev) } EXPORT_SYMBOL_GPL(pm_runtime_enable); +static void pm_runtime_disable_action(void *data) +{ + pm_runtime_disable(data); +} + +/** + * devm_pm_runtime_enable - devres-enabled version of pm_runtime_enable. + * @dev: Device to handle. + */ +int devm_pm_runtime_enable(struct device *dev) +{ + pm_runtime_enable(dev); + + return devm_add_action_or_reset(dev, pm_runtime_disable_action, dev); +} +EXPORT_SYMBOL_GPL(devm_pm_runtime_enable); + /** * pm_runtime_forbid - Block runtime PM of a device. * @dev: Device to handle. diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index f0b37c188514..99bda0da23a8 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -1180,7 +1180,7 @@ static const struct file_operations wakeup_sources_stats_fops = { static int __init wakeup_sources_debugfs_init(void) { - debugfs_create_file("wakeup_sources", S_IRUGO, NULL, NULL, + debugfs_create_file("wakeup_sources", 0444, NULL, NULL, &wakeup_sources_stats_fops); return 0; } diff --git a/drivers/base/property.c b/drivers/base/property.c index d0874f6c29bb..453918eb7390 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -1033,7 +1033,26 @@ struct fwnode_handle * fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode, struct fwnode_handle *prev) { - return fwnode_call_ptr_op(fwnode, graph_get_next_endpoint, prev); + const struct fwnode_handle *parent; + struct fwnode_handle *ep; + + /* + * If this function is in a loop and the previous iteration returned + * an endpoint from fwnode->secondary, then we need to use the secondary + * as parent rather than @fwnode. + */ + if (prev) + parent = fwnode_graph_get_port_parent(prev); + else + parent = fwnode; + + ep = fwnode_call_ptr_op(parent, graph_get_next_endpoint, prev); + + if (IS_ERR_OR_NULL(ep) && + !IS_ERR_OR_NULL(parent) && !IS_ERR_OR_NULL(parent->secondary)) + ep = fwnode_graph_get_next_endpoint(parent->secondary, NULL); + + return ep; } EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint); @@ -1212,14 +1231,7 @@ fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode, best_ep_id = fwnode_ep.id; } - if (best_ep) - return best_ep; - - if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary)) - return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port, - endpoint, flags); - - return NULL; + return best_ep; } EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id); diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 0097696c31de..b1905916f7af 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -53,6 +53,10 @@ struct regmap { spinlock_t spinlock; unsigned long spinlock_flags; }; + struct { + raw_spinlock_t raw_spinlock; + unsigned long raw_spinlock_flags; + }; }; regmap_lock lock; regmap_unlock unlock; diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 211a335a608d..ad684d37c2da 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -368,7 +368,7 @@ static ssize_t regmap_reg_ranges_read_file(struct file *file, char *buf; char *entry; int ret; - unsigned entry_len; + unsigned int entry_len; if (*ppos < 0 || !count) return -EINVAL; diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index f9cd51afb9d2..71f16be7e717 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -15,7 +15,7 @@ struct regmap_mmio_context { void __iomem *regs; - unsigned val_bytes; + unsigned int val_bytes; bool relaxed_mmio; bool attached_clk; diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index fe3e38dd5324..21a0c2562ec0 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -533,6 +533,23 @@ __releases(&map->spinlock) spin_unlock_irqrestore(&map->spinlock, map->spinlock_flags); } +static void regmap_lock_raw_spinlock(void *__map) +__acquires(&map->raw_spinlock) +{ + struct regmap *map = __map; + unsigned long flags; + + raw_spin_lock_irqsave(&map->raw_spinlock, flags); + map->raw_spinlock_flags = flags; +} + +static void regmap_unlock_raw_spinlock(void *__map) +__releases(&map->raw_spinlock) +{ + struct regmap *map = __map; + raw_spin_unlock_irqrestore(&map->raw_spinlock, map->raw_spinlock_flags); +} + static void dev_get_regmap_release(struct device *dev, void *res) { /* @@ -770,11 +787,19 @@ struct regmap *__regmap_init(struct device *dev, } else { if ((bus && bus->fast_io) || config->fast_io) { - spin_lock_init(&map->spinlock); - map->lock = regmap_lock_spinlock; - map->unlock = regmap_unlock_spinlock; - lockdep_set_class_and_name(&map->spinlock, - lock_key, lock_name); + if (config->use_raw_spinlock) { + raw_spin_lock_init(&map->raw_spinlock); + map->lock = regmap_lock_raw_spinlock; + map->unlock = regmap_unlock_raw_spinlock; + lockdep_set_class_and_name(&map->raw_spinlock, + lock_key, lock_name); + } else { + spin_lock_init(&map->spinlock); + map->lock = regmap_lock_spinlock; + map->unlock = regmap_unlock_spinlock; + lockdep_set_class_and_name(&map->spinlock, + lock_key, lock_name); + } } else { mutex_init(&map->mutex); map->lock = regmap_lock_mutex; @@ -1126,10 +1151,10 @@ skip_format_initialization: /* Make sure, that this register range has no selector or data window within its boundary */ for (j = 0; j < config->num_ranges; j++) { - unsigned sel_reg = config->ranges[j].selector_reg; - unsigned win_min = config->ranges[j].window_start; - unsigned win_max = win_min + - config->ranges[j].window_len - 1; + unsigned int sel_reg = config->ranges[j].selector_reg; + unsigned int win_min = config->ranges[j].window_start; + unsigned int win_max = win_min + + config->ranges[j].window_len - 1; /* Allow data window inside its own virtual range */ if (j == i) @@ -1298,7 +1323,7 @@ EXPORT_SYMBOL_GPL(devm_regmap_field_alloc); */ int regmap_field_bulk_alloc(struct regmap *regmap, struct regmap_field **rm_field, - struct reg_field *reg_field, + const struct reg_field *reg_field, int num_fields) { struct regmap_field *rf; @@ -1334,7 +1359,7 @@ EXPORT_SYMBOL_GPL(regmap_field_bulk_alloc); int devm_regmap_field_bulk_alloc(struct device *dev, struct regmap *regmap, struct regmap_field **rm_field, - struct reg_field *reg_field, + const struct reg_field *reg_field, int num_fields) { struct regmap_field *rf; @@ -1667,7 +1692,7 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg, if (ret) { dev_err(map->dev, "Error in caching of register: %x ret: %d\n", - reg + i, ret); + reg + regmap_get_offset(map, i), ret); return ret; } } diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index d1f1a8240120..7bd0f3cfb7eb 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -11,6 +11,8 @@ #include <linux/property.h> #include <linux/slab.h> +#include "base.h" + struct swnode { struct kobject kobj; struct fwnode_handle fwnode; @@ -1053,7 +1055,7 @@ int device_add_software_node(struct device *dev, const struct software_node *nod * balance. */ if (device_is_registered(dev)) - software_node_notify(dev, KOBJ_ADD); + software_node_notify(dev); return 0; } @@ -1074,7 +1076,8 @@ void device_remove_software_node(struct device *dev) return; if (device_is_registered(dev)) - software_node_notify(dev, KOBJ_REMOVE); + software_node_notify_remove(dev); + set_secondary_fwnode(dev, NULL); kobject_put(&swnode->kobj); } @@ -1117,44 +1120,44 @@ int device_create_managed_software_node(struct device *dev, } EXPORT_SYMBOL_GPL(device_create_managed_software_node); -int software_node_notify(struct device *dev, unsigned long action) +void software_node_notify(struct device *dev) { struct swnode *swnode; int ret; swnode = dev_to_swnode(dev); if (!swnode) - return 0; + return; - switch (action) { - case KOBJ_ADD: - ret = sysfs_create_link(&dev->kobj, &swnode->kobj, "software_node"); - if (ret) - break; + ret = sysfs_create_link(&dev->kobj, &swnode->kobj, "software_node"); + if (ret) + return; - ret = sysfs_create_link(&swnode->kobj, &dev->kobj, - dev_name(dev)); - if (ret) { - sysfs_remove_link(&dev->kobj, "software_node"); - break; - } - kobject_get(&swnode->kobj); - break; - case KOBJ_REMOVE: - sysfs_remove_link(&swnode->kobj, dev_name(dev)); + ret = sysfs_create_link(&swnode->kobj, &dev->kobj, dev_name(dev)); + if (ret) { sysfs_remove_link(&dev->kobj, "software_node"); - kobject_put(&swnode->kobj); - - if (swnode->managed) { - set_secondary_fwnode(dev, NULL); - kobject_put(&swnode->kobj); - } - break; - default: - break; + return; } - return 0; + kobject_get(&swnode->kobj); +} + +void software_node_notify_remove(struct device *dev) +{ + struct swnode *swnode; + + swnode = dev_to_swnode(dev); + if (!swnode) + return; + + sysfs_remove_link(&swnode->kobj, dev_name(dev)); + sysfs_remove_link(&dev->kobj, "software_node"); + kobject_put(&swnode->kobj); + + if (swnode->managed) { + set_secondary_fwnode(dev, NULL); + kobject_put(&swnode->kobj); + } } static int __init software_node_init(void) diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 4d254fcc93d1..43c0940643f5 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -21,25 +21,27 @@ static ssize_t name##_show(struct device *dev, \ return sysfs_emit(buf, "%d\n", topology_##name(dev->id)); \ } -#define define_siblings_show_map(name, mask) \ -static ssize_t name##_show(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - return cpumap_print_to_pagebuf(false, buf, topology_##mask(dev->id));\ +#define define_siblings_read_func(name, mask) \ +static ssize_t name##_read(struct file *file, struct kobject *kobj, \ + struct bin_attribute *attr, char *buf, \ + loff_t off, size_t count) \ +{ \ + struct device *dev = kobj_to_dev(kobj); \ + \ + return cpumap_print_bitmask_to_buf(buf, topology_##mask(dev->id), \ + off, count); \ +} \ + \ +static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \ + struct bin_attribute *attr, char *buf, \ + loff_t off, size_t count) \ +{ \ + struct device *dev = kobj_to_dev(kobj); \ + \ + return cpumap_print_list_to_buf(buf, topology_##mask(dev->id), \ + off, count); \ } -#define define_siblings_show_list(name, mask) \ -static ssize_t name##_list_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - return cpumap_print_to_pagebuf(true, buf, topology_##mask(dev->id));\ -} - -#define define_siblings_show_func(name, mask) \ - define_siblings_show_map(name, mask); \ - define_siblings_show_list(name, mask) - define_id_show_func(physical_package_id); static DEVICE_ATTR_RO(physical_package_id); @@ -49,71 +51,80 @@ static DEVICE_ATTR_RO(die_id); define_id_show_func(core_id); static DEVICE_ATTR_RO(core_id); -define_siblings_show_func(thread_siblings, sibling_cpumask); -static DEVICE_ATTR_RO(thread_siblings); -static DEVICE_ATTR_RO(thread_siblings_list); +define_siblings_read_func(thread_siblings, sibling_cpumask); +static BIN_ATTR_RO(thread_siblings, 0); +static BIN_ATTR_RO(thread_siblings_list, 0); -define_siblings_show_func(core_cpus, sibling_cpumask); -static DEVICE_ATTR_RO(core_cpus); -static DEVICE_ATTR_RO(core_cpus_list); +define_siblings_read_func(core_cpus, sibling_cpumask); +static BIN_ATTR_RO(core_cpus, 0); +static BIN_ATTR_RO(core_cpus_list, 0); -define_siblings_show_func(core_siblings, core_cpumask); -static DEVICE_ATTR_RO(core_siblings); -static DEVICE_ATTR_RO(core_siblings_list); +define_siblings_read_func(core_siblings, core_cpumask); +static BIN_ATTR_RO(core_siblings, 0); +static BIN_ATTR_RO(core_siblings_list, 0); -define_siblings_show_func(die_cpus, die_cpumask); -static DEVICE_ATTR_RO(die_cpus); -static DEVICE_ATTR_RO(die_cpus_list); +define_siblings_read_func(die_cpus, die_cpumask); +static BIN_ATTR_RO(die_cpus, 0); +static BIN_ATTR_RO(die_cpus_list, 0); -define_siblings_show_func(package_cpus, core_cpumask); -static DEVICE_ATTR_RO(package_cpus); -static DEVICE_ATTR_RO(package_cpus_list); +define_siblings_read_func(package_cpus, core_cpumask); +static BIN_ATTR_RO(package_cpus, 0); +static BIN_ATTR_RO(package_cpus_list, 0); #ifdef CONFIG_SCHED_BOOK define_id_show_func(book_id); static DEVICE_ATTR_RO(book_id); -define_siblings_show_func(book_siblings, book_cpumask); -static DEVICE_ATTR_RO(book_siblings); -static DEVICE_ATTR_RO(book_siblings_list); +define_siblings_read_func(book_siblings, book_cpumask); +static BIN_ATTR_RO(book_siblings, 0); +static BIN_ATTR_RO(book_siblings_list, 0); #endif #ifdef CONFIG_SCHED_DRAWER define_id_show_func(drawer_id); static DEVICE_ATTR_RO(drawer_id); -define_siblings_show_func(drawer_siblings, drawer_cpumask); -static DEVICE_ATTR_RO(drawer_siblings); -static DEVICE_ATTR_RO(drawer_siblings_list); +define_siblings_read_func(drawer_siblings, drawer_cpumask); +static BIN_ATTR_RO(drawer_siblings, 0); +static BIN_ATTR_RO(drawer_siblings_list, 0); #endif +static struct bin_attribute *bin_attrs[] = { + &bin_attr_core_cpus, + &bin_attr_core_cpus_list, + &bin_attr_thread_siblings, + &bin_attr_thread_siblings_list, + &bin_attr_core_siblings, + &bin_attr_core_siblings_list, + &bin_attr_die_cpus, + &bin_attr_die_cpus_list, + &bin_attr_package_cpus, + &bin_attr_package_cpus_list, +#ifdef CONFIG_SCHED_BOOK + &bin_attr_book_siblings, + &bin_attr_book_siblings_list, +#endif +#ifdef CONFIG_SCHED_DRAWER + &bin_attr_drawer_siblings, + &bin_attr_drawer_siblings_list, +#endif + NULL +}; + static struct attribute *default_attrs[] = { &dev_attr_physical_package_id.attr, &dev_attr_die_id.attr, &dev_attr_core_id.attr, - &dev_attr_thread_siblings.attr, - &dev_attr_thread_siblings_list.attr, - &dev_attr_core_cpus.attr, - &dev_attr_core_cpus_list.attr, - &dev_attr_core_siblings.attr, - &dev_attr_core_siblings_list.attr, - &dev_attr_die_cpus.attr, - &dev_attr_die_cpus_list.attr, - &dev_attr_package_cpus.attr, - &dev_attr_package_cpus_list.attr, #ifdef CONFIG_SCHED_BOOK &dev_attr_book_id.attr, - &dev_attr_book_siblings.attr, - &dev_attr_book_siblings_list.attr, #endif #ifdef CONFIG_SCHED_DRAWER &dev_attr_drawer_id.attr, - &dev_attr_drawer_siblings.attr, - &dev_attr_drawer_siblings_list.attr, #endif NULL }; static const struct attribute_group topology_attr_group = { .attrs = default_attrs, + .bin_attrs = bin_attrs, .name = "topology" }; |