diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-14 16:10:09 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-14 16:10:09 -0800 |
commit | e6b5be2be4e30037eb551e0ed09dd97bd00d85d3 (patch) | |
tree | 88801365987a0dc64d62d47e8a11f3b44691c37f /include/linux | |
parent | 37da7bbbe84fe9e8862940d3f9194fd27dce59bb (diff) | |
parent | f1c488a78d9f1a22cdb15648c15e70fd82ed229a (diff) | |
download | lwn-e6b5be2be4e30037eb551e0ed09dd97bd00d85d3.tar.gz lwn-e6b5be2be4e30037eb551e0ed09dd97bd00d85d3.zip |
Merge tag 'driver-core-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core update from Greg KH:
"Here's the set of driver core patches for 3.19-rc1.
They are dominated by the removal of the .owner field in platform
drivers. They touch a lot of files, but they are "simple" changes,
just removing a line in a structure.
Other than that, a few minor driver core and debugfs changes. There
are some ath9k patches coming in through this tree that have been
acked by the wireless maintainers as they relied on the debugfs
changes.
Everything has been in linux-next for a while"
* tag 'driver-core-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (324 commits)
Revert "ath: ath9k: use debugfs_create_devm_seqfile() helper for seq_file entries"
fs: debugfs: add forward declaration for struct device type
firmware class: Deletion of an unnecessary check before the function call "vunmap"
firmware loader: fix hung task warning dump
devcoredump: provide a one-way disable function
device: Add dev_<level>_once variants
ath: ath9k: use debugfs_create_devm_seqfile() helper for seq_file entries
ath: use seq_file api for ath9k debugfs files
debugfs: add helper function to create device related seq_file
drivers/base: cacheinfo: remove noisy error boot message
Revert "core: platform: add warning if driver has no owner"
drivers: base: support cpu cache information interface to userspace via sysfs
drivers: base: add cpu_device_create to support per-cpu devices
topology: replace custom attribute macros with standard DEVICE_ATTR*
cpumask: factor out show_cpumap into separate helper function
driver core: Fix unbalanced device reference in drivers_probe
driver core: fix race with userland in device_add()
sysfs/kernfs: make read requests on pre-alloc files use the buffer.
sysfs/kernfs: allow attributes to request write buffer be pre-allocated.
fs: sysfs: return EGBIG on write if offset is larger than file size
...
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/bitmap.h | 3 | ||||
-rw-r--r-- | include/linux/cacheinfo.h | 100 | ||||
-rw-r--r-- | include/linux/cpu.h | 4 | ||||
-rw-r--r-- | include/linux/cpumask.h | 17 | ||||
-rw-r--r-- | include/linux/debugfs.h | 17 | ||||
-rw-r--r-- | include/linux/device.h | 35 | ||||
-rw-r--r-- | include/linux/kernfs.h | 8 | ||||
-rw-r--r-- | include/linux/platform_device.h | 12 | ||||
-rw-r--r-- | include/linux/sysfs.h | 9 |
9 files changed, 200 insertions, 5 deletions
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 34e020c23644..202e4034fe26 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -61,6 +61,7 @@ * bitmap_find_free_region(bitmap, bits, order) Find and allocate bit region * bitmap_release_region(bitmap, pos, order) Free specified bit region * bitmap_allocate_region(bitmap, pos, order) Allocate specified bit region + * bitmap_print_to_pagebuf(list, buf, mask, nbits) Print bitmap src as list/hex */ /* @@ -171,6 +172,8 @@ extern void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int o extern int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order); extern void bitmap_copy_le(void *dst, const unsigned long *src, int nbits); extern int bitmap_ord_to_pos(const unsigned long *bitmap, int n, int bits); +extern int bitmap_print_to_pagebuf(bool list, char *buf, + const unsigned long *maskp, int nmaskbits); #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) #define BITMAP_LAST_WORD_MASK(nbits) \ diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h new file mode 100644 index 000000000000..3daf5ed392c9 --- /dev/null +++ b/include/linux/cacheinfo.h @@ -0,0 +1,100 @@ +#ifndef _LINUX_CACHEINFO_H +#define _LINUX_CACHEINFO_H + +#include <linux/bitops.h> +#include <linux/cpumask.h> +#include <linux/smp.h> + +struct device_node; +struct attribute; + +enum cache_type { + CACHE_TYPE_NOCACHE = 0, + CACHE_TYPE_INST = BIT(0), + CACHE_TYPE_DATA = BIT(1), + CACHE_TYPE_SEPARATE = CACHE_TYPE_INST | CACHE_TYPE_DATA, + CACHE_TYPE_UNIFIED = BIT(2), +}; + +/** + * struct cacheinfo - represent a cache leaf node + * @type: type of the cache - data, inst or unified + * @level: represents the hierarcy in the multi-level cache + * @coherency_line_size: size of each cache line usually representing + * the minimum amount of data that gets transferred from memory + * @number_of_sets: total number of sets, a set is a collection of cache + * lines sharing the same index + * @ways_of_associativity: number of ways in which a particular memory + * block can be placed in the cache + * @physical_line_partition: number of physical cache lines sharing the + * same cachetag + * @size: Total size of the cache + * @shared_cpu_map: logical cpumask representing all the cpus sharing + * this cache node + * @attributes: bitfield representing various cache attributes + * @of_node: if devicetree is used, this represents either the cpu node in + * case there's no explicit cache node or the cache node itself in the + * device tree + * @disable_sysfs: indicates whether this node is visible to the user via + * sysfs or not + * @priv: pointer to any private data structure specific to particular + * cache design + * + * While @of_node, @disable_sysfs and @priv are used for internal book + * keeping, the remaining members form the core properties of the cache + */ +struct cacheinfo { + enum cache_type type; + unsigned int level; + unsigned int coherency_line_size; + unsigned int number_of_sets; + unsigned int ways_of_associativity; + unsigned int physical_line_partition; + unsigned int size; + cpumask_t shared_cpu_map; + unsigned int attributes; +#define CACHE_WRITE_THROUGH BIT(0) +#define CACHE_WRITE_BACK BIT(1) +#define CACHE_WRITE_POLICY_MASK \ + (CACHE_WRITE_THROUGH | CACHE_WRITE_BACK) +#define CACHE_READ_ALLOCATE BIT(2) +#define CACHE_WRITE_ALLOCATE BIT(3) +#define CACHE_ALLOCATE_POLICY_MASK \ + (CACHE_READ_ALLOCATE | CACHE_WRITE_ALLOCATE) + + struct device_node *of_node; + bool disable_sysfs; + void *priv; +}; + +struct cpu_cacheinfo { + struct cacheinfo *info_list; + unsigned int num_levels; + unsigned int num_leaves; +}; + +/* + * Helpers to make sure "func" is executed on the cpu whose cache + * attributes are being detected + */ +#define DEFINE_SMP_CALL_CACHE_FUNCTION(func) \ +static inline void _##func(void *ret) \ +{ \ + int cpu = smp_processor_id(); \ + *(int *)ret = __##func(cpu); \ +} \ + \ +int func(unsigned int cpu) \ +{ \ + int ret; \ + smp_call_function_single(cpu, _##func, &ret, true); \ + return ret; \ +} + +struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu); +int init_cache_level(unsigned int cpu); +int populate_cache_leaves(unsigned int cpu); + +const struct attribute_group *cache_get_priv_group(struct cacheinfo *this_leaf); + +#endif /* _LINUX_CACHEINFO_H */ diff --git a/include/linux/cpu.h b/include/linux/cpu.h index b2d9a43012b2..4260e8594bd7 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -19,6 +19,7 @@ struct device; struct device_node; +struct attribute_group; struct cpu { int node_id; /* The node which contains the CPU */ @@ -39,6 +40,9 @@ extern void cpu_remove_dev_attr(struct device_attribute *attr); extern int cpu_add_dev_attr_group(struct attribute_group *attrs); extern void cpu_remove_dev_attr_group(struct attribute_group *attrs); +extern struct device *cpu_device_create(struct device *parent, void *drvdata, + const struct attribute_group **groups, + const char *fmt, ...); #ifdef CONFIG_HOTPLUG_CPU extern void unregister_cpu(struct cpu *cpu); extern ssize_t arch_cpu_probe(const char *, size_t); diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 0a9a6da21e74..b950e9d6008b 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -803,6 +803,23 @@ static inline const struct cpumask *get_cpu_mask(unsigned int cpu) } #endif /* NR_CPUS > BITS_PER_LONG */ +/** + * cpumap_print_to_pagebuf - copies the cpumask into the buffer either + * as comma-separated list of cpus or hex values of cpumask + * @list: indicates whether the cpumap must be list + * @mask: the cpumask to copy + * @buf: the buffer to copy into + * + * Returns the length of the (null-terminated) @buf string, zero if + * nothing is copied. + */ +static inline ssize_t +cpumap_print_to_pagebuf(bool list, char *buf, const struct cpumask *mask) +{ + return bitmap_print_to_pagebuf(list, buf, cpumask_bits(mask), + nr_cpumask_bits); +} + /* * * From here down, all obsolete. Use cpumask_ variants! diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index d84f8c254a87..da4c4983adbe 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -20,6 +20,7 @@ #include <linux/types.h> +struct device; struct file_operations; struct debugfs_blob_wrapper { @@ -99,13 +100,18 @@ struct dentry *debugfs_create_u32_array(const char *name, umode_t mode, struct dentry *parent, u32 *array, u32 elements); +struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name, + struct dentry *parent, + int (*read_fn)(struct seq_file *s, + void *data)); + bool debugfs_initialized(void); #else #include <linux/err.h> -/* +/* * We do not return NULL from these functions if CONFIG_DEBUG_FS is not enabled * so users have a chance to detect if there was a real error or not. We don't * want to duplicate the design decision mistakes of procfs and devfs again. @@ -250,6 +256,15 @@ static inline struct dentry *debugfs_create_u32_array(const char *name, umode_t return ERR_PTR(-ENODEV); } +static inline struct dentry *debugfs_create_devm_seqfile(struct device *dev, + const char *name, + struct dentry *parent, + int (*read_fn)(struct seq_file *s, + void *data)) +{ + return ERR_PTR(-ENODEV); +} + #endif #endif diff --git a/include/linux/device.h b/include/linux/device.h index 41d6a7555c6b..fb506738f7b7 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -1123,6 +1123,41 @@ do { \ }) #endif +#ifdef CONFIG_PRINTK +#define dev_level_once(dev_level, dev, fmt, ...) \ +do { \ + static bool __print_once __read_mostly; \ + \ + if (!__print_once) { \ + __print_once = true; \ + dev_level(dev, fmt, ##__VA_ARGS__); \ + } \ +} while (0) +#else +#define dev_level_once(dev_level, dev, fmt, ...) \ +do { \ + if (0) \ + dev_level(dev, fmt, ##__VA_ARGS__); \ +} while (0) +#endif + +#define dev_emerg_once(dev, fmt, ...) \ + dev_level_once(dev_emerg, dev, fmt, ##__VA_ARGS__) +#define dev_alert_once(dev, fmt, ...) \ + dev_level_once(dev_alert, dev, fmt, ##__VA_ARGS__) +#define dev_crit_once(dev, fmt, ...) \ + dev_level_once(dev_crit, dev, fmt, ##__VA_ARGS__) +#define dev_err_once(dev, fmt, ...) \ + dev_level_once(dev_err, dev, fmt, ##__VA_ARGS__) +#define dev_warn_once(dev, fmt, ...) \ + dev_level_once(dev_warn, dev, fmt, ##__VA_ARGS__) +#define dev_notice_once(dev, fmt, ...) \ + dev_level_once(dev_notice, dev, fmt, ##__VA_ARGS__) +#define dev_info_once(dev, fmt, ...) \ + dev_level_once(dev_info, dev, fmt, ##__VA_ARGS__) +#define dev_dbg_once(dev, fmt, ...) \ + dev_level_once(dev_info, dev, fmt, ##__VA_ARGS__) + #define dev_level_ratelimited(dev_level, dev, fmt, ...) \ do { \ static DEFINE_RATELIMIT_STATE(_rs, \ diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index 30faf797c2c3..d4e01b358341 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h @@ -179,6 +179,7 @@ struct kernfs_open_file { struct mutex mutex; int event; struct list_head list; + char *prealloc_buf; size_t atomic_write_len; bool mmapped; @@ -214,6 +215,13 @@ struct kernfs_ops { * larger ones are rejected with -E2BIG. */ size_t atomic_write_len; + /* + * "prealloc" causes a buffer to be allocated at open for + * all read/write requests. As ->seq_show uses seq_read() + * which does its own allocation, it is incompatible with + * ->prealloc. Provide ->read and ->write with ->prealloc. + */ + bool prealloc; ssize_t (*write)(struct kernfs_open_file *of, char *buf, size_t bytes, loff_t off); diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 153d303af7eb..ae4882ca4a64 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -197,8 +197,10 @@ extern void platform_driver_unregister(struct platform_driver *); /* non-hotpluggable platform devices may use this so that probe() and * its support may live in __init sections, conserving runtime memory. */ -extern int platform_driver_probe(struct platform_driver *driver, - int (*probe)(struct platform_device *)); +#define platform_driver_probe(drv, probe) \ + __platform_driver_probe(drv, probe, THIS_MODULE) +extern int __platform_driver_probe(struct platform_driver *driver, + int (*probe)(struct platform_device *), struct module *module); static inline void *platform_get_drvdata(const struct platform_device *pdev) { @@ -238,10 +240,12 @@ static void __exit __platform_driver##_exit(void) \ } \ module_exit(__platform_driver##_exit); -extern struct platform_device *platform_create_bundle( +#define platform_create_bundle(driver, probe, res, n_res, data, size) \ + __platform_create_bundle(driver, probe, res, n_res, data, size, THIS_MODULE) +extern struct platform_device *__platform_create_bundle( struct platform_driver *driver, int (*probe)(struct platform_device *), struct resource *res, unsigned int n_res, - const void *data, size_t size); + const void *data, size_t size, struct module *module); /* early platform driver interface */ struct early_platform_driver { diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index f97d0dbb59fa..ddad16148bd6 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -70,6 +70,8 @@ struct attribute_group { * for examples.. */ +#define SYSFS_PREALLOC 010000 + #define __ATTR(_name, _mode, _show, _store) { \ .attr = {.name = __stringify(_name), \ .mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, \ @@ -77,6 +79,13 @@ struct attribute_group { .store = _store, \ } +#define __ATTR_PREALLOC(_name, _mode, _show, _store) { \ + .attr = {.name = __stringify(_name), \ + .mode = SYSFS_PREALLOC | VERIFY_OCTAL_PERMISSIONS(_mode) },\ + .show = _show, \ + .store = _store, \ +} + #define __ATTR_RO(_name) { \ .attr = { .name = __stringify(_name), .mode = S_IRUGO }, \ .show = _name##_show, \ |