Driver Core and debugfs changes for 5.3-rc1

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.  Because of this, there is going
 to be some merge issues with your tree at the moment, I'll follow up
 with the expected resolutions to make it easier for you.
 
 Other than the debugfs cleanups, in this set of changes we have:
 	- bus iteration function cleanups (will cause build warnings
 	  with s390 and coresight drivers in your tree)
 	- 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.  Other than the merge
 issues, functionality is working properly in linux-next :)
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXSgpnQ8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ykcwgCfS30OR4JmwZydWGJ7zK/cHqk+KjsAnjOxjC1K
 LpRyb3zX29oChFaZkc5a
 =XrEZ
 -----END PGP SIGNATURE-----

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
commit f632a8170a
201 changed files with 1929 additions and 2104 deletions

View File

@ -5,7 +5,7 @@ Description: It is possible to switch the cpi setting of the mouse with the
press of a button.
When read, this file returns the raw number of the actual cpi
setting reported by the mouse. This number has to be further
processed to receive the real dpi value.
processed to receive the real dpi value:
VALUE DPI
1 400

View File

@ -1,5 +1,4 @@
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
asic_health
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/asic_health
Date: June 2018
KernelVersion: 4.19
@ -9,9 +8,8 @@ Description: This file shows ASIC health status. The possible values are:
The files are read only.
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
cpld1_version
cpld2_version
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld1_version
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld2_version
Date: June 2018
KernelVersion: 4.19
Contact: Vadim Pasternak <vadimpmellanox.com>
@ -20,8 +18,7 @@ Description: These files show with which CPLD versions have been burned
The files are read only.
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
fan_dir
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/fan_dir
Date: December 2018
KernelVersion: 5.0
@ -32,8 +29,7 @@ Description: This file shows the system fans direction:
The files are read only.
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
jtag_enable
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/jtag_enable
Date: November 2018
KernelVersion: 5.0
@ -43,8 +39,7 @@ Description: These files show with which CPLD versions have been burned
The files are read only.
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
jtag_enable
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/jtag_enable
Date: November 2018
KernelVersion: 5.0
@ -87,16 +82,15 @@ Description: These files allow asserting system power cycling, switching
The files are write only.
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
reset_aux_pwr_or_ref
reset_asic_thermal
reset_hotswap_or_halt
reset_hotswap_or_wd
reset_fw_reset
reset_long_pb
reset_main_pwr_fail
reset_short_pb
reset_sw_reset
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_aux_pwr_or_ref
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_asic_thermal
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_hotswap_or_halt
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_hotswap_or_wd
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_fw_reset
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_long_pb
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_main_pwr_fail
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_short_pb
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_sw_reset
Date: June 2018
KernelVersion: 4.19
Contact: Vadim Pasternak <vadimpmellanox.com>
@ -110,11 +104,10 @@ Description: These files show the system reset cause, as following: power
The files are read only.
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
reset_comex_pwr_fail
reset_from_comex
reset_system
reset_voltmon_upgrade_fail
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_comex_pwr_fail
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_from_comex
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_system
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_voltmon_upgrade_fail
Date: November 2018
KernelVersion: 5.0

View File

@ -1,6 +1,6 @@
Where: /sys/fs/pstore/... (or /dev/pstore/...)
What: /sys/fs/pstore/... (or /dev/pstore/...)
Date: March 2011
Kernel Version: 2.6.39
KernelVersion: 2.6.39
Contact: tony.luck@intel.com
Description: Generic interface to platform dependent persistent storage.

View File

@ -1,6 +1,6 @@
Where: /sys/bus/event_source/devices/<dev>/format
What: /sys/bus/event_source/devices/<dev>/format
Date: January 2012
Kernel Version: 3.3
KernelVersion: 3.3
Contact: Jiri Olsa <jolsa@redhat.com>
Description:
Attribute group to describe the magic bits that go into

View File

@ -1,20 +1,20 @@
Where: /sys/bus/i2c/devices/.../heading0_input
What: /sys/bus/i2c/devices/.../heading0_input
Date: April 2010
Kernel Version: 2.6.36?
KernelVersion: 2.6.36?
Contact: alan.cox@intel.com
Description: Reports the current heading from the compass as a floating
point value in degrees.
Where: /sys/bus/i2c/devices/.../power_state
What: /sys/bus/i2c/devices/.../power_state
Date: April 2010
Kernel Version: 2.6.36?
KernelVersion: 2.6.36?
Contact: alan.cox@intel.com
Description: Sets the power state of the device. 0 sets the device into
sleep mode, 1 wakes it up.
Where: /sys/bus/i2c/devices/.../calibration
What: /sys/bus/i2c/devices/.../calibration
Date: April 2010
Kernel Version: 2.6.36?
KernelVersion: 2.6.36?
Contact: alan.cox@intel.com
Description: Sets the calibration on or off (1 = on, 0 = off). See the
chip data sheet.

View File

@ -1,4 +1,4 @@
What /sys/bus/iio/devices/iio:deviceX/sensor_sensitivity
What: /sys/bus/iio/devices/iio:deviceX/sensor_sensitivity
Date: January 2017
KernelVersion: 4.11
Contact: linux-iio@vger.kernel.org
@ -6,7 +6,7 @@ Description:
Show or set the gain boost of the amp, from 0-31 range.
default 31
What /sys/bus/iio/devices/iio:deviceX/sensor_max_range
What: /sys/bus/iio/devices/iio:deviceX/sensor_max_range
Date: January 2017
KernelVersion: 4.11
Contact: linux-iio@vger.kernel.org

View File

@ -1,4 +1,4 @@
What /sys/bus/iio/devices/iio:deviceX/in_proximity_input
What: /sys/bus/iio/devices/iio:deviceX/in_proximity_input
Date: March 2014
KernelVersion: 3.15
Contact: Matt Ranostay <matt.ranostay@konsulko.com>
@ -6,7 +6,7 @@ Description:
Get the current distance in meters of storm (1km steps)
1000-40000 = distance in meters
What /sys/bus/iio/devices/iio:deviceX/sensor_sensitivity
What: /sys/bus/iio/devices/iio:deviceX/sensor_sensitivity
Date: March 2014
KernelVersion: 3.15
Contact: Matt Ranostay <matt.ranostay@konsulko.com>

View File

@ -9,9 +9,9 @@ errors may be "seen" / reported by the link partner and not the
problematic endpoint itself (which may report all counters as 0 as it never
saw any problems).
Where: /sys/bus/pci/devices/<dev>/aer_dev_correctable
What: /sys/bus/pci/devices/<dev>/aer_dev_correctable
Date: July 2018
Kernel Version: 4.19.0
KernelVersion: 4.19.0
Contact: linux-pci@vger.kernel.org, rajatja@google.com
Description: List of correctable errors seen and reported by this
PCI device using ERR_COR. Note that since multiple errors may
@ -31,9 +31,9 @@ Header Log Overflow 0
TOTAL_ERR_COR 2
-------------------------------------------------------------------------
Where: /sys/bus/pci/devices/<dev>/aer_dev_fatal
What: /sys/bus/pci/devices/<dev>/aer_dev_fatal
Date: July 2018
Kernel Version: 4.19.0
KernelVersion: 4.19.0
Contact: linux-pci@vger.kernel.org, rajatja@google.com
Description: List of uncorrectable fatal errors seen and reported by this
PCI device using ERR_FATAL. Note that since multiple errors may
@ -62,9 +62,9 @@ TLP Prefix Blocked Error 0
TOTAL_ERR_FATAL 0
-------------------------------------------------------------------------
Where: /sys/bus/pci/devices/<dev>/aer_dev_nonfatal
What: /sys/bus/pci/devices/<dev>/aer_dev_nonfatal
Date: July 2018
Kernel Version: 4.19.0
KernelVersion: 4.19.0
Contact: linux-pci@vger.kernel.org, rajatja@google.com
Description: List of uncorrectable nonfatal errors seen and reported by this
PCI device using ERR_NONFATAL. Note that since multiple errors
@ -103,20 +103,20 @@ collectors) that are AER capable. These indicate the number of error messages as
device, so these counters include them and are thus cumulative of all the error
messages on the PCI hierarchy originating at that root port.
Where: /sys/bus/pci/devices/<dev>/aer_stats/aer_rootport_total_err_cor
What: /sys/bus/pci/devices/<dev>/aer_stats/aer_rootport_total_err_cor
Date: July 2018
Kernel Version: 4.19.0
KernelVersion: 4.19.0
Contact: linux-pci@vger.kernel.org, rajatja@google.com
Description: Total number of ERR_COR messages reported to rootport.
Where: /sys/bus/pci/devices/<dev>/aer_stats/aer_rootport_total_err_fatal
What: /sys/bus/pci/devices/<dev>/aer_stats/aer_rootport_total_err_fatal
Date: July 2018
Kernel Version: 4.19.0
KernelVersion: 4.19.0
Contact: linux-pci@vger.kernel.org, rajatja@google.com
Description: Total number of ERR_FATAL messages reported to rootport.
Where: /sys/bus/pci/devices/<dev>/aer_stats/aer_rootport_total_err_nonfatal
What: /sys/bus/pci/devices/<dev>/aer_stats/aer_rootport_total_err_nonfatal
Date: July 2018
Kernel Version: 4.19.0
KernelVersion: 4.19.0
Contact: linux-pci@vger.kernel.org, rajatja@google.com
Description: Total number of ERR_NONFATAL messages reported to rootport.

View File

@ -1,68 +1,68 @@
Where: /sys/bus/pci/devices/<dev>/ccissX/cXdY/model
What: /sys/bus/pci/devices/<dev>/ccissX/cXdY/model
Date: March 2009
Kernel Version: 2.6.30
KernelVersion: 2.6.30
Contact: iss_storagedev@hp.com
Description: Displays the SCSI INQUIRY page 0 model for logical drive
Y of controller X.
Where: /sys/bus/pci/devices/<dev>/ccissX/cXdY/rev
What: /sys/bus/pci/devices/<dev>/ccissX/cXdY/rev
Date: March 2009
Kernel Version: 2.6.30
KernelVersion: 2.6.30
Contact: iss_storagedev@hp.com
Description: Displays the SCSI INQUIRY page 0 revision for logical
drive Y of controller X.
Where: /sys/bus/pci/devices/<dev>/ccissX/cXdY/unique_id
What: /sys/bus/pci/devices/<dev>/ccissX/cXdY/unique_id
Date: March 2009
Kernel Version: 2.6.30
KernelVersion: 2.6.30
Contact: iss_storagedev@hp.com
Description: Displays the SCSI INQUIRY page 83 serial number for logical
drive Y of controller X.
Where: /sys/bus/pci/devices/<dev>/ccissX/cXdY/vendor
What: /sys/bus/pci/devices/<dev>/ccissX/cXdY/vendor
Date: March 2009
Kernel Version: 2.6.30
KernelVersion: 2.6.30
Contact: iss_storagedev@hp.com
Description: Displays the SCSI INQUIRY page 0 vendor for logical drive
Y of controller X.
Where: /sys/bus/pci/devices/<dev>/ccissX/cXdY/block:cciss!cXdY
What: /sys/bus/pci/devices/<dev>/ccissX/cXdY/block:cciss!cXdY
Date: March 2009
Kernel Version: 2.6.30
KernelVersion: 2.6.30
Contact: iss_storagedev@hp.com
Description: A symbolic link to /sys/block/cciss!cXdY
Where: /sys/bus/pci/devices/<dev>/ccissX/rescan
What: /sys/bus/pci/devices/<dev>/ccissX/rescan
Date: August 2009
Kernel Version: 2.6.31
KernelVersion: 2.6.31
Contact: iss_storagedev@hp.com
Description: Kicks of a rescan of the controller to discover logical
drive topology changes.
Where: /sys/bus/pci/devices/<dev>/ccissX/cXdY/lunid
What: /sys/bus/pci/devices/<dev>/ccissX/cXdY/lunid
Date: August 2009
Kernel Version: 2.6.31
KernelVersion: 2.6.31
Contact: iss_storagedev@hp.com
Description: Displays the 8-byte LUN ID used to address logical
drive Y of controller X.
Where: /sys/bus/pci/devices/<dev>/ccissX/cXdY/raid_level
What: /sys/bus/pci/devices/<dev>/ccissX/cXdY/raid_level
Date: August 2009
Kernel Version: 2.6.31
KernelVersion: 2.6.31
Contact: iss_storagedev@hp.com
Description: Displays the RAID level of logical drive Y of
controller X.
Where: /sys/bus/pci/devices/<dev>/ccissX/cXdY/usage_count
What: /sys/bus/pci/devices/<dev>/ccissX/cXdY/usage_count
Date: August 2009
Kernel Version: 2.6.31
KernelVersion: 2.6.31
Contact: iss_storagedev@hp.com
Description: Displays the usage count (number of opens) of logical drive Y
of controller X.
Where: /sys/bus/pci/devices/<dev>/ccissX/resettable
What: /sys/bus/pci/devices/<dev>/ccissX/resettable
Date: February 2011
Kernel Version: 2.6.38
KernelVersion: 2.6.38
Contact: iss_storagedev@hp.com
Description: Value of 1 indicates the controller can honor the reset_devices
kernel parameter. Value of 0 indicates reset_devices cannot be
@ -71,9 +71,9 @@ Description: Value of 1 indicates the controller can honor the reset_devices
a dump device, as kdump requires resetting the device in order
to work reliably.
Where: /sys/bus/pci/devices/<dev>/ccissX/transport_mode
What: /sys/bus/pci/devices/<dev>/ccissX/transport_mode
Date: July 2011
Kernel Version: 3.0
KernelVersion: 3.0
Contact: iss_storagedev@hp.com
Description: Value of "simple" indicates that the controller has been placed
in "simple mode". Value of "performant" indicates that the

View File

