diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-04 21:50:37 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-04 21:50:37 -0800 |
commit | e880e87488d5bbf630dd716e6de8a53585614568 (patch) | |
tree | cab1f22bdd3adb3141df135f98dcabecabc181b1 /drivers/base | |
parent | 118c216e16c5ccb028cd03a0dcd56d17a07ff8d7 (diff) | |
parent | c23fe83138ed7b11ad763cbe8bf98e5378c04bd6 (diff) | |
download | linux-e880e87488d5bbf630dd716e6de8a53585614568.tar.bz2 |
Merge tag 'driver-core-4.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core updates from Greg KH:
"Here's the "big" driver core updates for 4.4-rc1. Primarily a bunch
of debugfs updates, with a smattering of minor driver core fixes and
updates as well.
All have been in linux-next for a long time"
* tag 'driver-core-4.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
debugfs: Add debugfs_create_ulong()
of: to support binding numa node to specified device in devicetree
debugfs: Add read-only/write-only bool file ops
debugfs: Add read-only/write-only size_t file ops
debugfs: Add read-only/write-only x64 file ops
debugfs: Consolidate file mode checks in debugfs_create_*()
Revert "mm: Check if section present during memory block (un)registering"
driver-core: platform: Provide helpers for multi-driver modules
mm: Check if section present during memory block (un)registering
devres: fix a for loop bounds check
CMA: fix CONFIG_CMA_SIZE_MBYTES overflow in 64bit
base/platform: assert that dev_pm_domain callbacks are called unconditionally
sysfs: correctly handle short reads on PREALLOC attrs.
base: soc: siplify ida usage
kobject: move EXPORT_SYMBOL() macros next to corresponding definitions
kobject: explain what kobject's sd field is
debugfs: document that debugfs_remove*() accepts NULL and error values
debugfs: Pass bool pointer to debugfs_create_bool()
ACPI / EC: Fix broken 64bit big-endian users of 'global_lock'
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/core.c | 2 | ||||
-rw-r--r-- | drivers/base/dma-contiguous.c | 2 | ||||
-rw-r--r-- | drivers/base/platform.c | 80 | ||||
-rw-r--r-- | drivers/base/regmap/internal.h | 6 | ||||
-rw-r--r-- | drivers/base/regmap/regcache-lzo.c | 4 | ||||
-rw-r--r-- | drivers/base/regmap/regcache.c | 24 | ||||
-rw-r--r-- | drivers/base/soc.c | 21 |
7 files changed, 94 insertions, 45 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 334ec7ef1960..b7d56c5ea3c6 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1066,7 +1066,7 @@ int device_add(struct device *dev) dev->kobj.parent = kobj; /* use parent numa_node */ - if (parent) + if (parent && (dev_to_node(dev) == NUMA_NO_NODE)) set_dev_node(dev, dev_to_node(parent)); /* first, register with generic layer. */ diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index a12ff9863d7e..e167a1e1bccb 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -46,7 +46,7 @@ struct cma *dma_contiguous_default_area; * Users, who want to set the size of global CMA area for their system * should use cma= kernel parameter. */ -static const phys_addr_t size_bytes = CMA_SIZE_MBYTES * SZ_1M; +static const phys_addr_t size_bytes = (phys_addr_t)CMA_SIZE_MBYTES * SZ_1M; static phys_addr_t size_cmdline = -1; static phys_addr_t base_cmdline; static phys_addr_t limit_cmdline; diff --git a/drivers/base/platform.c b/drivers/base/platform.c index f80aaaf9f610..1dd6d3bf1098 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -513,7 +513,7 @@ static int platform_drv_probe(struct device *_dev) return ret; ret = dev_pm_domain_attach(_dev, true); - if (ret != -EPROBE_DEFER) { + if (ret != -EPROBE_DEFER && drv->probe) { ret = drv->probe(dev); if (ret) dev_pm_domain_detach(_dev, true); @@ -536,9 +536,10 @@ static int platform_drv_remove(struct device *_dev) { struct platform_driver *drv = to_platform_driver(_dev->driver); struct platform_device *dev = to_platform_device(_dev); - int ret; + int ret = 0; - ret = drv->remove(dev); + if (drv->remove) + ret = drv->remove(dev); dev_pm_domain_detach(_dev, true); return ret; @@ -549,7 +550,8 @@ static void platform_drv_shutdown(struct device *_dev) struct platform_driver *drv = to_platform_driver(_dev->driver); struct platform_device *dev = to_platform_device(_dev); - drv->shutdown(dev); + if (drv->shutdown) + drv->shutdown(dev); dev_pm_domain_detach(_dev, true); } @@ -563,12 +565,9 @@ int __platform_driver_register(struct platform_driver *drv, { drv->driver.owner = owner; drv->driver.bus = &platform_bus_type; - if (drv->probe) - drv->driver.probe = platform_drv_probe; - if (drv->remove) - drv->driver.remove = platform_drv_remove; - if (drv->shutdown) - drv->driver.shutdown = platform_drv_shutdown; + drv->driver.probe = platform_drv_probe; + drv->driver.remove = platform_drv_remove; + drv->driver.shutdown = platform_drv_shutdown; return driver_register(&drv->driver); } @@ -711,6 +710,67 @@ err_out: } EXPORT_SYMBOL_GPL(__platform_create_bundle); +/** + * __platform_register_drivers - register an array of platform drivers + * @drivers: an array of drivers to register + * @count: the number of drivers to register + * @owner: module owning the drivers + * + * Registers platform drivers specified by an array. On failure to register a + * driver, all previously registered drivers will be unregistered. Callers of + * this API should use platform_unregister_drivers() to unregister drivers in + * the reverse order. + * + * Returns: 0 on success or a negative error code on failure. + */ +int __platform_register_drivers(struct platform_driver * const *drivers, + unsigned int count, struct module *owner) +{ + unsigned int i; + int err; + + for (i = 0; i < count; i++) { + pr_debug("registering platform driver %ps\n", drivers[i]); + + err = __platform_driver_register(drivers[i], owner); + if (err < 0) { + pr_err("failed to register platform driver %ps: %d\n", + drivers[i], err); + goto error; + } + } + + return 0; + +error: + while (i--) { + pr_debug("unregistering platform driver %ps\n", drivers[i]); + platform_driver_unregister(drivers[i]); + } + + return err; +} +EXPORT_SYMBOL_GPL(__platform_register_drivers); + +/** + * platform_unregister_drivers - unregister an array of platform drivers + * @drivers: an array of drivers to unregister + * @count: the number of drivers to unregister + * + * Unegisters platform drivers specified by an array. This is typically used + * to complement an earlier call to platform_register_drivers(). Drivers are + * unregistered in the reverse order in which they were registered. + */ +void platform_unregister_drivers(struct platform_driver * const *drivers, + unsigned int count) +{ + while (count--) { + pr_debug("unregistering platform driver %ps\n", drivers[count]); + platform_driver_unregister(drivers[count]); + } +} +EXPORT_SYMBOL_GPL(platform_unregister_drivers); + /* modalias support enables more hands-off userspace setup: * (a) environment variable lets new-style hotplug events work once system is * fully running: "modprobe $MODALIAS" diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 3250e53473a3..3df977054781 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -125,9 +125,9 @@ struct regmap { unsigned int num_reg_defaults_raw; /* if set, only the cache is modified not the HW */ - u32 cache_only; + bool cache_only; /* if set, only the HW is modified not the cache */ - u32 cache_bypass; + bool cache_bypass; /* if set, remember to free reg_defaults_raw */ bool cache_free; @@ -135,7 +135,7 @@ struct regmap { const void *reg_defaults_raw; void *cache; /* if set, the cache contains newer data than the HW */ - u32 cache_dirty; + bool cache_dirty; /* if set, the HW registers are known to match map->reg_defaults */ bool no_sync_defaults; diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c index 2d53f6f138e1..736e0d378567 100644 --- a/drivers/base/regmap/regcache-lzo.c +++ b/drivers/base/regmap/regcache-lzo.c @@ -355,9 +355,9 @@ static int regcache_lzo_sync(struct regmap *map, unsigned int min, if (ret > 0 && val == map->reg_defaults[ret].def) continue; - map->cache_bypass = 1; + map->cache_bypass = true; ret = _regmap_write(map, i, val); - map->cache_bypass = 0; + map->cache_bypass = false; if (ret) return ret; dev_dbg(map->dev, "Synced register %#x, value %#x\n", diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 6f8a13ec32a4..4c07802986b2 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -54,11 +54,11 @@ static int regcache_hw_init(struct regmap *map) return -ENOMEM; if (!map->reg_defaults_raw) { - u32 cache_bypass = map->cache_bypass; + bool cache_bypass = map->cache_bypass; dev_warn(map->dev, "No cache defaults, reading back from HW\n"); /* Bypass the cache access till data read from HW*/ - map->cache_bypass = 1; + map->cache_bypass = true; tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL); if (!tmp_buf) { ret = -ENOMEM; @@ -285,9 +285,9 @@ static int regcache_default_sync(struct regmap *map, unsigned int min, if (!regcache_reg_needs_sync(map, reg, val)) continue; - map->cache_bypass = 1; + map->cache_bypass = true; ret = _regmap_write(map, reg, val); - map->cache_bypass = 0; + map->cache_bypass = false; if (ret) { dev_err(map->dev, "Unable to sync register %#x. %d\n", reg, ret); @@ -315,7 +315,7 @@ int regcache_sync(struct regmap *map) int ret = 0; unsigned int i; const char *name; - unsigned int bypass; + bool bypass; BUG_ON(!map->cache_ops); @@ -333,7 +333,7 @@ int regcache_sync(struct regmap *map) map->async = true; /* Apply any patch first */ - map->cache_bypass = 1; + map->cache_bypass = true; for (i = 0; i < map->patch_regs; i++) { ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def); if (ret != 0) { @@ -342,7 +342,7 @@ int regcache_sync(struct regmap *map) goto out; } } - map->cache_bypass = 0; + map->cache_bypass = false; if (map->cache_ops->sync) ret = map->cache_ops->sync(map, 0, map->max_register); @@ -384,7 +384,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min, { int ret = 0; const char *name; - unsigned int bypass; + bool bypass; BUG_ON(!map->cache_ops); @@ -637,11 +637,11 @@ static int regcache_sync_block_single(struct regmap *map, void *block, if (!regcache_reg_needs_sync(map, regtmp, val)) continue; - map->cache_bypass = 1; + map->cache_bypass = true; ret = _regmap_write(map, regtmp, val); - map->cache_bypass = 0; + map->cache_bypass = false; if (ret != 0) { dev_err(map->dev, "Unable to sync register %#x. %d\n", regtmp, ret); @@ -668,14 +668,14 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data, dev_dbg(map->dev, "Writing %zu bytes for %d registers from 0x%x-0x%x\n", count * val_bytes, count, base, cur - map->reg_stride); - map->cache_bypass = 1; + map->cache_bypass = true; ret = _regmap_raw_write(map, base, *data, count * val_bytes); if (ret) dev_err(map->dev, "Unable to sync registers %#x-%#x. %d\n", base, cur - map->reg_stride, ret); - map->cache_bypass = 0; + map->cache_bypass = false; *data = NULL; diff --git a/drivers/base/soc.c b/drivers/base/soc.c index 39fca01c8fa1..75b98aad6faf 100644 --- a/drivers/base/soc.c +++ b/drivers/base/soc.c @@ -16,7 +16,6 @@ #include <linux/err.h> static DEFINE_IDA(soc_ida); -static DEFINE_SPINLOCK(soc_lock); static ssize_t soc_info_get(struct device *dev, struct device_attribute *attr, @@ -122,20 +121,10 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr } /* Fetch a unique (reclaimable) SOC ID. */ - do { - if (!ida_pre_get(&soc_ida, GFP_KERNEL)) { - ret = -ENOMEM; - goto out2; - } - - spin_lock(&soc_lock); - ret = ida_get_new(&soc_ida, &soc_dev->soc_dev_num); - spin_unlock(&soc_lock); - - } while (ret == -EAGAIN); - - if (ret) + ret = ida_simple_get(&soc_ida, 0, 0, GFP_KERNEL); + if (ret < 0) goto out2; + soc_dev->soc_dev_num = ret; soc_dev->attr = soc_dev_attr; soc_dev->dev.bus = &soc_bus_type; @@ -151,7 +140,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr return soc_dev; out3: - ida_remove(&soc_ida, soc_dev->soc_dev_num); + ida_simple_remove(&soc_ida, soc_dev->soc_dev_num); out2: kfree(soc_dev); out1: @@ -161,7 +150,7 @@ out1: /* Ensure soc_dev->attr is freed prior to calling soc_device_unregister. */ void soc_device_unregister(struct soc_device *soc_dev) { - ida_remove(&soc_ida, soc_dev->soc_dev_num); + ida_simple_remove(&soc_ida, soc_dev->soc_dev_num); device_unregister(&soc_dev->dev); } |