From 621a5f7ad9cd1ce7933f1d302067cbd58354173c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 26 Sep 2015 15:04:07 -0700 Subject: debugfs: Pass bool pointer to debugfs_create_bool() Its a bit odd that debugfs_create_bool() takes 'u32 *' as an argument, when all it needs is a boolean pointer. It would be better to update this API to make it accept 'bool *' instead, as that will make it more consistent and often more convenient. Over that bool takes just a byte. That required updates to all user sites as well, in the same commit updating the API. regmap core was also using debugfs_{read|write}_file_bool(), directly and variable types were updated for that to be bool as well. Signed-off-by: Viresh Kumar Acked-by: Mark Brown Acked-by: Charles Keepax Signed-off-by: Greg Kroah-Hartman --- drivers/base/regmap/internal.h | 6 +++--- drivers/base/regmap/regcache-lzo.c | 4 ++-- drivers/base/regmap/regcache.c | 24 ++++++++++++------------ 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index cc557886ab23..5b907f2c62b9 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -122,9 +122,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; @@ -132,7 +132,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; -- cgit v1.2.3 From cfcf6a91aa0d59faddb423a65230eea7f230d057 Mon Sep 17 00:00:00 2001 From: Lee Duncan Date: Thu, 1 Oct 2015 11:59:09 -0700 Subject: base: soc: siplify ida usage Simplify ida index allocation and removal by using the ida_simple_* helper functions Signed-off-by: Lee Duncan Reviewed-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- drivers/base/soc.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'drivers/base') 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 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); } -- cgit v1.2.3 From b8b2c7d845d57f7a4b9f1f941f24728165e27626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 7 Aug 2015 07:19:22 +0200 Subject: base/platform: assert that dev_pm_domain callbacks are called unconditionally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a platform driver doesn't provide a .remove callback the function platform_drv_remove isn't called and so the call to dev_pm_domain_attach called at probe time isn't paired by dev_pm_domain_detach at remove time. To fix this (and similar issues if different callbacks are missing) hook up the driver callbacks unconditionally and make them aware that the platform callbacks might be missing. Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index f80aaaf9f610..07cec9ba5e70 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); } -- cgit v1.2.3 From a785ce9c90bc7d73b5cae4388641b310948509cb Mon Sep 17 00:00:00 2001 From: Tan Xiaojun Date: Thu, 24 Sep 2015 11:27:47 +0800 Subject: CMA: fix CONFIG_CMA_SIZE_MBYTES overflow in 64bit In 64bit system, if you set CONFIG_CMA_SIZE_MBYTES>=2048, it will overflow and size_bytes will be a big wrong number. Set CONFIG_CMA_SIZE_MBYTES=2048 and you will get an info below during system boot: ********* cma: Failed to reserve 17592186042368 MiB ********* Signed-off-by: Tan Xiaojun Signed-off-by: Greg Kroah-Hartman --- drivers/base/dma-contiguous.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 950fff9ce453..426ba2772fe6 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; -- cgit v1.2.3 From 7568fb63f57ac8672f8bf2018171255441238882 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 25 Aug 2015 22:12:37 -0700 Subject: mm: Check if section present during memory block (un)registering Tony found on his setup, if memory block size 512M will cause crash during booting. BUG: unable to handle kernel paging request at ffffea0074000020 IP: [] get_nid_for_pfn+0x17/0x40 PGD 128ffcb067 PUD 128ffc9067 PMD 0 Oops: 0000 [#1] SMP Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.2.0-rc8 #1 ... Call Trace: [] ? register_mem_sect_under_node+0x66/0xe0 [] register_one_node+0x17b/0x240 [] ? pci_iommu_alloc+0x6e/0x6e [] topology_init+0x3c/0x95 [] do_one_initcall+0xcd/0x1f0 The system has non continuous RAM address: BIOS-e820: [mem 0x0000001300000000-0x0000001cffffffff] usable BIOS-e820: [mem 0x0000001d70000000-0x0000001ec7ffefff] usable BIOS-e820: [mem 0x0000001f00000000-0x0000002bffffffff] usable BIOS-e820: [mem 0x0000002c18000000-0x0000002d6fffefff] usable BIOS-e820: [mem 0x0000002e00000000-0x00000039ffffffff] usable So there are start sections in memory block not present. For example: memory block : [0x2c18000000, 0x2c20000000) 512M first three sections are not present. Current register_mem_sect_under_node() assume first section is present, but memory block section number range [start_section_nr, end_section_nr] would include not present section. For arch that support vmemmap, we don't setup memmap for struct page area within not present sections area. So skip the pfn range that belong to absent section. Also fixes unregister_mem_sect_under_nodes() that assume one section per memory block. Reported-by: Tony Luck Tested-by: Tony Luck Fixes: bdee237c0343 ("x86: mm: Use 2GB memory block size on large memory x86-64 systems") Fixes: 982792c782ef ("x86, mm: probe memory block size for generic x86 64bit") Signed-off-by: Yinghai Lu Cc: stable@vger.kernel.org #v3.15 Signed-off-by: Greg Kroah-Hartman --- drivers/base/node.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/node.c b/drivers/base/node.c index 560751bad294..ae98ebaf6313 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -390,7 +390,18 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) sect_end_pfn = section_nr_to_pfn(mem_blk->end_section_nr); sect_end_pfn += PAGES_PER_SECTION - 1; for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { - int page_nid; + int page_nid, scn_nr; + + /* + * memory block could have several absent sections from start. + * skip pfn range from absent section + */ + scn_nr = pfn_to_section_nr(pfn); + if (!present_section_nr(scn_nr)) { + pfn = round_down(pfn + PAGES_PER_SECTION, + PAGES_PER_SECTION) - 1; + continue; + } /* * memory block could have several absent sections from start. @@ -436,10 +447,22 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk, return -ENOMEM; nodes_clear(*unlinked_nodes); - sect_start_pfn = section_nr_to_pfn(phys_index); - sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; + sect_start_pfn = section_nr_to_pfn(mem_blk->start_section_nr); + sect_end_pfn = section_nr_to_pfn(mem_blk->end_section_nr); + sect_end_pfn += PAGES_PER_SECTION - 1; for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { - int nid; + int nid, scn_nr; + + /* + * memory block could have several absent sections from start. + * skip pfn range from absent section + */ + scn_nr = pfn_to_section_nr(pfn); + if (!present_section_nr(scn_nr)) { + pfn = round_down(pfn + PAGES_PER_SECTION, + PAGES_PER_SECTION) - 1; + continue; + } nid = get_nid_for_pfn(pfn); if (nid < 0) -- cgit v1.2.3 From dbe2256ddd8e8420c254c79f4045c41cb5f4bd6b Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 25 Sep 2015 17:29:04 +0200 Subject: driver-core: platform: Provide helpers for multi-driver modules Some modules register several sub-drivers. Provide a helper that makes it easy to register and unregister a list of sub-drivers, as well as unwind properly on error. Signed-off-by: Thierry Reding Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 07cec9ba5e70..1dd6d3bf1098 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -710,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" -- cgit v1.2.3 From 8346aa765e14348b7b436825b3c4740895a2fe1a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 13 Oct 2015 10:57:25 -0700 Subject: Revert "mm: Check if section present during memory block (un)registering" This reverts commit 7568fb63f57ac8672f8bf2018171255441238882 as it's already in Linus's tree through a different patch. Reported-by: Tony Luck Cc: Yinghai Lu Cc: stable@vger.kernel.org #v3.15 Signed-off-by: Greg Kroah-Hartman --- drivers/base/node.c | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/node.c b/drivers/base/node.c index ae98ebaf6313..560751bad294 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -390,18 +390,7 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) sect_end_pfn = section_nr_to_pfn(mem_blk->end_section_nr); sect_end_pfn += PAGES_PER_SECTION - 1; for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { - int page_nid, scn_nr; - - /* - * memory block could have several absent sections from start. - * skip pfn range from absent section - */ - scn_nr = pfn_to_section_nr(pfn); - if (!present_section_nr(scn_nr)) { - pfn = round_down(pfn + PAGES_PER_SECTION, - PAGES_PER_SECTION) - 1; - continue; - } + int page_nid; /* * memory block could have several absent sections from start. @@ -447,22 +436,10 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk, return -ENOMEM; nodes_clear(*unlinked_nodes); - sect_start_pfn = section_nr_to_pfn(mem_blk->start_section_nr); - sect_end_pfn = section_nr_to_pfn(mem_blk->end_section_nr); - sect_end_pfn += PAGES_PER_SECTION - 1; + sect_start_pfn = section_nr_to_pfn(phys_index); + sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { - int nid, scn_nr; - - /* - * memory block could have several absent sections from start. - * skip pfn range from absent section - */ - scn_nr = pfn_to_section_nr(pfn); - if (!present_section_nr(scn_nr)) { - pfn = round_down(pfn + PAGES_PER_SECTION, - PAGES_PER_SECTION) - 1; - continue; - } + int nid; nid = get_nid_for_pfn(pfn); if (nid < 0) -- cgit v1.2.3 From 56f2de81e020c537f7e35550d13840143cb765cd Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Tue, 25 Aug 2015 12:08:22 +0800 Subject: of: to support binding numa node to specified device in devicetree For now, in function device_add, the new device will be forced to inherit the numa node of its parent. But this will override the device's numa node which configured in devicetree. Signed-off-by: Zhen Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') 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. */ -- cgit v1.2.3