Merge tag 'driver-core-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core and debugfs updates from Greg KH:
 "Here is the "big" driver core and debugfs changes for 5.3-rc1

  It's a lot of different patches, all across the tree due to some api
  changes and lots of debugfs cleanups.

  Other than the debugfs cleanups, in this set of changes we have:

   - bus iteration function cleanups

   - scripts/get_abi.pl tool to display and parse Documentation/ABI
     entries in a simple way

   - cleanups to Documenatation/ABI/ entries to make them parse easier
     due to typos and other minor things

   - default_attrs use for some ktype users

   - driver model documentation file conversions to .rst

   - compressed firmware file loading

   - deferred probe fixes

  All of these have been in linux-next for a while, with a bunch of
  merge issues that Stephen has been patient with me for"

* tag 'driver-core-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (102 commits)
  debugfs: make error message a bit more verbose
  orangefs: fix build warning from debugfs cleanup patch
  ubifs: fix build warning after debugfs cleanup patch
  driver: core: Allow subsystems to continue deferring probe
  drivers: base: cacheinfo: Ensure cpu hotplug work is done before Intel RDT
  arch_topology: Remove error messages on out-of-memory conditions
  lib: notifier-error-inject: no need to check return value of debugfs_create functions
  swiotlb: no need to check return value of debugfs_create functions
  ceph: no need to check return value of debugfs_create functions
  sunrpc: no need to check return value of debugfs_create functions
  ubifs: no need to check return value of debugfs_create functions
  orangefs: no need to check return value of debugfs_create functions
  nfsd: no need to check return value of debugfs_create functions
  lib: 842: no need to check return value of debugfs_create functions
  debugfs: provide pr_fmt() macro
  debugfs: log errors when something goes wrong
  drivers: s390/cio: Fix compilation warning about const qualifiers
  drivers: Add generic helper to match by of_node
  driver_find_device: Unify the match function with class_find_device()
  bus_find_device: Unify the match callback with class_find_device
  ...
This commit is contained in:
Linus Torvalds
2019-07-12 12:24:03 -07:00
201 changed files with 1929 additions and 2104 deletions

View File

@@ -137,7 +137,6 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
sizeof(*raw_capacity),
GFP_KERNEL);
if (!raw_capacity) {
pr_err("cpu_capacity: failed to allocate memory for raw capacities\n");
cap_parsing_failed = true;
return false;
}
@@ -217,10 +216,8 @@ static int __init register_cpufreq_notifier(void)
if (!acpi_disabled || !raw_capacity)
return -EINVAL;
if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL)) {
pr_err("cpu_capacity: failed to allocate memory for cpus_to_visit\n");
if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL))
return -ENOMEM;
}
cpumask_copy(cpus_to_visit, cpu_possible_mask);

View File

@@ -323,8 +323,8 @@ EXPORT_SYMBOL_GPL(bus_for_each_dev);
* return to the caller and not iterate over any more devices.
*/
struct device *bus_find_device(struct bus_type *bus,
struct device *start, void *data,
int (*match)(struct device *dev, void *data))
struct device *start, const void *data,
int (*match)(struct device *dev, const void *data))
{
struct klist_iter i;
struct device *dev;
@@ -342,7 +342,7 @@ struct device *bus_find_device(struct bus_type *bus,
}
EXPORT_SYMBOL_GPL(bus_find_device);
static int match_name(struct device *dev, void *data)
static int match_name(struct device *dev, const void *data)
{
const char *name = data;

View File

@@ -660,7 +660,8 @@ static int cacheinfo_cpu_pre_down(unsigned int cpu)
static int __init cacheinfo_sysfs_init(void)
{
return cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "base/cacheinfo:online",
return cpuhp_setup_state(CPUHP_AP_BASE_CACHEINFO_ONLINE,
"base/cacheinfo:online",
cacheinfo_cpu_online, cacheinfo_cpu_pre_down);
}
device_initcall(cacheinfo_sysfs_init);

View File

@@ -3356,3 +3356,9 @@ void device_set_of_node_from_dev(struct device *dev, const struct device *dev2)
dev->of_node_reused = true;
}
EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);
int device_match_of_node(struct device *dev, const void *np)
{
return dev->of_node == np;
}
EXPORT_SYMBOL_GPL(device_match_of_node);

View File