@ -1,14 +1,14 @@
Where: /sys/bus/usb/.../powered
What: /sys/bus/usb/.../powered
Date: August 2008
Kernel Version: 2.6.26
KernelVersion: 2.6.26
Contact: Harrison Metzger <harrisonmetz@gmail.com>
Description: Controls whether the device's display will powered.
A value of 0 is off and a non-zero value is on.
Where: /sys/bus/usb/.../mode_msb
Where: /sys/bus/usb/.../mode_lsb
What: /sys/bus/usb/.../mode_msb
What: /sys/bus/usb/.../mode_lsb
Date: August 2008
Kernel Version: 2.6.26
KernelVersion: 2.6.26
Contact: Harrison Metzger <harrisonmetz@gmail.com>
Description: Controls the devices display mode.
For a 6 character display the values are
@ -16,24 +16,24 @@ Description: Controls the devices display mode.
for an 8 character display the values are
MSB 0x08; LSB 0xFF.
Where: /sys/bus/usb/.../textmode
What: /sys/bus/usb/.../textmode
Date: August 2008
Kernel Version: 2.6.26
KernelVersion: 2.6.26
Contact: Harrison Metzger <harrisonmetz@gmail.com>
Description: Controls the way the device interprets its text buffer.
raw: each character controls its segment manually
hex: each character is between 0-15
ascii: each character is between '0'-'9' and 'A'-'F'.
Where: /sys/bus/usb/.../text
What: /sys/bus/usb/.../text
Date: August 2008
Kernel Version: 2.6.26
KernelVersion: 2.6.26
Contact: Harrison Metzger <harrisonmetz@gmail.com>
Description: The text (or data) for the device to display
Where: /sys/bus/usb/.../decimals
What: /sys/bus/usb/.../decimals
Date: August 2008
Kernel Version: 2.6.26
KernelVersion: 2.6.26
Contact: Harrison Metzger <harrisonmetz@gmail.com>
Description: Controls the decimal places on the device.
To set the nth decimal place, give this field

View File

@ -4,7 +4,7 @@ KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Get the ALS output channel used as input in
ALS-current-control mode (0, 1), where
ALS-current-control mode (0, 1), where:
0 - out_current0 (backlight 0)
1 - out_current1 (backlight 1)
@ -28,7 +28,7 @@ Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the brightness-mapping mode (0, 1), where
Set the brightness-mapping mode (0, 1), where:
0 - exponential mode
1 - linear mode
@ -38,7 +38,7 @@ Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the PWM-input control mask (5 bits), where
Set the PWM-input control mask (5 bits), where:
bit 5 - PWM-input enabled in Zone 4
bit 4 - PWM-input enabled in Zone 3

View File

@ -1,6 +1,6 @@
Note: Attributes that are shared between devices are stored in the directory
pointed to by the symlink device/.
Example: The real path of the attribute /sys/class/cxl/afu0.0s/irqs_max is
Please note that attributes that are shared between devices are stored in
the directory pointed to by the symlink device/.
For example, the real path of the attribute /sys/class/cxl/afu0.0s/irqs_max is
/sys/class/cxl/afu0.0s/device/irqs_max, i.e. /sys/class/cxl/afu0.0/irqs_max.

View File

@ -47,7 +47,7 @@ Description:
What: /sys/class/devfreq/.../trans_stat
Date: October 2012
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
Descrtiption:
Description:
This ABI shows the statistics of devfreq behavior on a
specific device. It shows the time spent in each state and
the number of transitions between states.

View File

@ -4,7 +4,7 @@ KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the ALS output channel to use as input in
ALS-current-control mode (1, 2), where
ALS-current-control mode (1, 2), where:
1 - out_current1
2 - out_current2
@ -22,7 +22,7 @@ Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the pattern generator fall and rise times (0..7), where
Set the pattern generator fall and rise times (0..7), where:
0 - 2048 us
1 - 262 ms
@ -45,7 +45,7 @@ Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the brightness-mapping mode (0, 1), where
Set the brightness-mapping mode (0, 1), where:
0 - exponential mode
1 - linear mode
@ -55,7 +55,7 @@ Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the PWM-input control mask (5 bits), where
Set the PWM-input control mask (5 bits), where:
bit 5 - PWM-input enabled in Zone 4
bit 4 - PWM-input enabled in Zone 3

View File

@ -5,7 +5,7 @@ Contact: Janne Kanniainen <janne.kanniainen@gmail.com>
Description:
Set the mode of LEDs. You should notice that changing the mode
of one LED will update the mode of its two sibling devices as
well.
well. Possible values are:
0 - normal
1 - audio
@ -13,4 +13,4 @@ Description:
Normal: LEDs are fully on when enabled
Audio: LEDs brightness depends on sound level
Breathing: LEDs brightness varies at human breathing rate
Breathing: LEDs brightness varies at human breathing rate

View File

@ -147,6 +147,6 @@ What: /sys/class/powercap/.../<power zone>/enabled
Date: September 2013
KernelVersion: 3.13
Contact: linux-pm@vger.kernel.org
Description
Description:
This allows to enable/disable power capping at power zone level.
This applies to current power zone and its children.

View File

@ -125,12 +125,6 @@ Description:
The EUI-48 of this device in colon separated hex
octets.
What: /sys/class/uwb_rc/uwbN/<EUI-48>/BPST
Date: July 2008
KernelVersion: 2.6.27
Contact: linux-usb@vger.kernel.org
Description:
What: /sys/class/uwb_rc/uwbN/<EUI-48>/IEs
Date: July 2008
KernelVersion: 2.6.27

View File

@ -1,6 +1,6 @@
What: /sys/bus/pci/drivers/altera-cvp/chkcfg
Date: May 2017
Kernel Version: 4.13
KernelVersion: 4.13
Contact: Anatolij Gustschin <agust@denx.de>
Description:
Contains either 1 or 0 and controls if configuration

View File

@ -1,6 +1,6 @@
What: For USB devices : /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/report_descriptor
For BT devices : /sys/class/bluetooth/hci<addr>/<hid-bus>:<vendor-id>:<product-id>.<num>/report_descriptor
Symlink : /sys/class/hidraw/hidraw<num>/device/report_descriptor
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/report_descriptor
What: /sys/class/bluetooth/hci<addr>/<hid-bus>:<vendor-id>:<product-id>.<num>/report_descriptor
What: /sys/class/hidraw/hidraw<num>/device/report_descriptor
Date: Jan 2011
KernelVersion: 2.0.39
Contact: Alan Ott <alan@signal11.us>
@ -9,9 +9,9 @@ Description: When read, this file returns the device's raw binary HID
This file cannot be written.
Users: HIDAPI library (http://www.signal11.us/oss/hidapi)
What: For USB devices : /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/country
For BT devices : /sys/class/bluetooth/hci<addr>/<hid-bus>:<vendor-id>:<product-id>.<num>/country
Symlink : /sys/class/hidraw/hidraw<num>/device/country
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/country
What: /sys/class/bluetooth/hci<addr>/<hid-bus>:<vendor-id>:<product-id>.<num>/country
What: /sys/class/hidraw/hidraw<num>/device/country
Date: February 2015
KernelVersion: 3.19
Contact: Olivier Gay <ogay@logitech.com>

View File

@ -5,7 +5,7 @@ Description: It is possible to switch the dpi setting of the mouse with the
press of a button.
When read, this file returns the raw number of the actual dpi
setting reported by the mouse. This number has to be further
processed to receive the real dpi value.
processed to receive the real dpi value:
VALUE DPI
1 800

View File

@ -1,6 +1,6 @@
What: /sys/class/tpm/tpmX/ppi/
Date: August 2012
Kernel Version: 3.6
KernelVersion: 3.6
Contact: xiaoyan.zhang@intel.com
Description:
This folder includes the attributes related with PPI (Physical

View File

@ -1,6 +1,6 @@
What: /sys/bus/scsi/drivers/st/debug_flag
Date: October 2015
Kernel Version: ?.?
KernelVersion: ?.?
Contact: shane.seymour@hpe.com
Description:
This file allows you to turn debug output from the st driver

View File

@ -1,6 +1,6 @@
What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/speed
Date: April 2010
Kernel Version: 2.6.35
KernelVersion: 2.6.35
Contact: linux-bluetooth@vger.kernel.org
Description:
The /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/speed file

View File

@ -2,7 +2,7 @@ What: /sys/kernel/fscaps
Date: February 2011
KernelVersion: 2.6.38
Contact: Ludwig Nussel <ludwig.nussel@suse.de>
Description
Description:
Shows whether file system capabilities are honored
when executing a binary

View File

@ -4,7 +4,7 @@ KernelVersion: 2.6.24
Contact: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
Kexec Mailing List <kexec@lists.infradead.org>
Vivek Goyal <vgoyal@redhat.com>
Description
Description:
Shows physical address and size of vmcoreinfo ELF note.
First value contains physical address of note in hex and
second value contains the size of note in hex. This ELF

View File

@ -399,7 +399,7 @@ symbol:
will pass the struct gpio_chip* for the chip to all IRQ callbacks, so the
callbacks need to embed the gpio_chip in its state container and obtain a
pointer to the container using container_of().
(See Documentation/driver-model/design-patterns.txt)
(See Documentation/driver-model/design-patterns.rst)
- gpiochip_irqchip_add_nested(): adds a nested cascaded irqchip to a gpiochip,
as discussed above regarding different types of cascaded irqchips. The

View File

@ -1,5 +1,6 @@
==============
Driver Binding
==============
Driver binding is the process of associating a device with a device
driver that can control it. Bus drivers have typically handled this
@ -25,7 +26,7 @@ device_register
When a new device is added, the bus's list of drivers is iterated over
to find one that supports it. In order to determine that, the device
ID of the device must match one of the device IDs that the driver
supports. The format and semantics for comparing IDs is bus-specific.
supports. The format and semantics for comparing IDs is bus-specific.
Instead of trying to derive a complex state machine and matching
algorithm, it is up to the bus driver to provide a callback to compare
a device against the IDs of a driver. The bus returns 1 if a match was
@ -36,14 +37,14 @@ int match(struct device * dev, struct device_driver * drv);
If a match is found, the device's driver field is set to the driver
and the driver's probe callback is called. This gives the driver a
chance to verify that it really does support the hardware, and that
it's in a working state.
it's in a working state.
Device Class
~~~~~~~~~~~~
Upon the successful completion of probe, the device is registered with
the class to which it belongs. Device drivers belong to one and only one
class, and that is set in the driver's devclass field.
class, and that is set in the driver's devclass field.
devclass_add_device is called to enumerate the device within the class
and actually register it with the class, which happens with the
class's register_dev callback.
@ -53,7 +54,7 @@ Driver
~~~~~~
When a driver is attached to a device, the device is inserted into the
driver's list of devices.
driver's list of devices.
sysfs
@ -67,18 +68,18 @@ to the device's directory in the physical hierarchy.
A directory for the device is created in the class's directory. A
symlink is created in that directory that points to the device's
physical location in the sysfs tree.
physical location in the sysfs tree.
A symlink can be created (though this isn't done yet) in the device's
physical directory to either its class directory, or the class's
top-level directory. One can also be created to point to its driver's
directory also.
directory also.
driver_register
~~~~~~~~~~~~~~~
The process is almost identical for when a new driver is added.
The process is almost identical for when a new driver is added.
The bus's list of devices is iterated over to find a match. Devices
that already have a driver are skipped. All the devices are iterated
over, to bind as many devices as possible to the driver.
@ -94,5 +95,4 @@ of the driver is decremented. All symlinks between the two are removed.
When a driver is removed, the list of devices that it supports is
iterated over, and the driver's remove callback is called for each
one. The device is removed from that list and the symlinks removed.
one. The device is removed from that list and the symlinks removed.

View File

@ -1,5 +1,6 @@
Bus Types
=========
Bus Types
=========
Definition
~~~~~~~~~~
@ -13,12 +14,12 @@ Declaration
Each bus type in the kernel (PCI, USB, etc) should declare one static
object of this type. They must initialize the name field, and may
optionally initialize the match callback.
optionally initialize the match callback::
struct bus_type pci_bus_type = {
.name = "pci",
.match = pci_bus_match,
};
struct bus_type pci_bus_type = {
.name = "pci",
.match = pci_bus_match,
};
The structure should be exported to drivers in a header file:
@ -30,8 +31,8 @@ Registration
When a bus driver is initialized, it calls bus_register. This
initializes the rest of the fields in the bus object and inserts it
into a global list of bus types. Once the bus object is registered,
the fields in it are usable by the bus driver.
into a global list of bus types. Once the bus object is registered,
the fields in it are usable by the bus driver.
Callbacks
@ -43,17 +44,17 @@ match(): Attaching Drivers to Devices
The format of device ID structures and the semantics for comparing
them are inherently bus-specific. Drivers typically declare an array
of device IDs of devices they support that reside in a bus-specific
driver structure.
driver structure.
The purpose of the match callback is to give the bus an opportunity to
determine if a particular driver supports a particular device by
comparing the device IDs the driver supports with the device ID of a
particular device, without sacrificing bus-specific functionality or
type-safety.
type-safety.
When a driver is registered with the bus, the bus's list of devices is
iterated over, and the match callback is called for each device that
does not have a driver associated with it.
does not have a driver associated with it.
@ -64,22 +65,23 @@ The lists of devices and drivers are intended to replace the local
lists that many buses keep. They are lists of struct devices and
struct device_drivers, respectively. Bus drivers are free to use the
lists as they please, but conversion to the bus-specific type may be
necessary.
necessary.
The LDM core provides helper functions for iterating over each list.
The LDM core provides helper functions for iterating over each list::
int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,
int (*fn)(struct device *, void *));
int bus_for_each_dev(struct bus_type * bus, struct device * start,
void * data,
int (*fn)(struct device *, void *));
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
void * data, int (*fn)(struct device_driver *, void *));
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
void * data, int (*fn)(struct device_driver *, void *));
These helpers iterate over the respective list, and call the callback
for each device or driver in the list. All list accesses are
synchronized by taking the bus's lock (read currently). The reference
count on each object in the list is incremented before the callback is
called; it is decremented after the next object has been obtained. The
lock is not held when calling the callback.
lock is not held when calling the callback.
sysfs
@ -87,14 +89,14 @@ sysfs
There is a top-level directory named 'bus'.
Each bus gets a directory in the bus directory, along with two default
directories:
directories::
/sys/bus/pci/
|-- devices
`-- drivers
Drivers registered with the bus get a directory in the bus's drivers
directory:
directory::
/sys/bus/pci/
|-- devices
@ -106,7 +108,7 @@ directory:
Each device that is discovered on a bus of that type gets a symlink in
the bus's devices directory to the device's directory in the physical
hierarchy:
hierarchy::
/sys/bus/pci/
|-- devices
@ -118,26 +120,27 @@ hierarchy:
Exporting Attributes
~~~~~~~~~~~~~~~~~~~~
struct bus_attribute {
::
struct bus_attribute {
struct attribute attr;
ssize_t (*show)(struct bus_type *, char * buf);
ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
};
};
Bus drivers can export attributes using the BUS_ATTR_RW macro that works
similarly to the DEVICE_ATTR_RW macro for devices. For example, a
definition like this:
definition like this::
static BUS_ATTR_RW(debug);
static BUS_ATTR_RW(debug);
is equivalent to declaring:
is equivalent to declaring::
static bus_attribute bus_attr_debug;
static bus_attribute bus_attr_debug;
This can then be used to add and remove the attribute from the bus's
sysfs directory using:
int bus_create_file(struct bus_type *, struct bus_attribute *);
void bus_remove_file(struct bus_type *, struct bus_attribute *);
sysfs directory using::
int bus_create_file(struct bus_type *, struct bus_attribute *);
void bus_remove_file(struct bus_type *, struct bus_attribute *);

View File

@ -1,6 +1,6 @@
==============
Device Classes
==============
Introduction
~~~~~~~~~~~~
@ -13,37 +13,37 @@ device. The following device classes have been identified:
Each device class defines a set of semantics and a programming interface
that devices of that class adhere to. Device drivers are the
implementation of that programming interface for a particular device on
a particular bus.
a particular bus.
Device classes are agnostic with respect to what bus a device resides
on.
on.
Programming Interface
~~~~~~~~~~~~~~~~~~~~~
The device class structure looks like:
The device class structure looks like::
typedef int (*devclass_add)(struct device *);
typedef void (*devclass_remove)(struct device *);
typedef int (*devclass_add)(struct device *);
typedef void (*devclass_remove)(struct device *);
See the kerneldoc for the struct class.
A typical device class definition would look like:
A typical device class definition would look like::
struct device_class input_devclass = {
struct device_class input_devclass = {
.name = "input",
.add_device = input_add_device,
.remove_device = input_remove_device,
};
};
Each device class structure should be exported in a header file so it
can be used by drivers, extensions and interfaces.
Device classes are registered and unregistered with the core using:
Device classes are registered and unregistered with the core using::
int devclass_register(struct device_class * cls);
void devclass_unregister(struct device_class * cls);
int devclass_register(struct device_class * cls);
void devclass_unregister(struct device_class * cls);
Devices
@ -52,16 +52,16 @@ As devices are bound to drivers, they are added to the device class
that the driver belongs to. Before the driver model core, this would
typically happen during the driver's probe() callback, once the device
has been initialized. It now happens after the probe() callback
finishes from the core.
finishes from the core.
The device is enumerated in the class. Each time a device is added to
the class, the class's devnum field is incremented and assigned to the
device. The field is never decremented, so if the device is removed
from the class and re-added, it will receive a different enumerated
value.
value.
The class is allowed to create a class-specific structure for the
device and store it in the device's class_data pointer.
device and store it in the device's class_data pointer.
There is no list of devices in the device class. Each driver has a
list of devices that it supports. The device class has a list of
@ -73,15 +73,15 @@ Device Drivers
~~~~~~~~~~~~~~
Device drivers are added to device classes when they are registered
with the core. A driver specifies the class it belongs to by setting
the struct device_driver::devclass field.
the struct device_driver::devclass field.
sysfs directory structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There is a top-level sysfs directory named 'class'.
There is a top-level sysfs directory named 'class'.
Each class gets a directory in the class directory, along with two
default subdirectories:
default subdirectories::
class/
`-- input
@ -89,8 +89,8 @@ default subdirectories:
`-- drivers
Drivers registered with the class get a symlink in the drivers/ directory
that points to the driver's directory (under its bus directory):
Drivers registered with the class get a symlink in the drivers/ directory
that points to the driver's directory (under its bus directory)::
class/
`-- input
@ -99,8 +99,8 @@ that points to the driver's directory (under its bus directory):
`-- usb:usb_mouse -> ../../../bus/drivers/usb_mouse/
Each device gets a symlink in the devices/ directory that points to the
device's directory in the physical hierarchy:
Each device gets a symlink in the devices/ directory that points to the
device's directory in the physical hierarchy::
class/
`-- input
@ -111,37 +111,39 @@ device's directory in the physical hierarchy:
Exporting Attributes
~~~~~~~~~~~~~~~~~~~~
struct devclass_attribute {
::
struct devclass_attribute {
struct attribute attr;
ssize_t (*show)(struct device_class *, char * buf, size_t count, loff_t off);
ssize_t (*store)(struct device_class *, const char * buf, size_t count, loff_t off);
};
};
Class drivers can export attributes using the DEVCLASS_ATTR macro that works
similarly to the DEVICE_ATTR macro for devices. For example, a definition
like this:
similarly to the DEVICE_ATTR macro for devices. For example, a definition
like this::
static DEVCLASS_ATTR(debug,0644,show_debug,store_debug);
static DEVCLASS_ATTR(debug,0644,show_debug,store_debug);
is equivalent to declaring:
is equivalent to declaring::
static devclass_attribute devclass_attr_debug;
static devclass_attribute devclass_attr_debug;
The bus driver can add and remove the attribute from the class's
sysfs directory using:
sysfs directory using::
int devclass_create_file(struct device_class *, struct devclass_attribute *);
void devclass_remove_file(struct device_class *, struct devclass_attribute *);
int devclass_create_file(struct device_class *, struct devclass_attribute *);
void devclass_remove_file(struct device_class *, struct devclass_attribute *);
In the example above, the file will be named 'debug' in placed in the
class's directory in sysfs.
class's directory in sysfs.
Interfaces
~~~~~~~~~~
There may exist multiple mechanisms for accessing the same device of a
particular class type. Device interfaces describe these mechanisms.
particular class type. Device interfaces describe these mechanisms.
When a device is added to a device class, the core attempts to add it
to every interface that is registered with the device class.

