Commit 59838093 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull driver core updates from Greg KH:
 "Here is the "big" set of driver core changes for 5.7-rc1.

  Nothing huge in here, just lots of little firmware core changes and
  use of new apis, a libfs fix, a debugfs api change, and some driver
  core deferred probe rework.

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

* tag 'driver-core-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (44 commits)
  Revert "driver core: Set fw_devlink to "permissive" behavior by default"
  driver core: Set fw_devlink to "permissive" behavior by default
  driver core: Replace open-coded list_last_entry()
  driver core: Read atomic counter once in driver_probe_done()
  libfs: fix infoleak in simple_attr_read()
  driver core: Add device links from fwnode only for the primary device
  platform/x86: touchscreen_dmi: Add info for the Chuwi Vi8 Plus tablet
  platform/x86: touchscreen_dmi: Add EFI embedded firmware info support
  Input: icn8505 - Switch to firmware_request_platform for retreiving the fw
  Input: silead - Switch to firmware_request_platform for retreiving the fw
  selftests: firmware: Add firmware_request_platform tests
  test_firmware: add support for firmware_request_platform
  firmware: Add new platform fallback mechanism and firmware_request_platform()
  Revert "drivers: base: power: wakeup.c: Use built-in RCU list checking"
  drivers: base: power: wakeup.c: Use built-in RCU list checking
  component: allow missing unbind callback
  debugfs: remove return value of debugfs_create_file_size()
  debugfs: Check module state before warning in {full/open}_proxy_open()
  firmware: fix a double abort case with fw_load_sysfs_fallback
  arch_topology: Fix putting invalid cpu clk
  ...
parents db34c5ff 18555cb6
Loading
Loading
Loading
Loading
+18 −6
Original line number Diff line number Diff line
@@ -1360,6 +1360,24 @@
			can be changed at run time by the max_graph_depth file
			in the tracefs tracing directory. default: 0 (no limit)

	fw_devlink=	[KNL] Create device links between consumer and supplier
			devices by scanning the firmware to infer the
			consumer/supplier relationships. This feature is
			especially useful when drivers are loaded as modules as
			it ensures proper ordering of tasks like device probing
			(suppliers first, then consumers), supplier boot state
			clean up (only after all consumers have probed),
			suspend/resume & runtime PM (consumers first, then
			suppliers).
			Format: { off | permissive | on | rpm }
			off --	Don't create device links from firmware info.
			permissive -- Create device links from firmware info
				but use it only for ordering boot state clean
				up (sync_state() calls).
			on -- 	Create device links from firmware info and use it
				to enforce probe and suspend/resume ordering.
			rpm --	Like "on", but also use to order runtime PM.

	gamecon.map[2|3]=
			[HW,JOY] Multisystem joystick and NES/SNES/PSX pad
			support via parallel port (up to 5 devices per port)
@@ -3291,12 +3309,6 @@
			This can be set from sysctl after boot.
			See Documentation/admin-guide/sysctl/vm.rst for details.

	of_devlink	[OF, KNL] Create device links between consumer and
			supplier devices by scanning the devictree to infer the
			consumer/supplier relationships.  A consumer device
			will not be probed until all the supplier devices have
			probed successfully.

	ohci1394_dma=early	[HW] enable debugging via the ohci1394 driver.
			See Documentation/debugging-via-ohci1394.txt for more
			info.
+103 −0
Original line number Diff line number Diff line
@@ -202,3 +202,106 @@ the following file:

If you echo 0 into it means MAX_JIFFY_OFFSET will be used. The data type
for the timeout is an int.

EFI embedded firmware fallback mechanism
========================================

On some devices the system's EFI code / ROM may contain an embedded copy
of firmware for some of the system's integrated peripheral devices and
the peripheral's Linux device-driver needs to access this firmware.

Device drivers which need such firmware can use the
firmware_request_platform() function for this, note that this is a
separate fallback mechanism from the other fallback mechanisms and
this does not use the sysfs interface.

A device driver which needs this can describe the firmware it needs
using an efi_embedded_fw_desc struct:

.. kernel-doc:: include/linux/efi_embedded_fw.h
   :functions: efi_embedded_fw_desc

The EFI embedded-fw code works by scanning all EFI_BOOT_SERVICES_CODE memory
segments for an eight byte sequence matching prefix; if the prefix is found it
then does a sha256 over length bytes and if that matches makes a copy of length
bytes and adds that to its list with found firmwares.

To avoid doing this somewhat expensive scan on all systems, dmi matching is
used. Drivers are expected to export a dmi_system_id array, with each entries'
driver_data pointing to an efi_embedded_fw_desc.