@@ -235,6 +235,19 @@ static int __init deferred_probe_timeout_setup(char *str)
}
__setup("deferred_probe_timeout=", deferred_probe_timeout_setup);
static int __driver_deferred_probe_check_state(struct device *dev)
{
if (!initcalls_done)
return -EPROBE_DEFER;
if (!deferred_probe_timeout) {
dev_WARN(dev, "deferred probe timeout, ignoring dependency");
return -ETIMEDOUT;
}
return 0;
}
/**
* driver_deferred_probe_check_state() - Check deferred probe state
* @dev: device to check
@@ -248,14 +261,40 @@ __setup("deferred_probe_timeout=", deferred_probe_timeout_setup);
*/
int driver_deferred_probe_check_state(struct device *dev)
{
if (initcalls_done) {
if (!deferred_probe_timeout) {
dev_WARN(dev, "deferred probe timeout, ignoring dependency");
return -ETIMEDOUT;
}
dev_warn(dev, "ignoring dependency for device, assuming no driver");
return -ENODEV;
}
int ret;
ret = __driver_deferred_probe_check_state(dev);
if (ret < 0)
return ret;
dev_warn(dev, "ignoring dependency for device, assuming no driver");
return -ENODEV;
}
/**
* driver_deferred_probe_check_state_continue() - check deferred probe state
* @dev: device to check
*
* Returns -ETIMEDOUT if deferred probe debug timeout has expired, or
* -EPROBE_DEFER otherwise.
*
* Drivers or subsystems can opt-in to calling this function instead of
* directly returning -EPROBE_DEFER.
*
* This is similar to driver_deferred_probe_check_state(), but it allows the
* subsystem to keep deferring probe after built-in drivers have had a chance
* to probe. One scenario where that is useful is if built-in drivers rely on
* resources that are provided by modular drivers.
*/
int driver_deferred_probe_check_state_continue(struct device *dev)
{
int ret;
ret = __driver_deferred_probe_check_state(dev);
if (ret < 0)
return ret;
return -EPROBE_DEFER;
}

View File

@@ -133,7 +133,7 @@ static struct bus_type *generic_match_buses[] = {
NULL,
};
static int device_fwnode_match(struct device *dev, void *fwnode)
static int device_fwnode_match(struct device *dev, const void *fwnode)
{
return dev_fwnode(dev) == fwnode;
}

View File

@@ -73,8 +73,8 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
* return to the caller and not iterate over any more devices.
*/
struct device *driver_find_device(struct device_driver *drv,
struct device *start, void *data,
int (*match)(struct device *dev, void *data))
struct device *start, const void *data,
int (*match)(struct device *dev, const void *data))
{
struct klist_iter i;
struct device *dev;

View File

@@ -26,6 +26,9 @@ config FW_LOADER
if FW_LOADER
config FW_LOADER_PAGED_BUF
bool
config EXTRA_FIRMWARE
string "Build named firmware blobs into the kernel binary"
help
@@ -67,6 +70,7 @@ config EXTRA_FIRMWARE_DIR
config FW_LOADER_USER_HELPER
bool "Enable the firmware sysfs fallback mechanism"
select FW_LOADER_PAGED_BUF
help
This option enables a sysfs loading facility to enable firmware
loading to the kernel through userspace as a fallback mechanism
@@ -151,5 +155,19 @@ config FW_LOADER_USER_HELPER_FALLBACK
If you are unsure about this, say N here.
config FW_LOADER_COMPRESS
bool "Enable compressed firmware support"
select FW_LOADER_PAGED_BUF
select XZ_DEC
help
This option enables the support for loading compressed firmware
files. The caller of firmware API receives the decompressed file
content. The compressed file is loaded as a fallback, only after
loading the raw file failed at first.
Currently only XZ-compressed files are supported, and they have to
be compressed with either none or crc32 integrity check type (pass
"-C crc32" option to xz command).
endif # FW_LOADER
endmenu

View File

@@ -219,20 +219,6 @@ static ssize_t firmware_loading_show(struct device *dev,
return sprintf(buf, "%d\n", loading);
}
/* one pages buffer should be mapped/unmapped only once */
static int map_fw_priv_pages(struct fw_priv *fw_priv)
{
if (!fw_priv->is_paged_buf)
return 0;
vunmap(fw_priv->data);
fw_priv->data = vmap(fw_priv->pages, fw_priv->nr_pages, 0,
PAGE_KERNEL_RO);
if (!fw_priv->data)
return -ENOMEM;
return 0;
}
/**
* firmware_loading_store() - set value in the 'loading' control file
* @dev: device pointer
@@ -254,7 +240,6 @@ static ssize_t firmware_loading_store(struct device *dev,
struct fw_priv *fw_priv;
ssize_t written = count;
int loading = simple_strtol(buf, NULL, 10);
int i;
mutex_lock(&fw_lock);
fw_priv = fw_sysfs->fw_priv;
@@ -265,12 +250,7 @@ static ssize_t firmware_loading_store(struct device *dev,
case 1:
/* discarding any previous partial load */
if (!fw_sysfs_done(fw_priv)) {
for (i = 0; i < fw_priv->nr_pages; i++)
__free_page(fw_priv->pages[i]);
vfree(fw_priv->pages);
fw_priv->pages = NULL;
fw_priv->page_array_size = 0;
fw_priv->nr_pages = 0;
fw_free_paged_buf(fw_priv);
fw_state_start(fw_priv);
}
break;
@@ -284,7 +264,7 @@ static ssize_t firmware_loading_store(struct device *dev,
* see the mapped 'buf->data' once the loading
* is completed.
* */
rc = map_fw_priv_pages(fw_priv);
rc = fw_map_paged_buf(fw_priv);
if (rc)
dev_err(dev, "%s: map pages failed\n",
__func__);
@@ -389,40 +369,13 @@ out:
static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size)
{
struct fw_priv *fw_priv= fw_sysfs->fw_priv;
int pages_needed = PAGE_ALIGN(min_size) >> PAGE_SHIFT;
int err;
/* If the array of pages is too small, grow it... */
if (fw_priv->page_array_size < pages_needed) {
int new_array_size = max(pages_needed,
fw_priv->page_array_size * 2);
struct page **new_pages;
new_pages = vmalloc(array_size(new_array_size, sizeof(void *)));
if (!new_pages) {
fw_load_abort(fw_sysfs);
return -ENOMEM;
}
memcpy(new_pages, fw_priv->pages,
fw_priv->page_array_size * sizeof(void *));
memset(&new_pages[fw_priv->page_array_size], 0, sizeof(void *) *
(new_array_size - fw_priv->page_array_size));
vfree(fw_priv->pages);
fw_priv->pages = new_pages;
fw_priv->page_array_size = new_array_size;
}
while (fw_priv->nr_pages < pages_needed) {
fw_priv->pages[fw_priv->nr_pages] =
alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
if (!fw_priv->pages[fw_priv->nr_pages]) {
fw_load_abort(fw_sysfs);
return -ENOMEM;
}
fw_priv->nr_pages++;
}
return 0;
err = fw_grow_paged_buf(fw_sysfs->fw_priv,
PAGE_ALIGN(min_size) >> PAGE_SHIFT);
if (err)
fw_load_abort(fw_sysfs);
return err;
}
/**
@@ -659,7 +612,7 @@ static bool fw_run_sysfs_fallback(enum fw_opt opt_flags)
/* Also permit LSMs and IMA to fail firmware sysfs fallback */
ret = security_kernel_load_data(LOADING_FIRMWARE);
if (ret < 0)
return ret;
return false;
return fw_force_sysfs_fallback(opt_flags);
}

View File

@@ -64,12 +64,14 @@ struct fw_priv {
void *data;
size_t size;
size_t allocated_size;
#ifdef CONFIG_FW_LOADER_USER_HELPER
#ifdef CONFIG_FW_LOADER_PAGED_BUF
bool is_paged_buf;
bool need_uevent;
struct page **pages;
int nr_pages;
int page_array_size;
#endif
#ifdef CONFIG_FW_LOADER_USER_HELPER
bool need_uevent;
struct list_head pending_list;
#endif
const char *fw_name;
@@ -133,4 +135,14 @@ static inline void fw_state_done(struct fw_priv *fw_priv)
int assign_fw(struct firmware *fw, struct device *device,
enum fw_opt opt_flags);
#ifdef CONFIG_FW_LOADER_PAGED_BUF
void fw_free_paged_buf(struct fw_priv *fw_priv);
int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed);
int fw_map_paged_buf(struct fw_priv *fw_priv);
#else
static inline void fw_free_paged_buf(struct fw_priv *fw_priv) {}
int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; }
int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; }
#endif
#endif /* __FIRMWARE_LOADER_H */

View File