View File

@ -1,6 +1,6 @@
=============================
Device Driver Design Patterns
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=============================
This document describes a few common design patterns found in device drivers.
It is likely that subsystem maintainers will ask driver developers to
@ -19,23 +19,23 @@ that the device the driver binds to will appear in several instances. This
means that the probe() function and all callbacks need to be reentrant.
The most common way to achieve this is to use the state container design
pattern. It usually has this form:
pattern. It usually has this form::
struct foo {
spinlock_t lock; /* Example member */
(...)
};
struct foo {
spinlock_t lock; /* Example member */
(...)
};
static int foo_probe(...)
{
struct foo *foo;
static int foo_probe(...)
{
struct foo *foo;
foo = devm_kzalloc(dev, sizeof(*foo), GFP_KERNEL);
if (!foo)
return -ENOMEM;
spin_lock_init(&foo->lock);
(...)
}
foo = devm_kzalloc(dev, sizeof(*foo), GFP_KERNEL);
if (!foo)
return -ENOMEM;
spin_lock_init(&foo->lock);
(...)
}
This will create an instance of struct foo in memory every time probe() is
called. This is our state container for this instance of the device driver.
@ -43,21 +43,21 @@ Of course it is then necessary to always pass this instance of the
state around to all functions that need access to the state and its members.
For example, if the driver is registering an interrupt handler, you would
pass around a pointer to struct foo like this:
pass around a pointer to struct foo like this::
static irqreturn_t foo_handler(int irq, void *arg)
{
struct foo *foo = arg;
(...)
}
static irqreturn_t foo_handler(int irq, void *arg)
{
struct foo *foo = arg;
(...)
}
static int foo_probe(...)
{
struct foo *foo;
static int foo_probe(...)
{
struct foo *foo;
(...)
ret = request_irq(irq, foo_handler, 0, "foo", foo);
}
(...)
ret = request_irq(irq, foo_handler, 0, "foo", foo);
}
This way you always get a pointer back to the correct instance of foo in
your interrupt handler.
@ -66,38 +66,38 @@ your interrupt handler.
2. container_of()
~~~~~~~~~~~~~~~~~
Continuing on the above example we add an offloaded work:
Continuing on the above example we add an offloaded work::
struct foo {
spinlock_t lock;
struct workqueue_struct *wq;
struct work_struct offload;
(...)
};
struct foo {
spinlock_t lock;
struct workqueue_struct *wq;
struct work_struct offload;
(...)
};
static void foo_work(struct work_struct *work)
{
struct foo *foo = container_of(work, struct foo, offload);
static void foo_work(struct work_struct *work)
{
struct foo *foo = container_of(work, struct foo, offload);
(...)
}
(...)
}
static irqreturn_t foo_handler(int irq, void *arg)
{
struct foo *foo = arg;
static irqreturn_t foo_handler(int irq, void *arg)
{
struct foo *foo = arg;
queue_work(foo->wq, &foo->offload);
(...)
}
queue_work(foo->wq, &foo->offload);
(...)
}
static int foo_probe(...)
{
struct foo *foo;
static int foo_probe(...)
{
struct foo *foo;
foo->wq = create_singlethread_workqueue("foo-wq");
INIT_WORK(&foo->offload, foo_work);
(...)
}
foo->wq = create_singlethread_workqueue("foo-wq");
INIT_WORK(&foo->offload, foo_work);
(...)
}
The design pattern is the same for an hrtimer or something similar that will
return a single argument which is a pointer to a struct member in the

View File

@ -1,6 +1,6 @@
==========================
The Basic Device Structure
~~~~~~~~~~~~~~~~~~~~~~~~~~
==========================
See the kerneldoc for the struct device.
@ -8,9 +8,9 @@ See the kerneldoc for the struct device.
Programming Interface
~~~~~~~~~~~~~~~~~~~~~
The bus driver that discovers the device uses this to register the
device with the core:
device with the core::
int device_register(struct device * dev);
int device_register(struct device * dev);
The bus should initialize the following fields:
@ -20,30 +20,33 @@ The bus should initialize the following fields:
- bus
A device is removed from the core when its reference count goes to
0. The reference count can be adjusted using:
0. The reference count can be adjusted using::
struct device * get_device(struct device * dev);
void put_device(struct device * dev);
struct device * get_device(struct device * dev);
void put_device(struct device * dev);
get_device() will return a pointer to the struct device passed to it
if the reference is not already 0 (if it's in the process of being
removed already).
A driver can access the lock in the device structure using:
A driver can access the lock in the device structure using::
void lock_device(struct device * dev);
void unlock_device(struct device * dev);
void lock_device(struct device * dev);
void unlock_device(struct device * dev);
Attributes
~~~~~~~~~~
struct device_attribute {
::
struct device_attribute {
struct attribute attr;
ssize_t (*show)(struct device *dev, struct device_attribute *attr,
char *buf);
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
};
};
Attributes of devices can be exported by a device driver through sysfs.
@ -54,39 +57,39 @@ As explained in Documentation/kobject.txt, device attributes must be
created before the KOBJ_ADD uevent is generated. The only way to realize
that is by defining an attribute group.
Attributes are declared using a macro called DEVICE_ATTR:
Attributes are declared using a macro called DEVICE_ATTR::
#define DEVICE_ATTR(name,mode,show,store)
#define DEVICE_ATTR(name,mode,show,store)
Example:
Example:::
static DEVICE_ATTR(type, 0444, show_type, NULL);
static DEVICE_ATTR(power, 0644, show_power, store_power);
static DEVICE_ATTR(type, 0444, show_type, NULL);
static DEVICE_ATTR(power, 0644, show_power, store_power);
This declares two structures of type struct device_attribute with respective
names 'dev_attr_type' and 'dev_attr_power'. These two attributes can be
organized as follows into a group:
organized as follows into a group::
static struct attribute *dev_attrs[] = {
static struct attribute *dev_attrs[] = {
&dev_attr_type.attr,
&dev_attr_power.attr,
NULL,
};
};
static struct attribute_group dev_attr_group = {
static struct attribute_group dev_attr_group = {
.attrs = dev_attrs,
};
};
static const struct attribute_group *dev_attr_groups[] = {
static const struct attribute_group *dev_attr_groups[] = {
&dev_attr_group,
NULL,
};
};
This array of groups can then be associated with a device by setting the
group pointer in struct device before device_register() is invoked:
group pointer in struct device before device_register() is invoked::
dev->groups = dev_attr_groups;
device_register(dev);
dev->groups = dev_attr_groups;
device_register(dev);
The device_register() function will use the 'groups' pointer to create the
device attributes and the device_unregister() function will use this pointer

View File

@ -1,3 +1,4 @@
================================
Devres - Managed Device Resource
================================
@ -5,17 +6,18 @@ Tejun Heo <teheo@suse.de>
First draft 10 January 2007
.. contents
1. Intro : Huh? Devres?
2. Devres : Devres in a nutshell
3. Devres Group : Group devres'es and release them together
4. Details : Life time rules, calling context, ...
5. Overhead : How much do we have to pay for this?
6. List of managed interfaces : Currently implemented managed interfaces
1. Intro : Huh? Devres?
2. Devres : Devres in a nutshell
3. Devres Group : Group devres'es and release them together
4. Details : Life time rules, calling context, ...
5. Overhead : How much do we have to pay for this?
6. List of managed interfaces: Currently implemented managed interfaces
1. Intro
--------
1. Intro
--------
devres came up while trying to convert libata to use iomap. Each
iomapped address should be kept and unmapped on driver detach. For
@ -42,8 +44,8 @@ would leak resources or even cause oops when failure occurs. iomap
adds more to this mix. So do msi and msix.
2. Devres
---------
2. Devres
---------
devres is basically linked list of arbitrarily sized memory areas
associated with a struct device. Each devres entry is associated with
@ -58,7 +60,7 @@ using dma_alloc_coherent(). The managed version is called
dmam_alloc_coherent(). It is identical to dma_alloc_coherent() except
for the DMA memory allocated using it is managed and will be
automatically released on driver detach. Implementation looks like
the following.
the following::
struct dma_devres {
size_t size;
@ -98,7 +100,7 @@ If a driver uses dmam_alloc_coherent(), the area is guaranteed to be
freed whether initialization fails half-way or the device gets
detached. If most resources are acquired using managed interface, a
driver can have much simpler init and exit code. Init path basically
looks like the following.
looks like the following::
my_init_one()
{
@ -119,7 +121,7 @@ looks like the following.
return register_to_upper_layer(d);
}
And exit path,
And exit path::
my_remove_one()
{
@ -140,13 +142,13 @@ on you. In some cases this may mean introducing checks that were not
necessary before moving to the managed devm_* calls.
3. Devres group
---------------
3. Devres group
---------------
Devres entries can be grouped using devres group. When a group is
released, all contained normal devres entries and properly nested
groups are released. One usage is to rollback series of acquired
resources on failure. For example,
resources on failure. For example::
if (!devres_open_group(dev, NULL, GFP_KERNEL))
return -ENOMEM;
@ -172,7 +174,7 @@ like above are usually useful in midlayer driver (e.g. libata core
layer) where interface function shouldn't have side effect on failure.
For LLDs, just returning error code suffices in most cases.
Each group is identified by void *id. It can either be explicitly
Each group is identified by `void *id`. It can either be explicitly
specified by @id argument to devres_open_group() or automatically
created by passing NULL as @id as in the above example. In both
cases, devres_open_group() returns the group's id. The returned id
@ -180,7 +182,7 @@ can be passed to other devres functions to select the target group.
If NULL is given to those functions, the latest open group is
selected.
For example, you can do something like the following.
For example, you can do something like the following::
int my_midlayer_create_something()
{
@ -199,8 +201,8 @@ For example, you can do something like the following.
}
4. Details
----------
4. Details
----------
Lifetime of a devres entry begins on devres allocation and finishes
when it is released or destroyed (removed and freed) - no reference
@ -220,8 +222,8 @@ All devres interface functions can be called without context if the
right gfp mask is given.
5. Overhead
-----------
5. Overhead
-----------
Each devres bookkeeping info is allocated together with requested data
area. With debug option turned off, bookkeeping info occupies 16
@ -237,8 +239,8 @@ and 400 bytes on 32bit machine after naive conversion (we can
certainly invest a bit more effort into libata core layer).
6. List of managed interfaces
-----------------------------
6. List of managed interfaces
-----------------------------
CLOCK
devm_clk_get()

View File

@ -1,5 +1,6 @@
==============
Device Drivers
==============
See the kerneldoc for the struct device_driver.
@ -26,50 +27,50 @@ Declaration
As stated above, struct device_driver objects are statically
allocated. Below is an example declaration of the eepro100
driver. This declaration is hypothetical only; it relies on the driver
being converted completely to the new model.
being converted completely to the new model::
static struct device_driver eepro100_driver = {
.name = "eepro100",
.bus = &pci_bus_type,
.probe = eepro100_probe,
.remove = eepro100_remove,
.suspend = eepro100_suspend,
.resume = eepro100_resume,
};
static struct device_driver eepro100_driver = {
.name = "eepro100",
.bus = &pci_bus_type,
.probe = eepro100_probe,
.remove = eepro100_remove,
.suspend = eepro100_suspend,
.resume = eepro100_resume,
};
Most drivers will not be able to be converted completely to the new
model because the bus they belong to has a bus-specific structure with
bus-specific fields that cannot be generalized.
bus-specific fields that cannot be generalized.
The most common example of this are device ID structures. A driver
typically defines an array of device IDs that it supports. The format
of these structures and the semantics for comparing device IDs are
completely bus-specific. Defining them as bus-specific entities would
sacrifice type-safety, so we keep bus-specific structures around.
sacrifice type-safety, so we keep bus-specific structures around.
Bus-specific drivers should include a generic struct device_driver in
the definition of the bus-specific driver. Like this:
the definition of the bus-specific driver. Like this::
struct pci_driver {
const struct pci_device_id *id_table;
struct device_driver driver;
};
struct pci_driver {
const struct pci_device_id *id_table;
struct device_driver driver;
};
A definition that included bus-specific fields would look like
(using the eepro100 driver again):
(using the eepro100 driver again)::
static struct pci_driver eepro100_driver = {
.id_table = eepro100_pci_tbl,
.driver = {
static struct pci_driver eepro100_driver = {
.id_table = eepro100_pci_tbl,
.driver = {
.name = "eepro100",
.bus = &pci_bus_type,
.probe = eepro100_probe,
.remove = eepro100_remove,
.suspend = eepro100_suspend,
.resume = eepro100_resume,
},
};
},
};
Some may find the syntax of embedded struct initialization awkward or
even a bit ugly. So far, it's the best way we've found to do what we want...
@ -77,12 +78,14 @@ even a bit ugly. So far, it's the best way we've found to do what we want...
Registration
~~~~~~~~~~~~
int driver_register(struct device_driver * drv);
::
int driver_register(struct device_driver *drv);
The driver registers the structure on startup. For drivers that have
no bus-specific fields (i.e. don't have a bus-specific driver
structure), they would use driver_register and pass a pointer to their
struct device_driver object.
struct device_driver object.
Most drivers, however, will have a bus-specific structure and will
need to register with the bus using something like pci_driver_register.
@ -101,7 +104,7 @@ By defining wrapper functions, the transition to the new model can be
made easier. Drivers can ignore the generic structure altogether and
let the bus wrapper fill in the fields. For the callbacks, the bus can
define generic callbacks that forward the call to the bus-specific
callbacks of the drivers.
callbacks of the drivers.
This solution is intended to be only temporary. In order to get class
information in the driver, the drivers must be modified anyway. Since
@ -113,16 +116,16 @@ Access
~~~~~~
Once the object has been registered, it may access the common fields of
the object, like the lock and the list of devices.
the object, like the lock and the list of devices::
int driver_for_each_dev(struct device_driver * drv, void * data,
int (*callback)(struct device * dev, void * data));
int driver_for_each_dev(struct device_driver *drv, void *data,
int (*callback)(struct device *dev, void *data));
The devices field is a list of all the devices that have been bound to
the driver. The LDM core provides a helper function to operate on all
the devices a driver controls. This helper locks the driver on each
node access, and does proper reference counting on each device as it
accesses it.
accesses it.
sysfs
@ -142,7 +145,9 @@ supports.
Callbacks
~~~~~~~~~
int (*probe) (struct device * dev);
::
int (*probe) (struct device *dev);
The probe() entry is called in task context, with the bus's rwsem locked
and the driver partially bound to the device. Drivers commonly use
@ -162,9 +167,9 @@ the driver to that device.
A driver's probe() may return a negative errno value to indicate that
the driver did not bind to this device, in which case it should have
released all resources it allocated.
released all resources it allocated::
int (*remove) (struct device * dev);
int (*remove) (struct device *dev);
remove is called to unbind a driver from a device. This may be
called if a device is physically removed from the system, if the
@ -173,43 +178,46 @@ in other cases.
It is up to the driver to determine if the device is present or
not. It should free any resources allocated specifically for the
device; i.e. anything in the device's driver_data field.
device; i.e. anything in the device's driver_data field.
If the device is still present, it should quiesce the device and place
it into a supported low-power state.
it into a supported low-power state::
int (*suspend) (struct device * dev, pm_message_t state);
int (*suspend) (struct device *dev, pm_message_t state);
suspend is called to put the device in a low power state.
suspend is called to put the device in a low power state::
int (*resume) (struct device * dev);
int (*resume) (struct device *dev);
Resume is used to bring a device back from a low power state.
Attributes
~~~~~~~~~~
struct driver_attribute {
struct attribute attr;
ssize_t (*show)(struct device_driver *driver, char *buf);
ssize_t (*store)(struct device_driver *, const char * buf, size_t count);
};
Device drivers can export attributes via their sysfs directories.
::
struct driver_attribute {
struct attribute attr;
ssize_t (*show)(struct device_driver *driver, char *buf);
ssize_t (*store)(struct device_driver *, const char *buf, size_t count);
};
Device drivers can export attributes via their sysfs directories.
Drivers can declare attributes using a DRIVER_ATTR_RW and DRIVER_ATTR_RO
macro that works identically to the DEVICE_ATTR_RW and DEVICE_ATTR_RO
macros.
Example:
Example::
DRIVER_ATTR_RW(debug);
DRIVER_ATTR_RW(debug);
This is equivalent to declaring:
This is equivalent to declaring::
struct driver_attribute driver_attr_debug;
struct driver_attribute driver_attr_debug;
This can then be used to add and remove the attribute from the
driver's directory using:
driver's directory using::
int driver_create_file(struct device_driver *, const struct driver_attribute *);
void driver_remove_file(struct device_driver *, const struct driver_attribute *);
int driver_create_file(struct device_driver *, const struct driver_attribute *);
void driver_remove_file(struct device_driver *, const struct driver_attribute *);

View File

@ -0,0 +1,26 @@
:orphan:
============
Driver Model
============
.. toctree::
:maxdepth: 1
binding
bus
class
design-patterns
device
devres
driver
overview
platform
porting
.. only:: subproject and html
Indices
=======
* :ref:`genindex`

View File

@ -1,4 +1,6 @@
=============================
The Linux Kernel Device Model
=============================
Patrick Mochel <mochel@digitalimplant.org>
@ -41,14 +43,14 @@ data structure. These fields must still be accessed by the bus layers,
and sometimes by the device-specific drivers.
Other bus layers are encouraged to do what has been done for the PCI layer.
struct pci_dev now looks like this:
struct pci_dev now looks like this::
struct pci_dev {
struct pci_dev {
...
struct device dev; /* Generic device interface */
...
};
};
Note first that the struct device dev within the struct pci_dev is
statically allocated. This means only one allocation on device discovery.
@ -80,26 +82,26 @@ easy. This has been accomplished by implementing a special purpose virtual
file system named sysfs.
Almost all mainstream Linux distros mount this filesystem automatically; you
can see some variation of the following in the output of the "mount" command:
can see some variation of the following in the output of the "mount" command::
$ mount
...
none on /sys type sysfs (rw,noexec,nosuid,nodev)
...
$
$ mount
...
none on /sys type sysfs (rw,noexec,nosuid,nodev)
...
$
The auto-mounting of sysfs is typically accomplished by an entry similar to
the following in the /etc/fstab file:
the following in the /etc/fstab file::
none /sys sysfs defaults 0 0
none /sys sysfs defaults 0 0
or something similar in the /lib/init/fstab file on Debian-based systems:
or something similar in the /lib/init/fstab file on Debian-based systems::
none /sys sysfs nodev,noexec,nosuid 0 0
none /sys sysfs nodev,noexec,nosuid 0 0
If sysfs is not automatically mounted, you can always do it manually with:
If sysfs is not automatically mounted, you can always do it manually with::
# mount -t sysfs sysfs /sys
# mount -t sysfs sysfs /sys
Whenever a device is inserted into the tree, a directory is created for it.
This directory may be populated at each layer of discovery - the global layer,
@ -108,7 +110,7 @@ the bus layer, or the device layer.
The global layer currently creates two files - 'name' and 'power'. The
former only reports the name of the device. The latter reports the
current power state of the device. It will also be used to set the current
power state.
power state.
The bus layer may also create files for the devices it finds while probing the
bus. For example, the PCI layer currently creates 'irq' and 'resource' files
@ -118,6 +120,5 @@ A device-specific driver may also export files in its directory to expose
device-specific data or tunable interfaces.
More information about the sysfs directory layout can be found in
the other documents in this directory and in the file
the other documents in this directory and in the file
Documentation/filesystems/sysfs.txt.

View File

@ -1,5 +1,7 @@
============================
Platform Devices and Drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
============================
See <linux/platform_device.h> for the driver model interface to the
platform bus: platform_device, and platform_driver. This pseudo-bus
is used to connect devices on busses with minimal infrastructure,
@ -19,15 +21,15 @@ be connected through a segment of some other kind of bus; but its
registers will still be directly addressable.
Platform devices are given a name, used in driver binding, and a
list of resources such as addresses and IRQs.
list of resources such as addresses and IRQs::
struct platform_device {
struct platform_device {
const char *name;
u32 id;
struct device dev;
u32 num_resources;
struct resource *resource;
};
};
Platform drivers
@ -35,9 +37,9 @@ Platform drivers
Platform drivers follow the standard driver model convention, where
discovery/enumeration is handled outside the drivers, and drivers
provide probe() and remove() methods. They support power management
and shutdown notifications using the standard conventions.
and shutdown notifications using the standard conventions::
struct platform_driver {
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
@ -46,25 +48,25 @@ struct platform_driver {
int (*resume_early)(struct platform_device *);
int (*resume)(struct platform_device *);
struct device_driver driver;
};
};
Note that probe() should in general verify that the specified device hardware
actually exists; sometimes platform setup code can't be sure. The probing
can use device resources, including clocks, and device platform_data.
Platform drivers register themselves the normal way:
Platform drivers register themselves the normal way::
int platform_driver_register(struct platform_driver *drv);
Or, in common situations where the device is known not to be hot-pluggable,
the probe() routine can live in an init section to reduce the driver's
runtime memory footprint:
runtime memory footprint::
int platform_driver_probe(struct platform_driver *drv,
int (*probe)(struct platform_device *))
Kernel modules can be composed of several platform drivers. The platform core
provides helpers to register and unregister an array of drivers:
provides helpers to register and unregister an array of drivers::
int __platform_register_drivers(struct platform_driver * const *drivers,
unsigned int count, struct module *owner);
@ -73,7 +75,7 @@ provides helpers to register and unregister an array of drivers:
If one of the drivers fails to register, all drivers registered up to that
point will be unregistered in reverse order. Note that there is a convenience
macro that passes THIS_MODULE as owner parameter:
macro that passes THIS_MODULE as owner parameter::
#define platform_register_drivers(drivers, count)
@ -81,7 +83,7 @@ macro that passes THIS_MODULE as owner parameter:
Device Enumeration
~~~~~~~~~~~~~~~~~~
As a rule, platform specific (and often board-specific) setup code will
register platform devices:
register platform devices::
int platform_device_register(struct platform_device *pdev);
@ -133,14 +135,14 @@ tend to already have "normal" modes, such as ones using device nodes that
were created by PNP or by platform device setup.
None the less, there are some APIs to support such legacy drivers. Avoid
using these calls except with such hotplug-deficient drivers.
using these calls except with such hotplug-deficient drivers::
struct platform_device *platform_device_alloc(
const char *name, int id);
You can use platform_device_alloc() to dynamically allocate a device, which
you will then initialize with resources and platform_device_register().
A better solution is usually:
A better solution is usually::
struct platform_device *platform_device_register_simple(
const char *name, int id,

View File

@ -1,5 +1,6 @@
=======================================
Porting Drivers to the New Driver Model
=======================================
Patrick Mochel
@ -8,8 +9,8 @@ Patrick Mochel
Overview
Please refer to Documentation/driver-model/*.txt for definitions of
various driver types and concepts.
Please refer to `Documentation/driver-model/*.rst` for definitions of
various driver types and concepts.
Most of the work of porting devices drivers to the new model happens
at the bus driver layer. This was intentional, to minimize the
@ -18,11 +19,11 @@ of bus drivers.
In a nutshell, the driver model consists of a set of objects that can
be embedded in larger, bus-specific objects. Fields in these generic
objects can replace fields in the bus-specific objects.
objects can replace fields in the bus-specific objects.
The generic objects must be registered with the driver model core. By
doing so, they will exported via the sysfs filesystem. sysfs can be
mounted by doing
mounted by doing::
# mount -t sysfs sysfs /sys
@ -30,108 +31,109 @@ mounted by doing
The Process
Step 0: Read include/linux/device.h for object and function definitions.
Step 0: Read include/linux/device.h for object and function definitions.
Step 1: Registering the bus driver.
Step 1: Registering the bus driver.
- Define a struct bus_type for the bus driver.
- Define a struct bus_type for the bus driver::
struct bus_type pci_bus_type = {
.name = "pci",
};
struct bus_type pci_bus_type = {
.name = "pci",
};
- Register the bus type.
This should be done in the initialization function for the bus type,
which is usually the module_init(), or equivalent, function.
which is usually the module_init(), or equivalent, function::
static int __init pci_driver_init(void)
{
return bus_register(&pci_bus_type);
}
static int __init pci_driver_init(void)
{
return bus_register(&pci_bus_type);
}
subsys_initcall(pci_driver_init);
subsys_initcall(pci_driver_init);
The bus type may be unregistered (if the bus driver may be compiled
as a module) by doing:
as a module) by doing::
bus_unregister(&pci_bus_type);
- Export the bus type for others to use.
- Export the bus type for others to use.
Other code may wish to reference the bus type, so declare it in a
Other code may wish to reference the bus type, so declare it in a
shared header file and export the symbol.
From include/linux/pci.h:
From include/linux/pci.h::
extern struct bus_type pci_bus_type;
extern struct bus_type pci_bus_type;
From file the above code appears in:
From file the above code appears in::
EXPORT_SYMBOL(pci_bus_type);
EXPORT_SYMBOL(pci_bus_type);
- This will cause the bus to show up in /sys/bus/pci/ with two
subdirectories: 'devices' and 'drivers'.
subdirectories: 'devices' and 'drivers'::
# tree -d /sys/bus/pci/
/sys/bus/pci/
|-- devices
`-- drivers
# tree -d /sys/bus/pci/
/sys/bus/pci/
|-- devices
`-- drivers
Step 2: Registering Devices.
Step 2: Registering Devices.
struct device represents a single device. It mainly contains metadata
describing the relationship the device has to other entities.
describing the relationship the device has to other entities.
- Embed a struct device in the bus-specific device type.
- Embed a struct device in the bus-specific device type::
struct pci_dev {
...
struct device dev; /* Generic device interface */
...
};
struct pci_dev {
...
struct device dev; /* Generic device interface */
...
};
It is recommended that the generic device not be the first item in
It is recommended that the generic device not be the first item in
the struct to discourage programmers from doing mindless casts
between the object types. Instead macros, or inline functions,
should be created to convert from the generic object type.
should be created to convert from the generic object type::
#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
or
or
static inline struct pci_dev * to_pci_dev(struct kobject * kobj)
{
static inline struct pci_dev * to_pci_dev(struct kobject * kobj)
{
return container_of(n, struct pci_dev, dev);
}
}
This allows the compiler to verify type-safety of the operations
This allows the compiler to verify type-safety of the operations
that are performed (which is Good).
- Initialize the device on registration.
When devices are discovered or registered with the bus type, the
When devices are discovered or registered with the bus type, the
bus driver should initialize the generic device. The most important
things to initialize are the bus_id, parent, and bus fields.
The bus_id is an ASCII string that contains the device's address on
the bus. The format of this string is bus-specific. This is
necessary for representing devices in sysfs.
necessary for representing devices in sysfs.
parent is the physical parent of the device. It is important that
the bus driver sets this field correctly.
the bus driver sets this field correctly.
The driver model maintains an ordered list of devices that it uses
for power management. This list must be in order to guarantee that
@ -140,13 +142,13 @@ static inline struct pci_dev * to_pci_dev(struct kobject * kobj)
devices.
Also, the location of the device's sysfs directory depends on a
device's parent. sysfs exports a directory structure that mirrors
device's parent. sysfs exports a directory structure that mirrors
the device hierarchy. Accurately setting the parent guarantees that
sysfs will accurately represent the hierarchy.
The device's bus field is a pointer to the bus type the device
belongs to. This should be set to the bus_type that was declared
and initialized before.
and initialized before.
Optionally, the bus driver may set the device's name and release
fields.
@ -155,107 +157,107 @@ static inline struct pci_dev * to_pci_dev(struct kobject * kobj)
"ATI Technologies Inc Radeon QD"
The release field is a callback that the driver model core calls
when the device has been removed, and all references to it have
The release field is a callback that the driver model core calls
when the device has been removed, and all references to it have
been released. More on this in a moment.
- Register the device.
- Register the device.
Once the generic device has been initialized, it can be registered
with the driver model core by doing:
with the driver model core by doing::
device_register(&dev->dev);
It can later be unregistered by doing:
It can later be unregistered by doing::
device_unregister(&dev->dev);
This should happen on buses that support hotpluggable devices.
This should happen on buses that support hotpluggable devices.
If a bus driver unregisters a device, it should not immediately free
it. It should instead wait for the driver model core to call the
device's release method, then free the bus-specific object.
it. It should instead wait for the driver model core to call the
device's release method, then free the bus-specific object.
(There may be other code that is currently referencing the device
structure, and it would be rude to free the device while that is
structure, and it would be rude to free the device while that is
happening).
When the device is registered, a directory in sysfs is created.
The PCI tree in sysfs looks like:
When the device is registered, a directory in sysfs is created.
The PCI tree in sysfs looks like::
/sys/devices/pci0/
|-- 00:00.0
|-- 00:01.0
| `-- 01:00.0
|-- 00:02.0
| `-- 02:1f.0
| `-- 03:00.0
|-- 00:1e.0
| `-- 04:04.0
|-- 00:1f.0
|-- 00:1f.1
| |-- ide0
| | |-- 0.0
| | `-- 0.1
| `-- ide1
| `-- 1.0
|-- 00:1f.2
|-- 00:1f.3
`-- 00:1f.5
/sys/devices/pci0/
|-- 00:00.0
|-- 00:01.0
| `-- 01:00.0
|-- 00:02.0
| `-- 02:1f.0
| `-- 03:00.0
|-- 00:1e.0
| `-- 04:04.0
|-- 00:1f.0
|-- 00:1f.1
| |-- ide0
| | |-- 0.0
| | `-- 0.1
| `-- ide1
| `-- 1.0
|-- 00:1f.2
|-- 00:1f.3
`-- 00:1f.5
Also, symlinks are created in the bus's 'devices' directory
that point to the device's directory in the physical hierarchy.
that point to the device's directory in the physical hierarchy::
/sys/bus/pci/devices/
|-- 00:00.0 -> ../../../devices/pci0/00:00.0
|-- 00:01.0 -> ../../../devices/pci0/00:01.0
|-- 00:02.0 -> ../../../devices/pci0/00:02.0
|-- 00:1e.0 -> ../../../devices/pci0/00:1e.0
|-- 00:1f.0 -> ../../../devices/pci0/00:1f.0
|-- 00:1f.1 -> ../../../devices/pci0/00:1f.1
|-- 00:1f.2 -> ../../../devices/pci0/00:1f.2
|-- 00:1f.3 -> ../../../devices/pci0/00:1f.3
|-- 00:1f.5 -> ../../../devices/pci0/00:1f.5
|-- 01:00.0 -> ../../../devices/pci0/00:01.0/01:00.0
|-- 02:1f.0 -> ../../../devices/pci0/00:02.0/02:1f.0
|-- 03:00.0 -> ../../../devices/pci0/00:02.0/02:1f.0/03:00.0
`-- 04:04.0 -> ../../../devices/pci0/00:1e.0/04:04.0
/sys/bus/pci/devices/
|-- 00:00.0 -> ../../../devices/pci0/00:00.0
|-- 00:01.0 -> ../../../devices/pci0/00:01.0
|-- 00:02.0 -> ../../../devices/pci0/00:02.0
|-- 00:1e.0 -> ../../../devices/pci0/00:1e.0
|-- 00:1f.0 -> ../../../devices/pci0/00:1f.0
|-- 00:1f.1 -> ../../../devices/pci0/00:1f.1
|-- 00:1f.2 -> ../../../devices/pci0/00:1f.2
|-- 00:1f.3 -> ../../../devices/pci0/00:1f.3
|-- 00:1f.5 -> ../../../devices/pci0/00:1f.5
|-- 01:00.0 -> ../../../devices/pci0/00:01.0/01:00.0
|-- 02:1f.0 -> ../../../devices/pci0/00:02.0/02:1f.0
|-- 03:00.0 -> ../../../devices/pci0/00:02.0/02:1f.0/03:00.0
`-- 04:04.0 -> ../../../devices/pci0/00:1e.0/04:04.0
Step 3: Registering Drivers.
struct device_driver is a simple driver structure that contains a set
of operations that the driver model core may call.
of operations that the driver model core may call.
- Embed a struct device_driver in the bus-specific driver.
- Embed a struct device_driver in the bus-specific driver.
Just like with devices, do something like:
Just like with devices, do something like::
struct pci_driver {
...
struct device_driver driver;
};
struct pci_driver {
...
struct device_driver driver;
};
- Initialize the generic driver structure.
- Initialize the generic driver structure.
When the driver registers with the bus (e.g. doing pci_register_driver()),
initialize the necessary fields of the driver: the name and bus
fields.
fields.
- Register the driver.
After the generic driver has been initialized, call
After the generic driver has been initialized, call::
driver_register(&drv->driver);
to register the driver with the core.
When the driver is unregistered from the bus, unregister it from the
core by doing:
core by doing::
driver_unregister(&drv->driver);
@ -265,15 +267,15 @@ struct pci_driver {
- Sysfs representation.
Drivers are exported via sysfs in their bus's 'driver's directory.
For example:
Drivers are exported via sysfs in their bus's 'driver's directory.
For example::
/sys/bus/pci/drivers/
|-- 3c59x
|-- Ensoniq AudioPCI
|-- agpgart-amdk7
|-- e100
`-- serial
/sys/bus/pci/drivers/
|-- 3c59x
|-- Ensoniq AudioPCI
|-- agpgart-amdk7
|-- e100
`-- serial
Step 4: Define Generic Methods for Drivers.
@ -281,30 +283,30 @@ Step 4: Define Generic Methods for Drivers.
struct device_driver defines a set of operations that the driver model
core calls. Most of these operations are probably similar to
operations the bus already defines for drivers, but taking different
parameters.
parameters.
It would be difficult and tedious to force every driver on a bus to
simultaneously convert their drivers to generic format. Instead, the
bus driver should define single instances of the generic methods that
forward call to the bus-specific drivers. For instance:
forward call to the bus-specific drivers. For instance::
static int pci_device_remove(struct device * dev)
{
struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver;
static int pci_device_remove(struct device * dev)
{
struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver;
if (drv) {
if (drv->remove)
drv->remove(pci_dev);
pci_dev->driver = NULL;
}
return 0;
}
if (drv) {
if (drv->remove)
drv->remove(pci_dev);
pci_dev->driver = NULL;
}
return 0;
}
The generic driver should be initialized with these methods before it
is registered.
is registered::
/* initialize common driver fields */
drv->driver.name = drv->name;
@ -320,23 +322,23 @@ is registered.
Ideally, the bus should only initialize the fields if they are not
already set. This allows the drivers to implement their own generic
methods.
methods.
Step 5: Support generic driver binding.
Step 5: Support generic driver binding.
The model assumes that a device or driver can be dynamically
registered with the bus at any time. When registration happens,
devices must be bound to a driver, or drivers must be bound to all
devices that it supports.
devices that it supports.
A driver typically contains a list of device IDs that it supports. The
bus driver compares these IDs to the IDs of devices registered with it.
bus driver compares these IDs to the IDs of devices registered with it.
The format of the device IDs, and the semantics for comparing them are
bus-specific, so the generic model does attempt to generalize them.
bus-specific, so the generic model does attempt to generalize them.
Instead, a bus may supply a method in struct bus_type that does the
comparison:
comparison::
int (*match)(struct device * dev, struct device_driver * drv);
@ -346,59 +348,59 @@ and zero otherwise. It may also return error code (for example
not possible.
When a device is registered, the bus's list of drivers is iterated
over. bus->match() is called for each one until a match is found.
over. bus->match() is called for each one until a match is found.
When a driver is registered, the bus's list of devices is iterated
over. bus->match() is called for each device that is not already
claimed by a driver.
claimed by a driver.
When a device is successfully bound to a driver, device->driver is
set, the device is added to a per-driver list of devices, and a
symlink is created in the driver's sysfs directory that points to the
device's physical directory:
device's physical directory::
/sys/bus/pci/drivers/
|-- 3c59x
| `-- 00:0b.0 -> ../../../../devices/pci0/00:0b.0
|-- Ensoniq AudioPCI
|-- agpgart-amdk7
| `-- 00:00.0 -> ../../../../devices/pci0/00:00.0
|-- e100
| `-- 00:0c.0 -> ../../../../devices/pci0/00:0c.0
`-- serial
/sys/bus/pci/drivers/
|-- 3c59x
| `-- 00:0b.0 -> ../../../../devices/pci0/00:0b.0
|-- Ensoniq AudioPCI
|-- agpgart-amdk7
| `-- 00:00.0 -> ../../../../devices/pci0/00:00.0
|-- e100
| `-- 00:0c.0 -> ../../../../devices/pci0/00:0c.0
`-- serial
This driver binding should replace the existing driver binding
mechanism the bus currently uses.
mechanism the bus currently uses.
Step 6: Supply a hotplug callback.
Whenever a device is registered with the driver model core, the
userspace program /sbin/hotplug is called to notify userspace.
userspace program /sbin/hotplug is called to notify userspace.
Users can define actions to perform when a device is inserted or
removed.
removed.
The driver model core passes several arguments to userspace via
environment variables, including
- ACTION: set to 'add' or 'remove'
- DEVPATH: set to the device's physical path in sysfs.
- DEVPATH: set to the device's physical path in sysfs.
A bus driver may also supply additional parameters for userspace to
consume. To do this, a bus must implement the 'hotplug' method in
struct bus_type:
struct bus_type::
int (*hotplug) (struct device *dev, char **envp,
int (*hotplug) (struct device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
This is called immediately before /sbin/hotplug is executed.
This is called immediately before /sbin/hotplug is executed.
Step 7: Cleaning up the bus driver.
The generic bus, device, and driver structures provide several fields
that can replace those defined privately to the bus driver.
that can replace those defined privately to the bus driver.
- Device list.
@ -407,36 +409,36 @@ type. This includes all devices on all instances of that bus type.
An internal list that the bus uses may be removed, in favor of using
this one.
The core provides an iterator to access these devices.
The core provides an iterator to access these devices::
int bus_for_each_dev(struct bus_type * bus, struct device * start,
void * data, int (*fn)(struct device *, void *));
int bus_for_each_dev(struct bus_type * bus, struct device * start,
void * data, int (*fn)(struct device *, void *));
- Driver list.
struct bus_type also contains a list of all drivers registered with
it. An internal list of drivers that the bus driver maintains may
be removed in favor of using the generic one.
it. An internal list of drivers that the bus driver maintains may
be removed in favor of using the generic one.
The drivers may be iterated over, like devices:
The drivers may be iterated over, like devices::
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
void * data, int (*fn)(struct device_driver *, void *));
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
void * data, int (*fn)(struct device_driver *, void *));
Please see drivers/base/bus.c for more information.
- rwsem
- rwsem
struct bus_type contains an rwsem that protects all core accesses to
the device and driver lists. This can be used by the bus driver
internally, and should be used when accessing the device or driver
lists the bus maintains.
lists the bus maintains.
- Device and driver fields.
- Device and driver fields.
Some of the fields in struct device and struct device_driver duplicate
fields in the bus-specific representations of these objects. Feel free
@ -444,4 +446,3 @@ to remove the bus-specific ones and favor the generic ones. Note
though, that this will likely mean fixing up all the drivers that
reference the bus-specific fields (though those should all be 1-line
changes).

View File

@ -103,7 +103,7 @@ id_table an array of NULL terminated EISA id strings,
(driver_data).
driver a generic driver, such as described in
Documentation/driver-model/driver.txt. Only .name,
Documentation/driver-model/driver.rst. Only .name,
.probe and .remove members are mandatory.
=============== ====================================================
@ -152,7 +152,7 @@ state set of flags indicating the state of the device. Current
flags are EISA_CONFIG_ENABLED and EISA_CONFIG_FORCED.
res set of four 256 bytes I/O regions allocated to this device
dma_mask DMA mask set from the parent device.
dev generic device (see Documentation/driver-model/device.txt)
dev generic device (see Documentation/driver-model/device.rst)
======== ============================================================
You can get the 'struct eisa_device' from 'struct device' using the

View File

@ -169,7 +169,7 @@ byte offsets over a base for the register block.
If you want to dump an u32 array in debugfs, you can create file with:
struct dentry *debugfs_create_u32_array(const char *name, umode_t mode,
void debugfs_create_u32_array(const char *name, umode_t mode,
struct dentry *parent,
u32 *array, u32 elements);

View File

@ -89,7 +89,7 @@ increase the chances of your change being accepted.
console. Excessive logging can seriously affect system performance.
* Use devres functions whenever possible to allocate resources. For rationale
and supported functions, please see Documentation/driver-model/devres.txt.
and supported functions, please see Documentation/driver-model/devres.rst.
If a function is not supported by devres, consider using devm_add_action().
* If the driver has a detect function, make sure it is silent. Debug messages

View File

@ -21,13 +21,10 @@ struct ptdump_info {
void ptdump_walk_pgd(struct seq_file *s, struct ptdump_info *info);
#ifdef CONFIG_ARM_PTDUMP_DEBUGFS
int ptdump_debugfs_register(struct ptdump_info *info, const char *name);
void ptdump_debugfs_register(struct ptdump_info *info, const char *name);
#else
static inline int ptdump_debugfs_register(struct ptdump_info *info,
const char *name)
{
return 0;
}
static inline void ptdump_debugfs_register(struct ptdump_info *info,
const char *name) { }
#endif /* CONFIG_ARM_PTDUMP_DEBUGFS */
void ptdump_check_wx(void);

View File

@ -987,84 +987,44 @@ static int debug_clock_show(struct seq_file *s, void *unused)
DEFINE_SHOW_ATTRIBUTE(debug_clock);
static int clk_debugfs_register_one(struct clk *c)
static void clk_debugfs_register_one(struct clk *c)
{
int err;
struct dentry *d;
struct clk *pa = c->parent;
d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
if (!d)
return -ENOMEM;
c->dent = d;
d = debugfs_create_u8("usecount", S_IRUGO, c->dent, &c->usecount);
if (!d) {
err = -ENOMEM;
goto err_out;
}
d = debugfs_create_ulong("rate", S_IRUGO, c->dent, &c->rate);
if (!d) {
err = -ENOMEM;
goto err_out;
}
d = debugfs_create_x8("flags", S_IRUGO, c->dent, &c->flags);
if (!d) {
err = -ENOMEM;
goto err_out;
}
return 0;
err_out:
debugfs_remove_recursive(c->dent);
return err;
debugfs_create_u8("usecount", S_IRUGO, c->dent, &c->usecount);
debugfs_create_ulong("rate", S_IRUGO, c->dent, &c->rate);
debugfs_create_x8("flags", S_IRUGO, c->dent, &c->flags);
}
static int clk_debugfs_register(struct clk *c)
static void clk_debugfs_register(struct clk *c)
{
int err;
struct clk *pa = c->parent;
if (pa && !pa->dent) {
err = clk_debugfs_register(pa);
if (err)
return err;
}
if (pa && !pa->dent)
clk_debugfs_register(pa);
if (!c->dent) {
err = clk_debugfs_register_one(c);
if (err)
return err;
}
return 0;
if (!c->dent)
clk_debugfs_register_one(c);
}
static int __init clk_debugfs_init(void)
{
struct clk *c;
struct dentry *d;
int err;
d = debugfs_create_dir("clock", NULL);
if (!d)
return -ENOMEM;
clk_debugfs_root = d;
list_for_each_entry(c, &clocks, node) {
err = clk_debugfs_register(c);
if (err)
goto err_out;
}
list_for_each_entry(c, &clocks, node)
clk_debugfs_register(c);
d = debugfs_create_file("summary", S_IRUGO,
d, NULL, &debug_clock_fops);
if (!d)
return -ENOMEM;
debugfs_create_file("summary", S_IRUGO, d, NULL, &debug_clock_fops);
return 0;
err_out:
debugfs_remove_recursive(clk_debugfs_root);
return err;
}
late_initcall(clk_debugfs_init);

View File

@ -539,11 +539,8 @@ static void omap_pm_init_debugfs(void)
struct dentry *d;
d = debugfs_create_dir("pm_debug", NULL);
if (!d)
return;
(void) debugfs_create_file("omap_pm", S_IWUSR | S_IRUGO,
d, NULL, &omap_pm_debug_fops);
debugfs_create_file("omap_pm", S_IWUSR | S_IRUGO, d, NULL,
&omap_pm_debug_fops);
}
#endif /* CONFIG_DEBUG_FS */

View File

@ -190,9 +190,8 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
return 0;
d = debugfs_create_dir(pwrdm->name, (struct dentry *)dir);
if (d)
(void) debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d,
(void *)pwrdm, &pwrdm_suspend_fops);
debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d, pwrdm,
&pwrdm_suspend_fops);
return 0;
}
@ -230,16 +229,14 @@ static int __init pm_dbg_init(void)
return 0;
d = debugfs_create_dir("pm_debug", NULL);
if (!d)
return -EINVAL;
(void) debugfs_create_file("count", 0444, d, NULL, &pm_dbg_counters_fops);
(void) debugfs_create_file("time", 0444, d, NULL, &pm_dbg_timers_fops);
debugfs_create_file("count", 0444, d, NULL, &pm_dbg_counters_fops);
debugfs_create_file("time", 0444, d, NULL, &pm_dbg_timers_fops);
pwrdm_for_each(pwrdms_setup, (void *)d);
(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
&enable_off_mode, &pm_dbg_option_fops);
debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
&enable_off_mode, &pm_dbg_option_fops);
pm_dbg_init_done = 1;
return 0;

View File

@ -446,7 +446,7 @@ void ptdump_check_wx(void)
static int ptdump_init(void)
{
ptdump_initialize();
return ptdump_debugfs_register(&kernel_ptdump_info,
"kernel_page_tables");
ptdump_debugfs_register(&kernel_ptdump_info, "kernel_page_tables");
return 0;
}
__initcall(ptdump_init);

View File

@ -24,11 +24,7 @@ static const struct file_operations ptdump_fops = {
.release = single_release,
};
int ptdump_debugfs_register(struct ptdump_info *info, const char *name)
void ptdump_debugfs_register(struct ptdump_info *info, const char *name)
{
struct dentry *pe;
pe = debugfs_create_file(name, 0400, NULL, info, &ptdump_fops);
return pe ? 0 : -ENOMEM;
debugfs_create_file(name, 0400, NULL, info, &ptdump_fops);
}

View File

@ -147,13 +147,13 @@ static const struct dma_map_ops ibmebus_dma_ops = {
.unmap_page = ibmebus_unmap_page,
};
static int ibmebus_match_path(struct device *dev, void *data)
static int ibmebus_match_path(struct device *dev, const void *data)
{
struct device_node *dn = to_platform_device(dev)->dev.of_node;
return (of_find_node_by_path(data) == dn);
}
static int ibmebus_match_node(struct device *dev, void *data)
static int ibmebus_match_node(struct device *dev, const void *data)
{
return to_platform_device(dev)->dev.of_node == data;
}

View File

@ -9,9 +9,6 @@ EXPORT_SYMBOL(arch_debugfs_dir);
static int __init arch_kdebugfs_init(void)
{
arch_debugfs_dir = debugfs_create_dir("sh", NULL);
if (!arch_debugfs_dir)
return -ENOMEM;
return 0;
}
arch_initcall(arch_kdebugfs_init);

View File

@ -63,13 +63,8 @@ static const struct file_operations asids_debugfs_fops = {
static int __init asids_debugfs_init(void)
{
struct dentry *asids_dentry;
asids_dentry = debugfs_create_file("asids", S_IRUSR, arch_debugfs_dir,
NULL, &asids_debugfs_fops);
if (!asids_dentry)
return -ENOMEM;
return PTR_ERR_OR_ZERO(asids_dentry);
debugfs_create_file("asids", S_IRUSR, arch_debugfs_dir, NULL,
&asids_debugfs_fops);
return 0;
}
device_initcall(asids_debugfs_init);

View File

@ -109,22 +109,10 @@ static const struct file_operations cache_debugfs_fops = {
static int __init cache_debugfs_init(void)
{
struct dentry *dcache_dentry, *icache_dentry;
dcache_dentry = debugfs_create_file("dcache", S_IRUSR, arch_debugfs_dir,
(unsigned int *)CACHE_TYPE_DCACHE,
&cache_debugfs_fops);
if (!dcache_dentry)
return -ENOMEM;
icache_dentry = debugfs_create_file("icache", S_IRUSR, arch_debugfs_dir,
(unsigned int *)CACHE_TYPE_ICACHE,
&cache_debugfs_fops);
if (!icache_dentry) {
debugfs_remove(dcache_dentry);
return -ENOMEM;
}
debugfs_create_file("dcache", S_IRUSR, arch_debugfs_dir,
(void *)CACHE_TYPE_DCACHE, &cache_debugfs_fops);
debugfs_create_file("icache", S_IRUSR, arch_debugfs_dir,
(void *)CACHE_TYPE_ICACHE, &cache_debugfs_fops);
return 0;
}
module_init(cache_debugfs_init);

View File

@ -861,13 +861,8 @@ static const struct file_operations pmb_debugfs_fops = {
static int __init pmb_debugfs_init(void)
{
struct dentry *dentry;
dentry = debugfs_create_file("pmb", S_IFREG | S_IRUGO,
arch_debugfs_dir, NULL, &pmb_debugfs_fops);
if (!dentry)
return -ENOMEM;
debugfs_create_file("pmb", S_IFREG | S_IRUGO, arch_debugfs_dir, NULL,
&pmb_debugfs_fops);
return 0;
}
subsys_initcall(pmb_debugfs_init);

View File

@ -149,22 +149,10 @@ static const struct file_operations tlb_debugfs_fops = {
static int __init tlb_debugfs_init(void)
{
struct dentry *itlb, *utlb;
itlb = debugfs_create_file("itlb", S_IRUSR, arch_debugfs_dir,
(unsigned int *)TLB_TYPE_ITLB,
&tlb_debugfs_fops);
if (unlikely(!itlb))
return -ENOMEM;
utlb = debugfs_create_file("utlb", S_IRUSR, arch_debugfs_dir,
(unsigned int *)TLB_TYPE_UTLB,
&tlb_debugfs_fops);
if (unlikely(!utlb)) {
debugfs_remove(itlb);
return -ENOMEM;
}
debugfs_create_file("itlb", S_IRUSR, arch_debugfs_dir,
(void *)TLB_TYPE_ITLB, &tlb_debugfs_fops);
debugfs_create_file("utlb", S_IRUSR, arch_debugfs_dir,
(void *)TLB_TYPE_UTLB, &tlb_debugfs_fops);
return 0;
}
module_init(tlb_debugfs_init);

View File

@ -67,33 +67,18 @@ static const struct file_operations fops_setup_data = {
.llseek = default_llseek,
};
static int __init
static void __init
create_setup_data_node(struct dentry *parent, int no,
struct setup_data_node *node)
{
struct dentry *d, *type, *data;
struct dentry *d;
char buf[16];
sprintf(buf, "%d", no);
d = debugfs_create_dir(buf, parent);
if (!d)
return -ENOMEM;
type = debugfs_create_x32("type", S_IRUGO, d, &node->type);
if (!type)
goto err_dir;
data = debugfs_create_file("data", S_IRUGO, d, node, &fops_setup_data);
if (!data)
goto err_type;
return 0;
err_type:
debugfs_remove(type);
err_dir:
debugfs_remove(d);
return -ENOMEM;
debugfs_create_x32("type", S_IRUGO, d, &node->type);
debugfs_create_file("data", S_IRUGO, d, node, &fops_setup_data);
}
static int __init create_setup_data_nodes(struct dentry *parent)
@ -106,8 +91,6 @@ static int __init create_setup_data_nodes(struct dentry *parent)
int no = 0;
d = debugfs_create_dir("setup_data", parent);
if (!d)
return -ENOMEM;
pa_data = boot_params.hdr.setup_data;
@ -128,19 +111,17 @@ static int __init create_setup_data_nodes(struct dentry *parent)
node->paddr = pa_data;
node->type = data->type;
node->len = data->len;
error = create_setup_data_node(d, no, node);
create_setup_data_node(d, no, node);
pa_data = data->next;
memunmap(data);
if (error)
goto err_dir;
no++;
}
return 0;
err_dir:
debugfs_remove(d);
debugfs_remove_recursive(d);
return error;
}
@ -151,35 +132,18 @@ static struct debugfs_blob_wrapper boot_params_blob = {
static int __init boot_params_kdebugfs_init(void)
{
struct dentry *dbp, *version, *data;
int error = -ENOMEM;
struct dentry *dbp;
int error;
dbp = debugfs_create_dir("boot_params", arch_debugfs_dir);
if (!dbp)
return -ENOMEM;
version = debugfs_create_x16("version", S_IRUGO, dbp,
&boot_params.hdr.version);
if (!version)
goto err_dir;
data = debugfs_create_blob("data", S_IRUGO, dbp,
&boot_params_blob);
if (!data)
goto err_version;
debugfs_create_x16("version", S_IRUGO, dbp, &boot_params.hdr.version);
debugfs_create_blob("data", S_IRUGO, dbp, &boot_params_blob);
error = create_setup_data_nodes(dbp);
if (error)
goto err_data;
debugfs_remove_recursive(dbp);
return 0;
err_data:
debugfs_remove(data);
err_version:
debugfs_remove(version);
err_dir:
debugfs_remove(dbp);
return error;
}
#endif /* CONFIG_DEBUG_BOOT_PARAMS */
@ -189,8 +153,6 @@ static int __init arch_kdebugfs_init(void)
int error = 0;
arch_debugfs_dir = debugfs_create_dir("x86", NULL);
if (!arch_debugfs_dir)
return -ENOMEM;
#ifdef CONFIG_DEBUG_BOOT_PARAMS
error = boot_params_kdebugfs_init();

View File

@ -26,8 +26,6 @@ static int ptdump_curknl_show(struct seq_file *m, void *v)
DEFINE_SHOW_ATTRIBUTE(ptdump_curknl);
#ifdef CONFIG_PAGE_TABLE_ISOLATION
static struct dentry *pe_curusr;
static int ptdump_curusr_show(struct seq_file *m, void *v)
{
if (current->mm->pgd) {
@ -42,8 +40,6 @@ DEFINE_SHOW_ATTRIBUTE(ptdump_curusr);
#endif
#if defined(CONFIG_EFI) && defined(CONFIG_X86_64)
static struct dentry *pe_efi;
static int ptdump_efi_show(struct seq_file *m, void *v)
{
if (efi_mm.pgd)
@ -54,41 +50,24 @@ static int ptdump_efi_show(struct seq_file *m, void *v)
DEFINE_SHOW_ATTRIBUTE(ptdump_efi);
#endif
static struct dentry *dir, *pe_knl, *pe_curknl;
static struct dentry *dir;
static int __init pt_dump_debug_init(void)
{
dir = debugfs_create_dir("page_tables", NULL);
if (!dir)
return -ENOMEM;
pe_knl = debugfs_create_file("kernel", 0400, dir, NULL,
&ptdump_fops);
if (!pe_knl)
goto err;
pe_curknl = debugfs_create_file("current_kernel", 0400,
dir, NULL, &ptdump_curknl_fops);
if (!pe_curknl)
goto err;
debugfs_create_file("kernel", 0400, dir, NULL, &ptdump_fops);
debugfs_create_file("current_kernel", 0400, dir, NULL,
&ptdump_curknl_fops);
#ifdef CONFIG_PAGE_TABLE_ISOLATION
pe_curusr = debugfs_create_file("current_user", 0400,
dir, NULL, &ptdump_curusr_fops);
if (!pe_curusr)
goto err;
debugfs_create_file("current_user", 0400, dir, NULL,
&ptdump_curusr_fops);
#endif
#if defined(CONFIG_EFI) && defined(CONFIG_X86_64)
pe_efi = debugfs_create_file("efi", 0400, dir, NULL, &ptdump_efi_fops);
if (!pe_efi)
goto err;
debugfs_create_file("efi", 0400, dir, NULL, &ptdump_efi_fops);
#endif
return 0;
err:
debugfs_remove_recursive(dir);
return -ENOMEM;
}
static void __exit pt_dump_debug_exit(void)

View File

@ -104,24 +104,12 @@ DEFINE_SHOW_ATTRIBUTE(punit_dev_state);
static struct dentry *punit_dbg_file;
static int punit_dbgfs_register(struct punit_device *punit_device)
static void punit_dbgfs_register(struct punit_device *punit_device)
{
struct dentry *dev_state;
punit_dbg_file = debugfs_create_dir("punit_atom", NULL);
if (!punit_dbg_file)
return -ENXIO;
dev_state = debugfs_create_file("dev_power_state", 0444,
punit_dbg_file, punit_device,
&punit_dev_state_fops);
if (!dev_state) {
pr_err("punit_dev_state register failed\n");
debugfs_remove(punit_dbg_file);
return -ENXIO;
}
return 0;
debugfs_create_file("dev_power_state", 0444, punit_dbg_file,
punit_device, &punit_dev_state_fops);
}
static void punit_dbgfs_unregister(void)
@ -145,15 +133,12 @@ MODULE_DEVICE_TABLE(x86cpu, intel_punit_cpu_ids);
static int __init punit_atom_debug_init(void)
{
const struct x86_cpu_id *id;
int ret;
id = x86_match_cpu(intel_punit_cpu_ids);
if (!id)
return -ENODEV;
ret = punit_dbgfs_register((struct punit_device *)id->driver_data);
if (ret < 0)
return ret;
punit_dbgfs_register((struct punit_device *)id->driver_data);
return 0;
}

View File

@ -35,7 +35,6 @@
#include <linux/types.h>
struct imr_device {
struct dentry *file;
bool init;
struct mutex lock;
int max_imr;
@ -231,13 +230,11 @@ DEFINE_SHOW_ATTRIBUTE(imr_dbgfs_state);
* imr_debugfs_register - register debugfs hooks.
*
* @idev: pointer to imr_device structure.
* @return: 0 on success - errno on failure.
*/
static int imr_debugfs_register(struct imr_device *idev)
static void imr_debugfs_register(struct imr_device *idev)
{
idev->file = debugfs_create_file("imr_state", 0444, NULL, idev,
&imr_dbgfs_state_fops);
return PTR_ERR_OR_ZERO(idev->file);
debugfs_create_file("imr_state", 0444, NULL, idev,
&imr_dbgfs_state_fops);
}
/**
@ -582,7 +579,6 @@ static const struct x86_cpu_id imr_ids[] __initconst = {
static int __init imr_init(void)
{
struct imr_device *idev = &imr_dev;
int ret;
if (!x86_match_cpu(imr_ids) || !iosf_mbi_available())
return -ENODEV;
@ -592,9 +588,7 @@ static int __init imr_init(void)
idev->init = true;
mutex_init(&idev->lock);
ret = imr_debugfs_register(idev);
if (ret != 0)
pr_warn("debugfs register failed!\n");
imr_debugfs_register(idev);
imr_fixup_memmap(idev);
return 0;
}

View File

@ -461,31 +461,16 @@ static struct dentry *iosf_dbg;
static void iosf_sideband_debug_init(void)
{
struct dentry *d;
iosf_dbg = debugfs_create_dir("iosf_sb", NULL);
if (IS_ERR_OR_NULL(iosf_dbg))
return;
/* mdr */
d = debugfs_create_x32("mdr", 0660, iosf_dbg, &dbg_mdr);
if (!d)
goto cleanup;
debugfs_create_x32("mdr", 0660, iosf_dbg, &dbg_mdr);
/* mcrx */
d = debugfs_create_x32("mcrx", 0660, iosf_dbg, &dbg_mcrx);
if (!d)
goto cleanup;
debugfs_create_x32("mcrx", 0660, iosf_dbg, &dbg_mcrx);
/* mcr - initiates mailbox tranaction */
d = debugfs_create_file("mcr", 0660, iosf_dbg, &dbg_mcr, &iosf_mcr_fops);
if (!d)
goto cleanup;
return;
cleanup:
debugfs_remove_recursive(d);
debugfs_create_file("mcr", 0660, iosf_dbg, &dbg_mcr, &iosf_mcr_fops);
}
static void iosf_debugfs_init(void)

View File

@ -66,7 +66,6 @@ static struct tunables tunables[] = {
};
static struct dentry *tunables_dir;
static struct dentry *tunables_file;
/* these correspond to the statistics printed by ptc_seq_show() */
static char *stat_description[] = {
@ -1700,18 +1699,8 @@ static int __init uv_ptc_init(void)
}
tunables_dir = debugfs_create_dir(UV_BAU_TUNABLES_DIR, NULL);
if (!tunables_dir) {
pr_err("unable to create debugfs directory %s\n",
UV_BAU_TUNABLES_DIR);
return -EINVAL;
}
tunables_file = debugfs_create_file(UV_BAU_TUNABLES_FILE, 0600,
tunables_dir, NULL, &tunables_fops);
if (!tunables_file) {
pr_err("unable to create debugfs file %s\n",
UV_BAU_TUNABLES_FILE);
return -EINVAL;
}
debugfs_create_file(UV_BAU_TUNABLES_FILE, 0600, tunables_dir, NULL,
&tunables_fops);
return 0;
}

View File

@ -9,13 +9,8 @@ static struct dentry *d_xen_debug;
struct dentry * __init xen_init_debugfs(void)
{
if (!d_xen_debug) {
if (!d_xen_debug)
d_xen_debug = debugfs_create_dir("xen", NULL);
if (!d_xen_debug)
pr_warning("Could not create 'xen' debugfs directory\n");
}
return d_xen_debug;
}

View File

@ -817,9 +817,6 @@ static int __init xen_p2m_debugfs(void)
{
struct dentry *d_xen = xen_init_debugfs();
if (d_xen == NULL)
return -ENOMEM;
d_mmu_debug = debugfs_create_dir("mmu", d_xen);
debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops);

View File

@ -508,10 +508,10 @@ struct hid_uid {
const char *uid;
};
static int match_hid_uid(struct device *dev, void *data)
static int match_hid_uid(struct device *dev, const void *data)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
struct hid_uid *id = data;
const struct hid_uid *id = data;
if (!adev)
return 0;

View File

@ -725,17 +725,15 @@ bool acpi_dev_found(const char *hid)
EXPORT_SYMBOL(acpi_dev_found);
struct acpi_dev_match_info {
const char *dev_name;
struct acpi_device *adev;
struct acpi_device_id hid[2];
const char *uid;
s64 hrv;
};
static int acpi_dev_match_cb(struct device *dev, void *data)
static int acpi_dev_match_cb(struct device *dev, const void *data)
{
struct acpi_device *adev = to_acpi_device(dev);
struct acpi_dev_match_info *match = data;
const struct acpi_dev_match_info *match = data;
unsigned long long hrv;
acpi_status status;
@ -746,9 +744,6 @@ static int acpi_dev_match_cb(struct device *dev, void *data)
strcmp(adev->pnp.unique_id, match->uid)))
return 0;
match->dev_name = acpi_dev_name(adev);
match->adev = adev;
if (match->hrv == -1)
return 1;
@ -818,7 +813,7 @@ acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
match.hrv = hrv;
dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
return dev ? match.adev : NULL;
return dev ? to_acpi_device(dev) : NULL;
}
EXPORT_SYMBOL(acpi_dev_get_first_match_dev);

View File

@ -134,10 +134,10 @@ static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset)
}
#ifdef CONFIG_TEGRA_IOMMU_SMMU
static int tegra_ahb_match_by_smmu(struct device *dev, void *data)
static int tegra_ahb_match_by_smmu(struct device *dev, const void *data)
{
struct tegra_ahb *ahb = dev_get_drvdata(dev);
struct device_node *dn = data;
const struct device_node *dn = data;
return (ahb->dev->of_node == dn) ? 1 : 0;
}

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 @@ static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj,
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.
*/

View File

@ -2819,9 +2819,9 @@ static const struct device_type bmc_device_type = {
.groups = bmc_dev_attr_groups,
};
static int __find_bmc_guid(struct device *dev, void *data)
static int __find_bmc_guid(struct device *dev, const void *data)
{
guid_t *guid = data;
const guid_t *guid = data;
struct bmc_device *bmc;
int rv;
@ -2857,9 +2857,9 @@ struct prod_dev_id {
unsigned char device_id;
};
static int __find_bmc_prod_dev_id(struct device *dev, void *data)
static int __find_bmc_prod_dev_id(struct device *dev, const void *data)
{
struct prod_dev_id *cid = data;
const struct prod_dev_id *cid = data;
struct bmc_device *bmc;
int rv;

View File

@ -426,7 +426,7 @@ static int ipmi_remove(struct platform_device *pdev)
return ipmi_si_remove_by_dev(&pdev->dev);
}
static int pdev_match_name(struct device *dev, void *data)
static int pdev_match_name(struct device *dev, const void *data)
{
struct platform_device *pdev = to_platform_device(dev);
const char *name = data;

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
/*
* System Control and Management Interface (SCMI) Message Protocol
* driver common header file containing some definitions, structures

View File

@ -17,9 +17,9 @@ struct acpi_hid_uid {
char uid[11]; /* UINT_MAX + null byte */
};
static int __init match_acpi_dev(struct device *dev, void *data)
static int __init match_acpi_dev(struct device *dev, const void *data)
{
struct acpi_hid_uid hid_uid = *(struct acpi_hid_uid *)data;
struct acpi_hid_uid hid_uid = *(const struct acpi_hid_uid *)data;
struct acpi_device *adev = to_acpi_device(dev);
if (acpi_match_device_ids(adev, hid_uid.hid))

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: BSD-3-Clause
/* SPDX-License-Identifier: BSD-3-Clause */
/*
* Texas Instruments System Control Interface (TISCI) Protocol
*

View File

@ -22,11 +22,6 @@ static const struct of_device_id fpga_region_of_match[] = {
};
MODULE_DEVICE_TABLE(of, fpga_region_of_match);
static int fpga_region_of_node_match(struct device *dev, const void *data)
{
return dev->of_node == data;
}
/**
* of_fpga_region_find - find FPGA region
* @np: device node of FPGA Region
@ -37,7 +32,7 @@ static int fpga_region_of_node_match(struct device *dev, const void *data)
*/
static struct fpga_region *of_fpga_region_find(struct device_node *np)
{
return fpga_region_class_find(NULL, np, fpga_region_of_node_match);
return fpga_region_class_find(NULL, np, device_match_of_node);
}
/**

View File

@ -41,7 +41,7 @@ MODULE_PARM_DESC(mask, "GPIO channel mask.");
/*
* FIXME: convert this singleton driver to use the state container
* design pattern, see Documentation/driver-model/design-patterns.txt
* design pattern, see Documentation/driver-model/design-patterns.rst
*/
static struct cs5535_gpio_chip {
struct gpio_chip chip;

View File

@ -93,7 +93,7 @@ static struct bus_type mipi_dsi_bus_type = {
.pm = &mipi_dsi_device_pm_ops,
};
static int of_device_match(struct device *dev, void *data)
static int of_device_match(struct device *dev, const void *data)
{
return dev->of_node == data;
}

View File

@ -2372,10 +2372,10 @@ static int tegra_dc_parse_dt(struct tegra_dc *dc)
return 0;
}
static int tegra_dc_match_by_pipe(struct device *dev, void *data)
static int tegra_dc_match_by_pipe(struct device *dev, const void *data)
{
struct tegra_dc *dc = dev_get_drvdata(dev);
unsigned int pipe = (unsigned long)data;
unsigned int pipe = (unsigned long)(void *)data;
return dc->pipe == pipe;
}

View File

@ -525,23 +525,12 @@ static const struct file_operations debug_func_knob_fops = {
static int debug_func_init(void)
{
struct dentry *file;
int ret;
/* Create debugfs node */
debug_debugfs_dir = debugfs_create_dir("coresight_cpu_debug", NULL);
if (!debug_debugfs_dir) {
pr_err("%s: unable to create debugfs directory\n", __func__);
return -ENOMEM;
}
file = debugfs_create_file("enable", 0644, debug_debugfs_dir, NULL,
&debug_func_knob_fops);
if (!file) {
pr_err("%s: unable to create enable knob file\n", __func__);
ret = -ENOMEM;
goto err;
}
debugfs_create_file("enable", 0644, debug_debugfs_dir, NULL,
&debug_func_knob_fops);
/* Register function to be called for panic */
ret = atomic_notifier_chain_register(&panic_notifier_list,

View File

@ -37,7 +37,7 @@ static int coresight_alloc_conns(struct device *dev,
return 0;
}
int coresight_device_fwnode_match(struct device *dev, void *fwnode)
int coresight_device_fwnode_match(struct device *dev, const void *fwnode)
{
return dev_fwnode(dev) == fwnode;
}

View File

@ -498,9 +498,9 @@ struct coresight_device *coresight_get_sink(struct list_head *path)
return csdev;
}
static int coresight_enabled_sink(struct device *dev, void *data)
static int coresight_enabled_sink(struct device *dev, const void *data)
{
bool *reset = data;
const bool *reset = data;
struct coresight_device *csdev = to_coresight_device(dev);
if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
@ -544,7 +544,7 @@ struct coresight_device *coresight_get_enabled_sink(bool deactivate)
return dev ? to_coresight_device(dev) : NULL;
}
static int coresight_sink_by_id(struct device *dev, void *data)
static int coresight_sink_by_id(struct device *dev, const void *data)
{
struct coresight_device *csdev = to_coresight_device(dev);
unsigned long hash;

View File

@ -789,10 +789,9 @@ static int intel_th_populate(struct intel_th *th)
return 0;
}
static int match_devt(struct device *dev, void *data)
static int match_devt(struct device *dev, const void *data)
{
dev_t devt = (dev_t)(unsigned long)data;
dev_t devt = (dev_t)(unsigned long)(void *)data;
return dev->devt == devt;
}

View File

@ -457,7 +457,7 @@ static struct pci_driver amd_mp2_pci_driver = {
};
module_pci_driver(amd_mp2_pci_driver);
static int amd_mp2_device_match(struct device *dev, void *data)
static int amd_mp2_device_match(struct device *dev, const void *data)
{
return 1;
}

View File

@ -320,7 +320,7 @@ u32 i2c_acpi_find_bus_speed(struct device *dev)
}
EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed);
static int i2c_acpi_find_match_adapter(struct device *dev, void *data)
static int i2c_acpi_find_match_adapter(struct device *dev, const void *data)
{
struct i2c_adapter *adapter = i2c_verify_adapter(dev);
@ -330,7 +330,7 @@ static int i2c_acpi_find_match_adapter(struct device *dev, void *data)
return ACPI_HANDLE(dev) == (acpi_handle)data;
}
static int i2c_acpi_find_match_device(struct device *dev, void *data)
static int i2c_acpi_find_match_device(struct device *dev, const void *data)
{
return ACPI_COMPANION(dev) == data;
}

View File

@ -112,12 +112,12 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
of_node_put(bus);
}
static int of_dev_node_match(struct device *dev, void *data)
static int of_dev_node_match(struct device *dev, const void *data)
{
return dev->of_node == data;
}
static int of_dev_or_parent_node_match(struct device *dev, void *data)
static int of_dev_or_parent_node_match(struct device *dev, const void *data)
{
if (dev->of_node == data)
return 1;

View File

@ -90,7 +90,7 @@ static const struct iio_chan_spec
#ifdef CONFIG_OF
static int iio_dev_node_match(struct device *dev, void *data)
static int iio_dev_node_match(struct device *dev, const void *data)
{
return dev->of_node == data && dev->type == &iio_device_type;
}

View File

@ -4498,7 +4498,7 @@ static const struct acpi_device_id hns_roce_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, hns_roce_acpi_match);
static int hns_roce_node_match(struct device *dev, void *fwnode)
static int hns_roce_node_match(struct device *dev, const void *fwnode)
{
return dev->fwnode == fwnode;
}

View File

@ -2034,7 +2034,7 @@ arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
static struct platform_driver arm_smmu_driver;
static int arm_smmu_match_node(struct device *dev, void *data)
static int arm_smmu_match_node(struct device *dev, const void *data)
{
return dev->fwnode == data;
}

View File

@ -1426,7 +1426,7 @@ static bool arm_smmu_capable(enum iommu_cap cap)
}
}
static int arm_smmu_match_node(struct device *dev, void *data)
static int arm_smmu_match_node(struct device *dev, const void *data)
{
return dev->fwnode == data;
}

View File

@ -296,8 +296,6 @@ struct flexrm_mbox {
struct dma_pool *bd_pool;
struct dma_pool *cmpl_pool;
struct dentry *root;
struct dentry *config;
struct dentry *stats;
struct mbox_controller controller;
};
@ -1603,7 +1601,6 @@ static int flexrm_mbox_probe(struct platform_device *pdev)
1 << RING_CMPL_ALIGN_ORDER, 0);
if (!mbox->cmpl_pool) {
ret = -ENOMEM;
goto fail_destroy_bd_pool;
}
/* Allocate platform MSIs for each ring */
@ -1624,28 +1621,15 @@ static int flexrm_mbox_probe(struct platform_device *pdev)
/* Create debugfs root entry */
mbox->root = debugfs_create_dir(dev_name(mbox->dev), NULL);
if (IS_ERR_OR_NULL(mbox->root)) {
ret = PTR_ERR_OR_ZERO(mbox->root);
goto fail_free_msis;
}
/* Create debugfs config entry */
mbox->config = debugfs_create_devm_seqfile(mbox->dev,
"config", mbox->root,
flexrm_debugfs_conf_show);
if (IS_ERR_OR_NULL(mbox->config)) {
ret = PTR_ERR_OR_ZERO(mbox->config);
goto fail_free_debugfs_root;
}
debugfs_create_devm_seqfile(mbox->dev, "config", mbox->root,
flexrm_debugfs_conf_show);
/* Create debugfs stats entry */
mbox->stats = debugfs_create_devm_seqfile(mbox->dev,
"stats", mbox->root,
flexrm_debugfs_stats_show);
if (IS_ERR_OR_NULL(mbox->stats)) {
ret = PTR_ERR_OR_ZERO(mbox->stats);
goto fail_free_debugfs_root;
}
debugfs_create_devm_seqfile(mbox->dev, "stats", mbox->root,
flexrm_debugfs_stats_show);
skip_debugfs:
/* Initialize mailbox controller */
@ -1676,11 +1660,9 @@ static int flexrm_mbox_probe(struct platform_device *pdev)
fail_free_debugfs_root:
debugfs_remove_recursive(mbox->root);
fail_free_msis:
platform_msi_domain_free_irqs(dev);
fail_destroy_cmpl_pool:
dma_pool_destroy(mbox->cmpl_pool);
fail_destroy_bd_pool:
dma_pool_destroy(mbox->bd_pool);
fail:
return ret;

