Commit ec064d3c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'driver-core-4.18-rc1' of...

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

Pull driver core updates from Greg KH:
 "Here is the driver core patchset for 4.18-rc1.

  The large chunk of these are firmware core documentation and api
  updates. Nothing major there, just better descriptions for others to
  be able to understand the firmware code better. There's also a user
  for a new firmware api call.

  Other than that, there are some minor updates for debugfs, kernfs, and
  the driver core itself.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'driver-core-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (23 commits)
  driver core: hold dev's parent lock when needed
  driver-core: return EINVAL error instead of BUG_ON()
  driver core: add __printf verification to device_create_groups_vargs
  mm: memory_hotplug: use put_device() if device_register fail
  base: core: fix typo 'can by' to 'can be'
  debugfs: inode: debugfs_create_dir uses mode permission from parent
  debugfs: Re-use kstrtobool_from_user()
  Documentation: clarify firmware_class provenance and why we can't rename the module
  Documentation: remove stale firmware API reference
  Documentation: fix few typos and clarifications for the firmware loader
  ath10k: re-enable the firmware fallback mechanism for testmode
  ath10k: use firmware_request_nowarn() to load firmware
  firmware: add firmware_request_nowarn() - load firmware without warnings
  firmware_loader: make firmware_fallback_sysfs() print more useful
  firmware_loader: move kconfig FW_LOADER entries to its own file
  firmware_loader: replace ---help--- with help
  firmware_loader: enhance Kconfig documentation over FW_LOADER
  firmware_loader: document firmware_sysfs_fallback()
  firmware: rename fw_sysfs_fallback to firmware_fallback_sysfs()
  firmware: use () to terminate kernel-doc function names
  ...