@@ -33,6 +33,7 @@
#include <linux/syscore_ops.h>
#include <linux/reboot.h>
#include <linux/security.h>
#include <linux/xz.h>
#include <generated/utsrelease.h>
@@ -251,15 +252,7 @@ static void __free_fw_priv(struct kref *ref)
list_del(&fw_priv->list);
spin_unlock(&fwc->lock);
#ifdef CONFIG_FW_LOADER_USER_HELPER
if (fw_priv->is_paged_buf) {
int i;
vunmap(fw_priv->data);
for (i = 0; i < fw_priv->nr_pages; i++)
__free_page(fw_priv->pages[i]);
vfree(fw_priv->pages);
} else
#endif
fw_free_paged_buf(fw_priv); /* free leftover pages */
if (!fw_priv->allocated_size)
vfree(fw_priv->data);
kfree_const(fw_priv->fw_name);
@@ -274,6 +267,174 @@ static void free_fw_priv(struct fw_priv *fw_priv)
spin_unlock(&fwc->lock);
}
#ifdef CONFIG_FW_LOADER_PAGED_BUF
void fw_free_paged_buf(struct fw_priv *fw_priv)
{
int i;
if (!fw_priv->pages)
return;
for (i = 0; i < fw_priv->nr_pages; i++)
__free_page(fw_priv->pages[i]);
kvfree(fw_priv->pages);
fw_priv->pages = NULL;
fw_priv->page_array_size = 0;
fw_priv->nr_pages = 0;
}
int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed)
{
/* If the array of pages is too small, grow it */
if (fw_priv->page_array_size < pages_needed) {
int new_array_size = max(pages_needed,
fw_priv->page_array_size * 2);
struct page **new_pages;
new_pages = kvmalloc_array(new_array_size, sizeof(void *),
GFP_KERNEL);
if (!new_pages)
return -ENOMEM;
memcpy(new_pages, fw_priv->pages,
fw_priv->page_array_size * sizeof(void *));
memset(&new_pages[fw_priv->page_array_size], 0, sizeof(void *) *
(new_array_size - fw_priv->page_array_size));
kvfree(fw_priv->pages);
fw_priv->pages = new_pages;
fw_priv->page_array_size = new_array_size;
}
while (fw_priv->nr_pages < pages_needed) {
fw_priv->pages[fw_priv->nr_pages] =
alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
if (!fw_priv->pages[fw_priv->nr_pages])
return -ENOMEM;
fw_priv->nr_pages++;
}
return 0;
}
int fw_map_paged_buf(struct fw_priv *fw_priv)
{
/* one pages buffer should be mapped/unmapped only once */
if (!fw_priv->pages)
return 0;
vunmap(fw_priv->data);
fw_priv->data = vmap(fw_priv->pages, fw_priv->nr_pages, 0,
PAGE_KERNEL_RO);
if (!fw_priv->data)
return -ENOMEM;
/* page table is no longer needed after mapping, let's free */
kvfree(fw_priv->pages);
fw_priv->pages = NULL;
return 0;
}
#endif
/*
* XZ-compressed firmware support
*/
#ifdef CONFIG_FW_LOADER_COMPRESS
/* show an error and return the standard error code */
static int fw_decompress_xz_error(struct device *dev, enum xz_ret xz_ret)
{
if (xz_ret != XZ_STREAM_END) {
dev_warn(dev, "xz decompression failed (xz_ret=%d)\n", xz_ret);
return xz_ret == XZ_MEM_ERROR ? -ENOMEM : -EINVAL;
}
return 0;
}
/* single-shot decompression onto the pre-allocated buffer */
static int fw_decompress_xz_single(struct device *dev, struct fw_priv *fw_priv,
size_t in_size, const void *in_buffer)
{
struct xz_dec *xz_dec;
struct xz_buf xz_buf;
enum xz_ret xz_ret;
xz_dec = xz_dec_init(XZ_SINGLE, (u32)-1);
if (!xz_dec)
return -ENOMEM;
xz_buf.in_size = in_size;
xz_buf.in = in_buffer;
xz_buf.in_pos = 0;
xz_buf.out_size = fw_priv->allocated_size;
xz_buf.out = fw_priv->data;
xz_buf.out_pos = 0;
xz_ret = xz_dec_run(xz_dec, &xz_buf);
xz_dec_end(xz_dec);
fw_priv->size = xz_buf.out_pos;
return fw_decompress_xz_error(dev, xz_ret);
}
/* decompression on paged buffer and map it */
static int fw_decompress_xz_pages(struct device *dev, struct fw_priv *fw_priv,
size_t in_size, const void *in_buffer)
{
struct xz_dec *xz_dec;
struct xz_buf xz_buf;
enum xz_ret xz_ret;
struct page *page;
int err = 0;
xz_dec = xz_dec_init(XZ_DYNALLOC, (u32)-1);
if (!xz_dec)
return -ENOMEM;
xz_buf.in_size = in_size;
xz_buf.in = in_buffer;
xz_buf.in_pos = 0;
fw_priv->is_paged_buf = true;
fw_priv->size = 0;
do {
if (fw_grow_paged_buf(fw_priv, fw_priv->nr_pages + 1)) {
err = -ENOMEM;
goto out;
}
/* decompress onto the new allocated page */
page = fw_priv->pages[fw_priv->nr_pages - 1];
xz_buf.out = kmap(page);
xz_buf.out_pos = 0;
xz_buf.out_size = PAGE_SIZE;
xz_ret = xz_dec_run(xz_dec, &xz_buf);
kunmap(page);
fw_priv->size += xz_buf.out_pos;
/* partial decompression means either end or error */
if (xz_buf.out_pos != PAGE_SIZE)
break;
} while (xz_ret == XZ_OK);
err = fw_decompress_xz_error(dev, xz_ret);
if (!err)
err = fw_map_paged_buf(fw_priv);
out:
xz_dec_end(xz_dec);
return err;
}
static int fw_decompress_xz(struct device *dev, struct fw_priv *fw_priv,
size_t in_size, const void *in_buffer)
{
/* if the buffer is pre-allocated, we can perform in single-shot mode */
if (fw_priv->data)
return fw_decompress_xz_single(dev, fw_priv, in_size, in_buffer);
else
return fw_decompress_xz_pages(dev, fw_priv, in_size, in_buffer);
}
#endif /* CONFIG_FW_LOADER_COMPRESS */
/* direct firmware loading support */
static char fw_path_para[256];
static const char * const fw_path[] = {
@@ -293,7 +454,12 @@ module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
static int
fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv)
fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv,
const char *suffix,
int (*decompress)(struct device *dev,
struct fw_priv *fw_priv,
size_t in_size,
const void *in_buffer))
{
loff_t size;
int i, len;
@@ -301,9 +467,11 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv)
char *path;
enum kernel_read_file_id id = READING_FIRMWARE;
size_t msize = INT_MAX;
void *buffer = NULL;
/* Already populated data member means we're loading into a buffer */
if (fw_priv->data) {
if (!decompress && fw_priv->data) {
buffer = fw_priv->data;
id = READING_FIRMWARE_PREALLOC_BUFFER;
msize = fw_priv->allocated_size;
}
@@ -317,15 +485,15 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv)
if (!fw_path[i][0])
continue;
len = snprintf(path, PATH_MAX, "%s/%s",
fw_path[i], fw_priv->fw_name);
len = snprintf(path, PATH_MAX, "%s/%s%s",
fw_path[i], fw_priv->fw_name, suffix);
if (len >= PATH_MAX) {
rc = -ENAMETOOLONG;
break;
}
fw_priv->size = 0;
rc = kernel_read_file_from_path(path, &fw_priv->data, &size,
rc = kernel_read_file_from_path(path, &buffer, &size,
msize, id);
if (rc) {
if (rc != -ENOENT)
@@ -336,8 +504,24 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv)
path);
continue;
}
dev_dbg(device, "direct-loading %s\n", fw_priv->fw_name);
fw_priv->size = size;
if (decompress) {
dev_dbg(device, "f/w decompressing %s\n",
fw_priv->fw_name);
rc = decompress(device, fw_priv, size, buffer);
/* discard the superfluous original content */
vfree(buffer);
buffer = NULL;
if (rc) {
fw_free_paged_buf(fw_priv);
continue;
}
} else {
dev_dbg(device, "direct-loading %s\n",
fw_priv->fw_name);
if (!fw_priv->data)
fw_priv->data = buffer;
fw_priv->size = size;
}
fw_state_done(fw_priv);
break;
}
@@ -584,7 +768,13 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
if (ret <= 0) /* error or already assigned */
goto out;
ret = fw_get_filesystem_firmware(device, fw->priv);
ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL);
#ifdef CONFIG_FW_LOADER_COMPRESS
if (ret == -ENOENT)
ret = fw_get_filesystem_firmware(device, fw->priv, ".xz",
fw_decompress_xz);
#endif
if (ret) {
if (!(opt_flags & FW_OPT_NO_WARN))
dev_warn(device,

View File

@@ -66,6 +66,7 @@ static DEVICE_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
* @dev: Device for this memory access class
* @list_node: List element in the node's access list
* @access: The access class rank
* @hmem_attrs: Heterogeneous memory performance attributes
*/
struct node_access_nodes {
struct device dev;
@@ -673,8 +674,8 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid)
/**
* register_memory_node_under_compute_node - link memory node to its compute
* node for a given access class.
* @mem_node: Memory node number
* @cpu_node: Cpu node number
* @mem_nid: Memory node number
* @cpu_nid: Cpu node number
* @access: Access class to register
*
* Description:

View File

@@ -5,7 +5,7 @@
* Copyright (c) 2002-3 Patrick Mochel
* Copyright (c) 2002-3 Open Source Development Labs
*
* Please see Documentation/driver-model/platform.txt for more
* Please see Documentation/driver-model/platform.rst for more
* information.
*/