View File

@ -395,8 +395,6 @@ struct pdc_state {
*/
struct scatterlist *src_sg[PDC_RING_ENTRIES];
struct dentry *debugfs_stats; /* debug FS stats file for this PDC */
/* counters */
u32 pdc_requests; /* number of request messages submitted */
u32 pdc_replies; /* number of reply messages received */
@ -501,9 +499,8 @@ static void pdc_setup_debugfs(struct pdc_state *pdcs)
debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
/* S_IRUSR == 0400 */
pdcs->debugfs_stats = debugfs_create_file(spu_stats_name, 0400,
debugfs_dir, pdcs,
&pdc_debugfs_stats);
debugfs_create_file(spu_stats_name, 0400, debugfs_dir, pdcs,
&pdc_debugfs_stats);
}
static void pdc_free_debugfs(void)
@ -1603,7 +1600,6 @@ static int pdc_probe(struct platform_device *pdev)
if (err)
goto cleanup_buf_pool;
pdcs->debugfs_stats = NULL;
pdc_setup_debugfs(pdcs);
dev_dbg(dev, "pdc_probe() successful");

View File

@ -92,9 +92,9 @@ static struct regmap_config altr_sysmgr_regmap_cfg = {
* Matching function used by driver_find_device().
* Return: True if match is found, otherwise false.
*/
static int sysmgr_match_phandle(struct device *dev, void *data)
static int sysmgr_match_phandle(struct device *dev, const void *data)
{
return dev->of_node == (struct device_node *)data;
return dev->of_node == (const struct device_node *)data;
}
/**

View File

@ -190,27 +190,6 @@ struct regmap *syscon_regmap_lookup_by_compatible(const char *s)
}
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible);
static int syscon_match_pdevname(struct device *dev, void *data)
{
return !strcmp(dev_name(dev), (const char *)data);
}
struct regmap *syscon_regmap_lookup_by_pdevname(const char *s)
{
struct device *dev;
struct syscon *syscon;
dev = driver_find_device(&syscon_driver.driver, NULL, (void *)s,
syscon_match_pdevname);
if (!dev)
return ERR_PTR(-EPROBE_DEFER);
syscon = dev_get_drvdata(dev);
return syscon->regmap;
}
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_pdevname);
struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
const char *property)
{

Some files were not shown because too many files have changed in this diff Show More