To register this array with the efi-embedded-fw code, a driver needs to:

1. Always be builtin to the kernel or store the dmi_system_id array in a
   separate object file which always gets builtin.

2. Add an extern declaration for the dmi_system_id array to
   include/linux/efi_embedded_fw.h.

3. Add the dmi_system_id array to the embedded_fw_table in
   drivers/firmware/efi/embedded-firmware.c wrapped in a #ifdef testing that
   the driver is being builtin.

4. Add "select EFI_EMBEDDED_FIRMWARE if EFI_STUB" to its Kconfig entry.

The firmware_request_platform() function will always first try to load firmware
with the specified name directly from the disk, so the EFI embedded-fw can
always be overridden by placing a file under /lib/firmware.

Note that:

1. The code scanning for EFI embedded-firmware runs near the end
   of start_kernel(), just before calling rest_init(). For normal drivers and
   subsystems using subsys_initcall() to register themselves this does not
   matter. This means that code running earlier cannot use EFI
   embedded-firmware.

2. At the moment the EFI embedded-fw code assumes that firmwares always start at
   an offset which is a multiple of 8 bytes, if this is not true for your case
   send in a patch to fix this.

3. At the moment the EFI embedded-fw code only works on x86 because other archs
   free EFI_BOOT_SERVICES_CODE before the EFI embedded-fw code gets a chance to
   scan it.

4. The current brute-force scanning of EFI_BOOT_SERVICES_CODE is an ad-hoc
   brute-force solution. There has been discussion to use the UEFI Platform
   Initialization (PI) spec's Firmware Volume protocol. This has been rejected
   because the FV Protocol relies on *internal* interfaces of the PI spec, and:
   1. The PI spec does not define peripheral firmware at all
   2. The internal interfaces of the PI spec do not guarantee any backward
   compatibility. Any implementation details in FV may be subject to change,
   and may vary system to system. Supporting the FV Protocol would be
   difficult as it is purposely ambiguous.

Example how to check for and extract embedded firmware
------------------------------------------------------

To check for, for example Silead touchscreen controller embedded firmware,
do the following:

1. Boot the system with efi=debug on the kernel commandline

2. cp /sys/kernel/debug/efi/boot_services_code? to your home dir

3. Open the boot_services_code? files in a hex-editor, search for the
   magic prefix for Silead firmware: F0 00 00 00 02 00 00 00, this gives you
   the beginning address of the firmware inside the boot_services_code? file.

4. The firmware has a specific pattern, it starts with a 8 byte page-address,
   typically F0 00 00 00 02 00 00 00 for the first page followed by 32-bit
   word-address + 32-bit value pairs. With the word-address incrementing 4
   bytes (1 word) for each pair until a page is complete. A complete page is
   followed by a new page-address, followed by more word + value pairs. This
   leads to a very distinct pattern. Scroll down until this pattern stops,
   this gives you the end of the firmware inside the boot_services_code? file.

5. "dd if=boot_services_code? of=firmware bs=1 skip=<begin-addr> count=<len>"
   will extract the firmware for you. Inspect the firmware file in a
   hexeditor to make sure you got the dd parameters correct.

6. Copy it to /lib/firmware under the expected name to test it.

7. If the extracted firmware works, you can use the found info to fill an
   efi_embedded_fw_desc struct to describe it, run "sha256sum firmware"
   to get the sha256sum to put in the sha256 field.
+2 −0
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@ a driver issues a firmware API call.
  return it immediately
* The ''Direct filesystem lookup'' is performed next, if found we
  return it immediately
* The ''Platform firmware fallback'' is performed next, but only when
  firmware_request_platform() is used, if found we return it immediately
* If no firmware has been found and the fallback mechanism was enabled
  the sysfs interface is created. After this either a kobject uevent
  is issued or the custom firmware loading is relied upon for firmware
+5 −0
Original line number Diff line number Diff line
@@ -25,6 +25,11 @@ firmware_request_nowarn
.. kernel-doc:: drivers/base/firmware_loader/main.c
   :functions: firmware_request_nowarn

firmware_request_platform
-------------------------
.. kernel-doc:: drivers/base/firmware_loader/main.c
   :functions: firmware_request_platform

request_firmware_direct
-----------------------
.. kernel-doc:: drivers/base/firmware_loader/main.c
+4 −4
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ missing.
Create a file with an initial size, the following function can be used
instead::

    struct dentry *debugfs_create_file_size(const char *name, umode_t mode,
    void debugfs_create_file_size(const char *name, umode_t mode,
				  struct dentry *parent, void *data,
				  const struct file_operations *fops,
				  loff_t file_size);
Loading