parents abf7dba7 8c97a46a
...@@ -121,10 +121,7 @@ read back the image downloaded. ...@@ -121,10 +121,7 @@ read back the image downloaded.
.. note:: .. note::
This driver requires a patch for firmware_class.c which has the modified After updating the BIOS image a user mode application needs to execute
request_firmware_nowait function.
Also after updating the BIOS image a user mode application needs to execute
code which sends the BIOS update request to the BIOS. So on the next reboot code which sends the BIOS update request to the BIOS. So on the next reboot
the BIOS knows about the new image downloaded and it updates itself. the BIOS knows about the new image downloaded and it updates itself.
Also don't unload the rbu driver if the image has to be updated. Also don't unload the rbu driver if the image has to be updated.
......
...@@ -72,9 +72,12 @@ the firmware requested, and establishes it in the device hierarchy by ...@@ -72,9 +72,12 @@ the firmware requested, and establishes it in the device hierarchy by
associating the device used to make the request as the device's parent. associating the device used to make the request as the device's parent.
The sysfs directory's file attributes are defined and controlled through The sysfs directory's file attributes are defined and controlled through
the new device's class (firmware_class) and group (fw_dev_attr_groups). the new device's class (firmware_class) and group (fw_dev_attr_groups).
This is actually where the original firmware_class.c file name comes from, This is actually where the original firmware_class module name came from,
as originally the only firmware loading mechanism available was the given that originally the only firmware loading mechanism available was the
mechanism we now use as a fallback mechanism. mechanism we now use as a fallback mechanism, which registers a struct class
firmware_class. Because the attributes exposed are part of the module name, the
module name firmware_class cannot be renamed in the future, to ensure backward
compatibility with old userspace.
To load firmware using the sysfs interface we expose a loading indicator, To load firmware using the sysfs interface we expose a loading indicator,
and a file upload firmware into: and a file upload firmware into:
...@@ -83,7 +86,7 @@ and a file upload firmware into: ...@@ -83,7 +86,7 @@ and a file upload firmware into:
* /sys/$DEVPATH/data * /sys/$DEVPATH/data
To upload firmware you will echo 1 onto the loading file to indicate To upload firmware you will echo 1 onto the loading file to indicate
you are loading firmware. You then cat the firmware into the data file, you are loading firmware. You then write the firmware into the data file,
and you notify the kernel the firmware is ready by echo'ing 0 onto and you notify the kernel the firmware is ready by echo'ing 0 onto
the loading file. the loading file.
...@@ -136,7 +139,8 @@ by kobject uevents. This is specially exacerbated due to the fact that most ...@@ -136,7 +139,8 @@ by kobject uevents. This is specially exacerbated due to the fact that most
distributions today disable CONFIG_FW_LOADER_USER_HELPER_FALLBACK. distributions today disable CONFIG_FW_LOADER_USER_HELPER_FALLBACK.
Refer to do_firmware_uevent() for details of the kobject event variables Refer to do_firmware_uevent() for details of the kobject event variables
setup. Variables passwdd with a kobject add event: setup. The variables currently passed to userspace with a "kobject add"
event are:
* FIRMWARE=firmware name * FIRMWARE=firmware name
* TIMEOUT=timeout value * TIMEOUT=timeout value
......
...@@ -29,8 +29,8 @@ Some implementation details about the firmware cache setup: ...@@ -29,8 +29,8 @@ Some implementation details about the firmware cache setup:
* If an asynchronous call is used the firmware cache is only set up for a * If an asynchronous call is used the firmware cache is only set up for a
device if if the second argument (uevent) to request_firmware_nowait() is device if if the second argument (uevent) to request_firmware_nowait() is
true. When uevent is true it requests that a kobject uevent be sent to true. When uevent is true it requests that a kobject uevent be sent to
userspace for the firmware request. For details refer to the Fackback userspace for the firmware request through the sysfs fallback mechanism
mechanism documented below. if the firmware file is not found.
* If the firmware cache is determined to be needed as per the above two * If the firmware cache is determined to be needed as per the above two
criteria the firmware cache is setup by adding a devres entry for the criteria the firmware cache is setup by adding a devres entry for the
......
...@@ -20,6 +20,11 @@ request_firmware ...@@ -20,6 +20,11 @@ request_firmware
.. kernel-doc:: drivers/base/firmware_loader/main.c .. kernel-doc:: drivers/base/firmware_loader/main.c
:functions: request_firmware :functions: request_firmware
firmware_request_nowarn
-----------------------
.. kernel-doc:: drivers/base/firmware_loader/main.c
:functions: firmware_request_nowarn
request_firmware_direct request_firmware_direct
----------------------- -----------------------
.. kernel-doc:: drivers/base/firmware_loader/main.c .. kernel-doc:: drivers/base/firmware_loader/main.c
......
...@@ -70,81 +70,25 @@ config STANDALONE ...@@ -70,81 +70,25 @@ config STANDALONE
If unsure, say Y. If unsure, say Y.
config PREVENT_FIRMWARE_BUILD config PREVENT_FIRMWARE_BUILD
bool "Prevent firmware from being built" bool "Disable drivers features which enable custom firmware building"
default y default y
help help
Say yes to avoid building firmware. Firmware is usually shipped Say yes to disable driver features which enable building a custom
with the driver and only when updating the firmware should a driver firmware at kernel build time. These drivers do not use the
rebuild be made. kernel firmware API to load firmware (CONFIG_FW_LOADER), instead they
If unsure, say Y here. use their own custom loading mechanism. The required firmware is
usually shipped with the driver, building the driver firmware
config FW_LOADER should only be needed if you have an updated firmware source.
tristate "Userspace firmware loading support" if EXPERT
default y Firmware should not be being built as part of kernel, these days
---help--- you should always prevent this and say Y here. There are only two
This option is provided for the case where none of the in-tree modules old drivers which enable building of its firmware at kernel build
require userspace firmware loading support, but a module built time:
out-of-tree does.
o CONFIG_WANXL through CONFIG_WANXL_BUILD_FIRMWARE
config EXTRA_FIRMWARE o CONFIG_SCSI_AIC79XX through CONFIG_AIC79XX_BUILD_FIRMWARE
string "External firmware blobs to build into the kernel binary"
depends on FW_LOADER source "drivers/base/firmware_loader/Kconfig"
help
Various drivers in the kernel source tree may require firmware,
which is generally available in your distribution's linux-firmware
package.
The linux-firmware package should install firmware into
/lib/firmware/ on your system, so they can be loaded by userspace
helpers on request.
This option allows firmware to be built into the kernel for the case
where the user either cannot or doesn't want to provide it from
userspace at runtime (for example, when the firmware in question is
required for accessing the boot device, and the user doesn't want to
use an initrd).
This option is a string and takes the (space-separated) names of the
firmware files -- the same names that appear in MODULE_FIRMWARE()
and request_firmware() in the source. These files should exist under
the directory specified by the EXTRA_FIRMWARE_DIR option, which is
/lib/firmware by default.
For example, you might set CONFIG_EXTRA_FIRMWARE="usb8388.bin", copy
the usb8388.bin file into /lib/firmware, and build the kernel. Then
any request_firmware("usb8388.bin") will be satisfied internally
without needing to call out to userspace.
WARNING: If you include additional firmware files into your binary
kernel image that are not available under the terms of the GPL,
then it may be a violation of the GPL to distribute the resulting
image since it combines both GPL and non-GPL work. You should
consult a lawyer of your own before distributing such an image.
config EXTRA_FIRMWARE_DIR
string "Firmware blobs root directory"
depends on EXTRA_FIRMWARE != ""
default "/lib/firmware"
help
This option controls the directory in which the kernel build system
looks for the firmware files listed in the EXTRA_FIRMWARE option.
config FW_LOADER_USER_HELPER
bool
config FW_LOADER_USER_HELPER_FALLBACK
bool "Fallback user-helper invocation for firmware loading"
depends on FW_LOADER
select FW_LOADER_USER_HELPER
help
This option enables / disables the invocation of user-helper
(e.g. udev) for loading firmware files as a fallback after the
direct file loading in kernel fails. The user-mode helper is
no longer required unless you have a special firmware file that
resides in a non-standard path. Moreover, the udev support has
been deprecated upstream.
If you are unsure about this, say N here.
config WANT_DEV_COREDUMP config WANT_DEV_COREDUMP
bool bool
......
...@@ -184,10 +184,10 @@ static ssize_t unbind_store(struct device_driver *drv, const char *buf, ...@@ -184,10 +184,10 @@ static ssize_t unbind_store(struct device_driver *drv, const char *buf,
dev = bus_find_device_by_name(bus, NULL, buf); dev = bus_find_device_by_name(bus, NULL, buf);
if (dev && dev->driver == drv) { if (dev && dev->driver == drv) {
if (dev->parent) /* Needed for USB */ if (dev->parent && dev->bus->need_parent_lock)
device_lock(dev->parent); device_lock(dev->parent);
device_release_driver(dev); device_release_driver(dev);
if (dev->parent) if (dev->parent && dev->bus->need_parent_lock)
device_unlock(dev->parent); device_unlock(dev->parent);
err = count; err = count;
} }
...@@ -211,12 +211,12 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf, ...@@ -211,12 +211,12 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf,
dev = bus_find_device_by_name(bus, NULL, buf); dev = bus_find_device_by_name(bus, NULL, buf);
if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
if (dev->parent) /* Needed for USB */ if (dev->parent && bus->need_parent_lock)
device_lock(dev->parent); device_lock(dev->parent);
device_lock(dev); device_lock(dev);
err = driver_probe_device(drv, dev); err = driver_probe_device(drv, dev);
device_unlock(dev); device_unlock(dev);
if (dev->parent) if (dev->parent && bus->need_parent_lock)
device_unlock(dev->parent); device_unlock(dev->parent);
if (err > 0) { if (err > 0) {
...@@ -735,10 +735,10 @@ static int __must_check bus_rescan_devices_helper(struct device *dev, ...@@ -735,10 +735,10 @@ static int __must_check bus_rescan_devices_helper(struct device *dev,
int ret = 0; int ret = 0;
if (!dev->driver) { if (!dev->driver) {
if (dev->parent) /* Needed for USB */ if (dev->parent && dev->bus->need_parent_lock)
device_lock(dev->parent); device_lock(dev->parent);
ret = device_attach(dev); ret = device_attach(dev);
if (dev->parent) if (dev->parent && dev->bus->need_parent_lock)
device_unlock(dev->parent); device_unlock(dev->parent);
} }
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
...@@ -770,10 +770,10 @@ EXPORT_SYMBOL_GPL(bus_rescan_devices); ...@@ -770,10 +770,10 @@ EXPORT_SYMBOL_GPL(bus_rescan_devices);
int device_reprobe(struct device *dev) int device_reprobe(struct device *dev)
{ {
if (dev->driver) { if (dev->driver) {
if (dev->parent) /* Needed for USB */ if (dev->parent && dev->bus->need_parent_lock)
device_lock(dev->parent); device_lock(dev->parent);
device_release_driver(dev); device_release_driver(dev);
if (dev->parent) if (dev->parent && dev->bus->need_parent_lock)
device_unlock(dev->parent); device_unlock(dev->parent);
} }
return bus_rescan_devices_helper(dev, NULL); return bus_rescan_devices_helper(dev, NULL);
......
...@@ -1487,7 +1487,7 @@ class_dir_create_and_add(struct class *class, struct kobject *parent_kobj) ...@@ -1487,7 +1487,7 @@ class_dir_create_and_add(struct class *class, struct kobject *parent_kobj)
dir = kzalloc(sizeof(*dir), GFP_KERNEL); dir = kzalloc(sizeof(*dir), GFP_KERNEL);
if (!dir) if (!dir)
return NULL; return ERR_PTR(-ENOMEM);
dir->class = class; dir->class = class;
kobject_init(&dir->kobj, &class_dir_ktype); kobject_init(&dir->kobj, &class_dir_ktype);
...@@ -1497,7 +1497,7 @@ class_dir_create_and_add(struct class *class, struct kobject *parent_kobj) ...@@ -1497,7 +1497,7 @@ class_dir_create_and_add(struct class *class, struct kobject *parent_kobj)
retval = kobject_add(&dir->kobj, parent_kobj, "%s", class->name); retval = kobject_add(&dir->kobj, parent_kobj, "%s", class->name);
if (retval < 0) { if (retval < 0) {
kobject_put(&dir->kobj); kobject_put(&dir->kobj);
return NULL; return ERR_PTR(retval);
} }
return &dir->kobj; return &dir->kobj;
} }
...@@ -1804,6 +1804,10 @@ int device_add(struct device *dev) ...@@ -1804,6 +1804,10 @@ int device_add(struct device *dev)
parent = get_device(dev->parent); parent = get_device(dev->parent);
kobj = get_device_parent(dev, parent); kobj = get_device_parent(dev, parent);
if (IS_ERR(kobj)) {
error = PTR_ERR(kobj);
goto parent_error;
}
if (kobj) if (kobj)
dev->kobj.parent = kobj; dev->kobj.parent = kobj;
...@@ -1902,6 +1906,7 @@ int device_add(struct device *dev) ...@@ -1902,6 +1906,7 @@ int device_add(struct device *dev)
kobject_del(&dev->kobj); kobject_del(&dev->kobj);
Error: Error:
cleanup_glue_dir(dev, glue_dir); cleanup_glue_dir(dev, glue_dir);
parent_error:
put_device(parent); put_device(parent);
name_error: name_error:
kfree(dev->p); kfree(dev->p);
...@@ -2426,7 +2431,7 @@ static void device_create_release(struct device *dev) ...@@ -2426,7 +2431,7 @@ static void device_create_release(struct device *dev)
kfree(dev); kfree(dev);
} }
static struct device * static __printf(6, 0) struct device *
device_create_groups_vargs(struct class *class, struct device *parent, device_create_groups_vargs(struct class *class, struct device *parent,
dev_t devt, void *drvdata, dev_t devt, void *drvdata,
const struct attribute_group **groups, const struct attribute_group **groups,
...@@ -2704,7 +2709,7 @@ static int device_move_class_links(struct device *dev, ...@@ -2704,7 +2709,7 @@ static int device_move_class_links(struct device *dev,
/** /**
* device_move - moves a device to a new parent * device_move - moves a device to a new parent
* @dev: the pointer to the struct device to be moved * @dev: the pointer to the struct device to be moved
* @new_parent: the new parent of the device (can by NULL) * @new_parent: the new parent of the device (can be NULL)
* @dpm_order: how to reorder the dpm_list * @dpm_order: how to reorder the dpm_list
*/ */
int device_move(struct device *dev, struct device *new_parent, int device_move(struct device *dev, struct device *new_parent,
...@@ -2721,6 +2726,11 @@ int device_move(struct device *dev, struct device *new_parent, ...@@ -2721,6 +2726,11 @@ int device_move(struct device *dev, struct device *new_parent,
device_pm_lock(); device_pm_lock();
new_parent = get_device(new_parent); new_parent = get_device(new_parent);
new_parent_kobj = get_device_parent(dev, new_parent); new_parent_kobj = get_device_parent(dev, new_parent);
if (IS_ERR(new_parent_kobj)) {
error = PTR_ERR(new_parent_kobj);
put_device(new_parent);
goto out;
}
pr_debug("device: '%s': %s: moving to '%s'\n", dev_name(dev), pr_debug("device: '%s': %s: moving to '%s'\n", dev_name(dev),
__func__, new_parent ? dev_name(new_parent) : "<NULL>"); __func__, new_parent ? dev_name(new_parent) : "<NULL>");
......
...@@ -814,13 +814,13 @@ static int __driver_attach(struct device *dev, void *data) ...@@ -814,13 +814,13 @@ static int __driver_attach(struct device *dev, void *data)
return ret; return ret;
} /* ret > 0 means positive match */ } /* ret > 0 means positive match */
if (dev->parent) /* Needed for USB */ if (dev->parent && dev->bus->need_parent_lock)
device_lock(dev->parent); device_lock(dev->parent);
device_lock(dev); device_lock(dev);
if (!dev->driver) if (!dev->driver)
driver_probe_device(drv, dev); driver_probe_device(drv, dev);
device_unlock(dev); device_unlock(dev);
if (dev->parent) if (dev->parent && dev->bus->need_parent_lock)
device_unlock(dev->parent); device_unlock(dev->parent);
return 0; return 0;
...@@ -916,7 +916,7 @@ void device_release_driver_internal(struct device *dev, ...@@ -916,7 +916,7 @@ void device_release_driver_internal(struct device *dev,
struct device_driver *drv, struct device_driver *drv,
struct device *parent) struct device *parent)
{ {
if (parent) if (parent && dev->bus->need_parent_lock)
device_lock(parent); device_lock(parent);
device_lock(dev); device_lock(dev);
...@@ -924,7 +924,7 @@ void device_release_driver_internal(struct device *dev, ...@@ -924,7 +924,7 @@ void device_release_driver_internal(struct device *dev,
__device_release_driver(dev, parent); __device_release_driver(dev, parent);
device_unlock(dev); device_unlock(dev);
if (parent) if (parent && dev->bus->need_parent_lock)
device_unlock(parent); device_unlock(parent);
} }
......
...@@ -148,7 +148,11 @@ int driver_register(struct device_driver *drv) ...@@ -148,7 +148,11 @@ int driver_register(struct device_driver *drv)
int ret; int ret;
struct device_driver *other; struct device_driver *other;
BUG_ON(!drv->bus->p); if (!drv->bus->p) {
pr_err("Driver '%s' was unable to register with bus_type '%s' because the bus was not initialized.\n",
drv->name, drv->bus->name);
return -EINVAL;
}
if ((drv->bus->probe && drv->probe) || if ((drv->bus->probe && drv->probe) ||
(drv->bus->remove && drv->remove) || (drv->bus->remove && drv->remove) ||
......
menu "Firmware loader"
config FW_LOADER
tristate "Firmware loading facility" if EXPERT
default y
help
This enables the firmware loading facility in the kernel. The kernel
will first look for built-in firmware, if it has any. Next, it will
look for the requested firmware in a series of filesystem paths:
o firmware_class path module parameter or kernel boot param
o /lib/firmware/updates/UTS_RELEASE
o /lib/firmware/updates
o /lib/firmware/UTS_RELEASE
o /lib/firmware
Enabling this feature only increases your kernel image by about
828 bytes, enable this option unless you are certain you don't
need firmware.
You typically want this built-in (=y) but you can also enable this
as a module, in which case the firmware_class module will be built.
You also want to be sure to enable this built-in if you are going to
enable built-in firmware (CONFIG_EXTRA_FIRMWARE).
if FW_LOADER
config EXTRA_FIRMWARE
string "Build named firmware blobs into the kernel binary"
help
Device drivers which require firmware can typically deal with
having the kernel load firmware from the various supported
/lib/firmware/ paths. This option enables you to build into the
kernel firmware files. Built-in firmware searches are preceded
over firmware lookups using your filesystem over the supported
/lib/firmware paths documented on CONFIG_FW_LOADER.
This may be useful for testing or if the firmware is required early on
in boot and cannot rely on the firmware being placed in an initrd or
initramfs.
This option is a string and takes the (space-separated) names of the
firmware files -- the same names that appear in MODULE_FIRMWARE()
and request_firmware() in the source. These files should exist under
the directory specified by the EXTRA_FIRMWARE_DIR option, which is
/lib/firmware by default.
For example, you might set CONFIG_EXTRA_FIRMWARE="usb8388.bin", copy
the usb8388.bin file into /lib/firmware, and build the kernel. Then
any request_firmware("usb8388.bin") will be satisfied internally
inside the kernel without ever looking at your filesystem at runtime.
WARNING: If you include additional firmware files into your binary
kernel image that are not available under the terms of the GPL,
then it may be a violation of the GPL to distribute the resulting
image since it combines both GPL and non-GPL work. You should
consult a lawyer of your own before distributing such an image.
config EXTRA_FIRMWARE_DIR
string "Firmware blobs root directory"
depends on EXTRA_FIRMWARE != ""
default "/lib/firmware"
help
This option controls the directory in which the kernel build system
looks for the firmware files listed in the EXTRA_FIRMWARE option.
config FW_LOADER_USER_HELPER
bool "Enable the firmware sysfs fallback mechanism"
help
This option enables a sysfs loading facility to enable firmware
loading to the kernel through userspace as a fallback mechanism
if and only if the kernel's direct filesystem lookup for the
firmware failed using the different /lib/firmware/ paths, or the
path specified in the firmware_class path module parameter, or the
firmware_class path kernel boot parameter if the firmware_class is
built-in. For details on how to work with the sysfs fallback mechanism
refer to Documentation/driver-api/firmware/fallback-mechanisms.rst.
The direct filesystem lookup for firmware is always used first now.
If the kernel's direct filesystem lookup for firmware fails to find
the requested firmware a sysfs fallback loading facility is made
available and userspace is informed about this through uevents.
The uevent can be suppressed if the driver explicitly requested it,
this is known as the driver using the custom fallback mechanism.
If the custom fallback mechanism is used userspace must always
acknowledge failure to find firmware as the timeout for the fallback
mechanism is disabled, and failed requests will linger forever.
This used to be the default firmware loading facility, and udev used
to listen for uvents to load firmware for the kernel. The firmware
loading facility functionality in udev has been removed, as such it
can no longer be relied upon as a fallback mechanism. Linux no longer
relies on or uses a fallback mechanism in userspace. If you need to
rely on one refer to the permissively licensed firmwared:
https://github.com/teg/firmwared
Since this was the default firmware loading facility at one point,
old userspace may exist which relies upon it, and as such this
mechanism can never be removed from the kernel.
You should only enable this functionality if you are certain you
require a fallback mechanism and have a userspace mechanism ready to
load firmware in case it is not found. One main reason for this may
be if you have drivers which require firmware built-in and for
whatever reason cannot place the required firmware in initramfs.
Another reason kernels may have this feature enabled is to support a
driver which explicitly relies on this fallback mechanism. Only two
drivers need this today:
o CONFIG_LEDS_LP55XX_COMMON
o CONFIG_DELL_RBU
Outside of supporting the above drivers, another reason for needing
this may be that your firmware resides outside of the paths the kernel
looks for and cannot possibly be specified using the firmware_class
path module parameter or kernel firmware_class path boot parameter
if firmware_class is built-in.
A modern use case may be to temporarily mount a custom partition
during provisioning which is only accessible to userspace, and then
to use it to look for and fetch the required firmware. Such type of
driver functionality may not even ever be desirable upstream by
vendors, and as such is only required to be supported as an interface
for provisioning. Since udev's firmware loading facility has been
removed you can use firmwared or a fork of it to customize how you
want to load firmware based on uevents issued.
Enabling this option will increase your kernel image size by about
13436 bytes.
If you are unsure about this, say N here, unless you are Linux
distribution and need to support the above two drivers, or you are
certain you need to support some really custom firmware loading
facility in userspace.
config FW_LOADER_USER_HELPER_FALLBACK
bool "Force the firmware sysfs fallback mechanism when possible"
depends on FW_LOADER_USER_HELPER
help
Enabling this option forces a sysfs userspace fallback mechanism
to be used for all firmware requests which explicitly do not disable a
a fallback mechanism. Firmware calls which do prohibit a fallback
mechanism is request_firmware_direct(). This option is kept for
backward compatibility purposes given this precise mechanism can also
be enabled by setting the proc sysctl value to true:
/proc/sys/kernel/firmware_config/force_sysfs_fallback
If you are unsure about this, say N here.
endif # FW_LOADER
endmenu
...@@ -125,7 +125,7 @@ static ssize_t timeout_show(struct class *class, struct class_attribute *attr, ...@@ -125,7 +125,7 @@ static ssize_t timeout_show(struct class *class, struct class_attribute *attr,
} }
/** /**
* firmware_timeout_store - set number of seconds to wait for firmware * firmware_timeout_store() - set number of seconds to wait for firmware
* @class: device class pointer * @class: device class pointer
* @attr: device attribute pointer * @attr: device attribute pointer
* @buf: buffer to scan for timeout value * @buf: buffer to scan for timeout value
...@@ -239,7 +239,7 @@ static int map_fw_priv_pages(struct fw_priv *fw_priv) ...@@ -239,7 +239,7 @@ static int map_fw_priv_pages(struct fw_priv *fw_priv)
} }
/** /**
* firmware_loading_store - set value in the 'loading' control file * firmware_loading_store() - set value in the 'loading' control file
* @dev: device pointer * @dev: device pointer
* @attr: device attribute pointer * @attr: device attribute pointer
* @buf: buffer to scan for loading control value * @buf: buffer to scan for loading control value
...@@ -431,7 +431,7 @@ static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size) ...@@ -431,7 +431,7 @@ static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size)
} }
/** /**
* firmware_data_write - write method for firmware * firmware_data_write() - write method for firmware
* @filp: open sysfs file * @filp: open sysfs file
* @kobj: kobject for the device * @kobj: kobject for the device
* @bin_attr: bin_attr structure * @bin_attr: bin_attr structure
...@@ -512,7 +512,7 @@ static const struct attribute_group *fw_dev_attr_groups[] = { ...@@ -512,7 +512,7 @@ static const struct attribute_group *fw_dev_attr_groups[] = {
static struct fw_sysfs * static struct fw_sysfs *
fw_create_instance(struct firmware *firmware, const char *fw_name, fw_create_instance(struct firmware *firmware, const char *fw_name,
struct device *device, unsigned int opt_flags) struct device *device, enum fw_opt opt_flags)
{ {
struct fw_sysfs *fw_sysfs; struct fw_sysfs *fw_sysfs;
struct device *f_dev; struct device *f_dev;
...@@ -537,7 +537,7 @@ fw_create_instance(struct firmware *firmware, const char *fw_name, ...@@ -537,7 +537,7 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
} }
/** /**
* fw_load_sysfs_fallback - load a firmware via the sysfs fallback mechanism * fw_load_sysfs_fallback() - load a firmware via the sysfs fallback mechanism
* @fw_sysfs: firmware sysfs information for the firmware to load * @fw_sysfs: firmware sysfs information for the firmware to load
* @opt_flags: flags of options, FW_OPT_* * @opt_flags: flags of options, FW_OPT_*
* @timeout: timeout to wait for the load * @timeout: timeout to wait for the load
...@@ -545,7 +545,7 @@ fw_create_instance(struct firmware *firmware, const char *fw_name, ...@@ -545,7 +545,7 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
* In charge of constructing a sysfs fallback interface for firmware loading. * In charge of constructing a sysfs fallback interface for firmware loading.
**/ **/
static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs,
unsigned int opt_flags, long timeout) enum fw_opt opt_flags, long timeout)
{ {
int retval = 0; int retval = 0;
struct device *f_dev = &fw_sysfs->dev; struct device *f_dev = &fw_sysfs->dev;
...@@ -599,7 +599,7 @@ static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, ...@@ -599,7 +599,7 @@ static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs,
static int fw_load_from_user_helper(struct firmware *firmware, static int fw_load_from_user_helper(struct firmware *firmware,
const char *name, struct device *device, const char *name, struct device *device,
unsigned int opt_flags) enum fw_opt opt_flags)
{ {
struct fw_sysfs *fw_sysfs; struct fw_sysfs *fw_sysfs;
long timeout; long timeout;
...@@ -640,7 +640,7 @@ static int fw_load_from_user_helper(struct firmware *firmware, ...@@ -640,7 +640,7 @@ static int fw_load_from_user_helper(struct firmware *firmware,
return ret; return ret;
} }
static bool fw_force_sysfs_fallback(unsigned int opt_flags) static bool fw_force_sysfs_fallback(enum fw_opt opt_flags)
{ {
if (fw_fallback_config.force_sysfs_fallback) if (fw_fallback_config.force_sysfs_fallback)
return true; return true;
...@@ -649,7 +649,7 @@ static bool fw_force_sysfs_fallback(unsigned int opt_flags) ...@@ -649,7 +649,7 @@ static bool fw_force_sysfs_fallback(unsigned int opt_flags)
return true; return true;
} }
static bool fw_run_sysfs_fallback(unsigned int opt_flags) static bool fw_run_sysfs_fallback(enum fw_opt opt_flags)
{ {
if (fw_fallback_config.ignore_sysfs_fallback) { if (fw_fallback_config.ignore_sysfs_fallback) {
pr_info_once("Ignoring firmware sysfs fallback due to sysctl knob\n"); pr_info_once("Ignoring firmware sysfs fallback due to sysctl knob\n");
...@@ -662,14 +662,39 @@ static bool fw_run_sysfs_fallback(unsigned int opt_flags) ...@@ -662,14 +662,39 @@ static bool fw_run_sysfs_fallback(unsigned int opt_flags)
return fw_force_sysfs_fallback(opt_flags); return fw_force_sysfs_fallback(opt_flags);
} }
int fw_sysfs_fallback(struct firmware *fw, const char *name, /**
* firmware_fallback_sysfs() - use the fallback mechanism to find firmware
* @fw: pointer to firmware image
* @name: name of firmware file to look for
* @device: device for which firmware is being loaded
* @opt_flags: options to control firmware loading behaviour
* @ret: return value from direct lookup which triggered the fallback mechanism
*
* This function is called if direct lookup for the firmware failed, it enables
* a fallback mechanism through userspace by exposing a sysfs loading
* interface. Userspace is in charge of loading the firmware through the syfs
* loading interface. This syfs fallback mechanism may be disabled completely
* on a system by setting the proc sysctl value ignore_sysfs_fallback to true.
* If this false we check if the internal API caller set the @FW_OPT_NOFALLBACK
* flag, if so it would also disable the fallback mechanism. A system may want
* to enfoce the sysfs fallback mechanism at all times, it can do this by
* setting ignore_sysfs_fallback to false and force_sysfs_fallback to true.
* Enabling force_sysfs_fallback is functionally equivalent to build a kernel
* with CONFIG_FW_LOADER_USER_HELPER_FALLBACK.
**/
int firmware_fallback_sysfs(struct firmware *fw, const char *name,
struct device *device, struct device *device,
unsigned int opt_flags, enum fw_opt opt_flags,
int ret) int ret)
{ {
if (!fw_run_sysfs_fallback(opt_flags)) if (!fw_run_sysfs_fallback(opt_flags))
return ret; return ret;
dev_warn(device, "Falling back to user helper\n"); if (!(opt_flags & FW_OPT_NO_WARN))
dev_warn(device, "Falling back to syfs fallback for: %s\n",
name);
else
dev_dbg(device, "Falling back to sysfs fallback for: %s\n",
name);
return fw_load_from_user_helper(fw, name, device, opt_flags); return fw_load_from_user_helper(fw, name, device, opt_flags);
} }
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/device.h> #include <linux/device.h>
#include "firmware.h"
/** /**
* struct firmware_fallback_config - firmware fallback configuration settings * struct firmware_fallback_config - firmware fallback configuration settings
* *
...@@ -29,9 +31,9 @@ struct firmware_fallback_config { ...@@ -29,9 +31,9 @@ struct firmware_fallback_config {
}; };
#ifdef CONFIG_FW_LOADER_USER_HELPER #ifdef CONFIG_FW_LOADER_USER_HELPER
int fw_sysfs_fallback(struct firmware *fw, const char *name, int firmware_fallback_sysfs(struct firmware *fw, const char *name,
struct device *device, struct device *device,
unsigned int opt_flags, enum fw_opt opt_flags,
int ret); int ret);
void kill_pending_fw_fallback_reqs(bool only_kill_custom); void kill_pending_fw_fallback_reqs(bool only_kill_custom);
...@@ -41,9 +43,9 @@ void fw_fallback_set_default_timeout(void); ...@@ -41,9 +43,9 @@ void fw_fallback_set_default_timeout(void);
int register_sysfs_loader(void); int register_sysfs_loader(void);
void unregister_sysfs_loader(void); void unregister_sysfs_loader(void);
#else /* CONFIG_FW_LOADER_USER_HELPER */ #else /* CONFIG_FW_LOADER_USER_HELPER */
static inline int fw_sysfs_fallback(struct firmware *fw, const char *name, static inline int firmware_fallback_sysfs(struct firmware *fw, const char *name,
struct device *device, struct device *device,
unsigned int opt_flags, enum fw_opt opt_flags,
int ret) int ret)
{ {
/* Keep carrying over the same error */ /* Keep carrying over the same error */
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#ifndef __FIRMWARE_LOADER_H #ifndef __FIRMWARE_LOADER_H
#define __FIRMWARE_LOADER_H #define __FIRMWARE_LOADER_H
#include <linux/bitops.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kref.h> #include <linux/kref.h>
...@@ -10,13 +11,33 @@ ...@@ -10,13 +11,33 @@
#include <generated/utsrelease.h> #include <generated/utsrelease.h>
/* firmware behavior options */ /**
#define FW_OPT_UEVENT (1U << 0) * enum fw_opt - options to control firmware loading behaviour
#define FW_OPT_NOWAIT (1U << 1) *
#define FW_OPT_USERHELPER (1U << 2) * @FW_OPT_UEVENT: Enables the fallback mechanism to send a kobject uevent
#define FW_OPT_NO_WARN (1U << 3) * when the firmware is not found. Userspace is in charge to load the
#define FW_OPT_NOCACHE (1U << 4) * firmware using the sysfs loading facility.
#define FW_OPT_NOFALLBACK (1U << 5) * @FW_OPT_NOWAIT: Used to describe the firmware request is asynchronous.
* @FW_OPT_USERHELPER: Enable the fallback mechanism, in case the direct
* filesystem lookup fails at finding the firmware. For details refer to
* firmware_fallback_sysfs().
* @FW_OPT_NO_WARN: Quiet, avoid printing warning messages.
* @FW_OPT_NOCACHE: Disables firmware caching. Firmware caching is used to
* cache the firmware upon suspend, so that upon resume races against the
* firmware file lookup on storage is avoided. Used for calls where the
* file may be too big, or where the driver takes charge of its own
* firmware caching mechanism.
* @FW_OPT_NOFALLBACK: Disable the fallback mechanism. Takes precedence over
* &FW_OPT_UEVENT and &FW_OPT_USERHELPER.
*/
enum fw_opt {
FW_OPT_UEVENT = BIT(0),
FW_OPT_NOWAIT = BIT(1),
FW_OPT_USERHELPER = BIT(2),
FW_OPT_NO_WARN = BIT(3),
FW_OPT_NOCACHE = BIT(4),
FW_OPT_NOFALLBACK = BIT(5),
};
enum fw_status { enum fw_status {
FW_STATUS_UNKNOWN, FW_STATUS_UNKNOWN,
...@@ -110,6 +131,6 @@ static inline void fw_state_done(struct fw_priv *fw_priv) ...@@ -110,6 +131,6 @@ static inline void fw_state_done(struct fw_priv *fw_priv)
} }
int assign_fw(struct firmware *fw, struct device *device, int assign_fw(struct firmware *fw, struct device *device,
unsigned int opt_flags); enum fw_opt opt_flags);
#endif /* __FIRMWARE_LOADER_H */ #endif /* __FIRMWARE_LOADER_H */
...@@ -443,7 +443,7 @@ static int fw_add_devm_name(struct device *dev, const char *name) ...@@ -443,7 +443,7 @@ static int fw_add_devm_name(struct device *dev, const char *name)
#endif #endif
int assign_fw(struct firmware *fw, struct device *device, int assign_fw(struct firmware *fw, struct device *device,
unsigned int opt_flags) enum fw_opt opt_flags)
{ {
struct fw_priv *fw_priv = fw->priv; struct fw_priv *fw_priv = fw->priv;
int ret; int ret;
...@@ -558,7 +558,7 @@ static void fw_abort_batch_reqs(struct firmware *fw) ...@@ -558,7 +558,7 @@ static void fw_abort_batch_reqs(struct firmware *fw)
static int static int
_request_firmware(const struct firmware **firmware_p, const char *name, _request_firmware(const struct firmware **firmware_p, const char *name,
struct device *device, void *buf, size_t size, struct device *device, void *buf, size_t size,
unsigned int opt_flags) enum fw_opt opt_flags)
{ {
struct firmware *fw = NULL; struct firmware *fw = NULL;
int ret; int ret;
...@@ -581,7 +581,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name, ...@@ -581,7 +581,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
dev_warn(device, dev_warn(device,
"Direct firmware load for %s failed with error %d\n", "Direct firmware load for %s failed with error %d\n",
name, ret); name, ret);
ret = fw_sysfs_fallback(fw, name, device, opt_flags, ret); ret = firmware_fallback_sysfs(fw, name, device, opt_flags, ret);
} else } else
ret = assign_fw(fw, device, opt_flags); ret = assign_fw(fw, device, opt_flags);
...@@ -597,7 +597,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name, ...@@ -597,7 +597,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
} }
/** /**
* request_firmware: - send firmware request and wait for it * request_firmware() - send firmware request and wait for it
* @firmware_p: pointer to firmware image * @firmware_p: pointer to firmware image
* @name: name of firmware file * @name: name of firmware file
* @device: device for which firmware is being loaded * @device: device for which firmware is being loaded
...@@ -632,7 +632,34 @@ request_firmware(const struct firmware **firmware_p, const char *name, ...@@ -632,7 +632,34 @@ request_firmware(const struct firmware **firmware_p, const char *name,
EXPORT_SYMBOL(request_firmware); EXPORT_SYMBOL(request_firmware);
/** /**
* request_firmware_direct: - load firmware directly without usermode helper * firmware_request_nowarn() - request for an optional fw module
* @firmware: pointer to firmware image
* @name: name of firmware file
* @device: device for which firmware is being loaded
*
* This function is similar in behaviour to request_firmware(), except
* it doesn't produce warning messages when the file is not found.
* The sysfs fallback mechanism is enabled if direct filesystem lookup fails,
* however, however failures to find the firmware file with it are still
* suppressed. It is therefore up to the driver to check for the return value
* of this call and to decide when to inform the users of errors.
**/
int firmware_request_nowarn(const struct firmware **firmware, const char *name,
struct device *device)
{
int ret;
/* Need to pin this module until return */
__module_get(THIS_MODULE);
ret = _request_firmware(firmware, name, device, NULL, 0,
FW_OPT_UEVENT | FW_OPT_NO_WARN);
module_put(THIS_MODULE);
return ret;
}
EXPORT_SYMBOL_GPL(firmware_request_nowarn);
/**
* request_firmware_direct() - load firmware directly without usermode helper
* @firmware_p: pointer to firmware image * @firmware_p: pointer to firmware image
* @name: name of firmware file * @name: name of firmware file
* @device: device for which firmware is being loaded * @device: device for which firmware is being loaded
...@@ -657,7 +684,7 @@ int request_firmware_direct(const struct firmware **firmware_p, ...@@ -657,7 +684,7 @@ int request_firmware_direct(const struct firmware **firmware_p,
EXPORT_SYMBOL_GPL(request_firmware_direct); EXPORT_SYMBOL_GPL(request_firmware_direct);
/** /**
* firmware_request_cache: - cache firmware for suspend so resume can use it * firmware_request_cache() - cache firmware for suspend so resume can use it
* @name: name of firmware file * @name: name of firmware file
* @device: device for which firmware should be cached for * @device: device for which firmware should be cached for
* *
...@@ -681,7 +708,7 @@ int firmware_request_cache(struct device *device, const char *name) ...@@ -681,7 +708,7 @@ int firmware_request_cache(struct device *device, const char *name)
EXPORT_SYMBOL_GPL(firmware_request_cache); EXPORT_SYMBOL_GPL(firmware_request_cache);
/** /**
* request_firmware_into_buf - load firmware into a previously allocated buffer * request_firmware_into_buf() - load firmware into a previously allocated buffer
* @firmware_p: pointer to firmware image * @firmware_p: pointer to firmware image
* @name: name of firmware file * @name: name of firmware file
* @device: device for which firmware is being loaded and DMA region allocated * @device: device for which firmware is being loaded and DMA region allocated
...@@ -713,7 +740,7 @@ request_firmware_into_buf(const struct firmware **firmware_p, const char *name, ...@@ -713,7 +740,7 @@ request_firmware_into_buf(const struct firmware **firmware_p, const char *name,
EXPORT_SYMBOL(request_firmware_into_buf); EXPORT_SYMBOL(request_firmware_into_buf);
/** /**
* release_firmware: - release the resource associated with a firmware image * release_firmware() - release the resource associated with a firmware image
* @fw: firmware resource to release * @fw: firmware resource to release
**/ **/
void release_firmware(const struct firmware *fw) void release_firmware(const struct firmware *fw)
...@@ -734,7 +761,7 @@ struct firmware_work { ...@@ -734,7 +761,7 @@ struct firmware_work {
struct device *device; struct device *device;
void *context; void *context;
void (*cont)(const struct firmware *fw, void *context); void (*cont)(const struct firmware *fw, void *context);
unsigned int opt_flags; enum fw_opt opt_flags;
}; };
static void request_firmware_work_func(struct work_struct *work) static void request_firmware_work_func(struct work_struct *work)
...@@ -755,7 +782,7 @@ static void request_firmware_work_func(struct work_struct *work) ...@@ -755,7 +782,7 @@ static void request_firmware_work_func(struct work_struct *work)
} }
/** /**
* request_firmware_nowait - asynchronous version of request_firmware * request_firmware_nowait() - asynchronous version of request_firmware
* @module: module requesting the firmware * @module: module requesting the firmware
* @uevent: sends uevent to copy the firmware image if this flag * @uevent: sends uevent to copy the firmware image if this flag
* is non-zero else the firmware copy must be done manually. * is non-zero else the firmware copy must be done manually.
...@@ -824,7 +851,7 @@ EXPORT_SYMBOL(request_firmware_nowait); ...@@ -824,7 +851,7 @@ EXPORT_SYMBOL(request_firmware_nowait);
static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
/** /**
* cache_firmware - cache one firmware image in kernel memory space * cache_firmware() - cache one firmware image in kernel memory space
* @fw_name: the firmware image name * @fw_name: the firmware image name
* *
* Cache firmware in kernel memory so that drivers can use it when * Cache firmware in kernel memory so that drivers can use it when
...@@ -866,7 +893,7 @@ static struct fw_priv *lookup_fw_priv(const char *fw_name) ...@@ -866,7 +893,7 @@ static struct fw_priv *lookup_fw_priv(const char *fw_name)
} }
/** /**
* uncache_firmware - remove one cached firmware image * uncache_firmware() - remove one cached firmware image
* @fw_name: the firmware image name * @fw_name: the firmware image name
* *
* Uncache one firmware image which has been cached successfully * Uncache one firmware image which has been cached successfully
...@@ -1042,7 +1069,7 @@ static void __device_uncache_fw_images(void) ...@@ -1042,7 +1069,7 @@ static void __device_uncache_fw_images(void)
} }
/** /**
* device_cache_fw_images - cache devices' firmware * device_cache_fw_images() - cache devices' firmware
* *
* If one device called request_firmware or its nowait version * If one device called request_firmware or its nowait version
* successfully before, the firmware names are recored into the * successfully before, the firmware names are recored into the
...@@ -1075,7 +1102,7 @@ static void device_cache_fw_images(void) ...@@ -1075,7 +1102,7 @@ static void device_cache_fw_images(void)
} }
/** /**
* device_uncache_fw_images - uncache devices' firmware * device_uncache_fw_images() - uncache devices' firmware
* *
* uncache all firmwares which have been cached successfully * uncache all firmwares which have been cached successfully
* by device_uncache_fw_images earlier * by device_uncache_fw_images earlier
...@@ -1092,7 +1119,7 @@ static void device_uncache_fw_images_work(struct work_struct *work) ...@@ -1092,7 +1119,7 @@ static void device_uncache_fw_images_work(struct work_struct *work)
} }
/** /**
* device_uncache_fw_images_delay - uncache devices firmwares * device_uncache_fw_images_delay() - uncache devices firmwares
* @delay: number of milliseconds to delay uncache device firmwares * @delay: number of milliseconds to delay uncache device firmwares
* *
* uncache all devices's firmwares which has been cached successfully * uncache all devices's firmwares which has been cached successfully
......
...@@ -649,13 +649,19 @@ static const struct attribute_group *memory_memblk_attr_groups[] = { ...@@ -649,13 +649,19 @@ static const struct attribute_group *memory_memblk_attr_groups[] = {
static static
int register_memory(struct memory_block *memory) int register_memory(struct memory_block *memory)
{ {
int ret;
memory->dev.bus = &memory_subsys; memory->dev.bus = &memory_subsys;
memory->dev.id = memory->start_section_nr / sections_per_block; memory->dev.id = memory->start_section_nr / sections_per_block;
memory->dev.release = memory_block_release; memory->dev.release = memory_block_release;
memory->dev.groups = memory_memblk_attr_groups; memory->dev.groups = memory_memblk_attr_groups;
memory->dev.offline = memory->state == MEM_OFFLINE; memory->dev.offline = memory->state == MEM_OFFLINE;
return device_register(&memory->dev); ret = device_register(&memory->dev);
if (ret)
put_device(&memory->dev);
return ret;
} }
static int init_memory_block(struct memory_block **memory, static int init_memory_block(struct memory_block **memory,
......
...@@ -653,7 +653,7 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar, ...@@ -653,7 +653,7 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar,
dir = "."; dir = ".";
snprintf(filename, sizeof(filename), "%s/%s", dir, file); snprintf(filename, sizeof(filename), "%s/%s", dir, file);
ret = request_firmware(&fw, filename, ar->dev); ret = firmware_request_nowarn(&fw, filename, ar->dev);
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n", ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n",
filename, ret); filename, ret);
......
...@@ -157,7 +157,7 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar, ...@@ -157,7 +157,7 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar,
ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
/* load utf firmware image */ /* load utf firmware image */
ret = request_firmware_direct(&fw_file->firmware, filename, ar->dev); ret = firmware_request_nowarn(&fw_file->firmware, filename, ar->dev);
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode fw request '%s': %d\n", ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode fw request '%s': %d\n",
filename, ret); filename, ret);
......
...@@ -1922,4 +1922,5 @@ struct bus_type usb_bus_type = { ...@@ -1922,4 +1922,5 @@ struct bus_type usb_bus_type = {
.name = "usb", .name = "usb",
.match = usb_device_match, .match = usb_device_match,
.uevent = usb_uevent, .uevent = usb_uevent,
.need_parent_lock = true,
}; };
...@@ -796,19 +796,13 @@ EXPORT_SYMBOL_GPL(debugfs_read_file_bool); ...@@ -796,19 +796,13 @@ EXPORT_SYMBOL_GPL(debugfs_read_file_bool);
ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf, ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
char buf[32];
size_t buf_size;
bool bv; bool bv;
int r; int r;
bool *val = file->private_data; bool *val = file->private_data;
struct dentry *dentry = F_DENTRY(file); struct dentry *dentry = F_DENTRY(file);
buf_size = min(count, (sizeof(buf)-1)); r = kstrtobool_from_user(user_buf, count, &bv);
if (copy_from_user(buf, user_buf, buf_size)) if (!r) {
return -EFAULT;
buf[buf_size] = '\0';
if (strtobool(buf, &bv) == 0) {
r = debugfs_file_get(dentry); r = debugfs_file_get(dentry);
if (unlikely(r)) if (unlikely(r))
return r; return r;
......
...@@ -512,7 +512,9 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) ...@@ -512,7 +512,9 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
if (unlikely(!inode)) if (unlikely(!inode))
return failed_creating(dentry); return failed_creating(dentry);
inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; if (!parent)
parent = debugfs_mount->mnt_root;
inode->i_mode = S_IFDIR | ((d_inode(parent)->i_mode & 0770));
inode->i_op = &simple_dir_inode_operations; inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations; inode->i_fop = &simple_dir_operations;
......
...@@ -348,11 +348,11 @@ static void kernfs_vma_open(struct vm_area_struct *vma) ...@@ -348,11 +348,11 @@ static void kernfs_vma_open(struct vm_area_struct *vma)
kernfs_put_active(of->kn); kernfs_put_active(of->kn);
} }
static int kernfs_vma_fault(struct vm_fault *vmf) static vm_fault_t kernfs_vma_fault(struct vm_fault *vmf)
{ {
struct file *file = vmf->vma->vm_file; struct file *file = vmf->vma->vm_file;
struct kernfs_open_file *of = kernfs_of(file); struct kernfs_open_file *of = kernfs_of(file);
int ret; vm_fault_t ret;
if (!of->vm_ops) if (!of->vm_ops)
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
...@@ -368,11 +368,11 @@ static int kernfs_vma_fault(struct vm_fault *vmf) ...@@ -368,11 +368,11 @@ static int kernfs_vma_fault(struct vm_fault *vmf)
return ret; return ret;
} }
static int kernfs_vma_page_mkwrite(struct vm_fault *vmf) static vm_fault_t kernfs_vma_page_mkwrite(struct vm_fault *vmf)
{ {
struct file *file = vmf->vma->vm_file; struct file *file = vmf->vma->vm_file;
struct kernfs_open_file *of = kernfs_of(file); struct kernfs_open_file *of = kernfs_of(file);
int ret; vm_fault_t ret;
if (!of->vm_ops) if (!of->vm_ops)
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
......
...@@ -98,6 +98,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); ...@@ -98,6 +98,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
* @p: The private data of the driver core, only the driver core can * @p: The private data of the driver core, only the driver core can
* touch this. * touch this.
* @lock_key: Lock class key for use by the lock validator * @lock_key: Lock class key for use by the lock validator
* @need_parent_lock: When probing or removing a device on this bus, the
* device core should lock the device's parent.
* *
* A bus is a channel between the processor and one or more devices. For the * A bus is a channel between the processor and one or more devices. For the
* purposes of the device model, all devices are connected via a bus, even if * purposes of the device model, all devices are connected via a bus, even if
...@@ -138,6 +140,8 @@ struct bus_type { ...@@ -138,6 +140,8 @@ struct bus_type {
struct subsys_private *p; struct subsys_private *p;
struct lock_class_key lock_key; struct lock_class_key lock_key;
bool need_parent_lock;
}; };
extern int __must_check bus_register(struct bus_type *bus); extern int __must_check bus_register(struct bus_type *bus);
......
...@@ -42,6 +42,8 @@ struct builtin_fw { ...@@ -42,6 +42,8 @@ struct builtin_fw {
#if defined(CONFIG_FW_LOADER) || (defined(CONFIG_FW_LOADER_MODULE) && defined(MODULE)) #if defined(CONFIG_FW_LOADER) || (defined(CONFIG_FW_LOADER_MODULE) && defined(MODULE))
int request_firmware(const struct firmware **fw, const char *name, int request_firmware(const struct firmware **fw, const char *name,
struct device *device); struct device *device);
int firmware_request_nowarn(const struct firmware **fw, const char *name,
struct device *device);
int request_firmware_nowait( int request_firmware_nowait(
struct module *module, bool uevent, struct module *module, bool uevent,
const char *name, struct device *device, gfp_t gfp, void *context, const char *name, struct device *device, gfp_t gfp, void *context,
...@@ -59,6 +61,14 @@ static inline int request_firmware(const struct firmware **fw, ...@@ -59,6 +61,14 @@ static inline int request_firmware(const struct firmware **fw,
{ {
return -EINVAL; return -EINVAL;
} }
static inline int firmware_request_nowarn(const struct firmware **fw,
const char *name,
struct device *device)
{
return -EINVAL;
}
static inline int request_firmware_nowait( static inline int request_firmware_nowait(
struct module *module, bool uevent, struct module *module, bool uevent,
const char *name, struct device *device, gfp_t gfp, void *context, const char *name, struct device *device, gfp_t gfp, void *context,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment